NodeJs / Javascript 를 활용한 네이버 지식인 오토 자동 댓글 / 답글 프로그램
프로그램 구동 로직
1. 네이버 로그인
2. 원하는 키워드 입력
3. 해당 키워드 관련 지식인 탭 내 모든 질문 한개씩 접속
4. 미리 입력한 댓글 자동 입력 후 업로드
5. 다음글에 접속 후 위 3,4 과정 반복
네이버 지식인 하루 댓글 작성 개수가
한정되어있는 것으로 알고 있는데
몇개 까지 달수 있는지에 대해 정확히 몰라서
프로그램 사용자가 직접 원하는 댓글 개수를
입력할수 있도록 만들어 보았다
프로그램 설치 및 사용 방법
위 프로그램은 소스 코드로 제작을 하였기 때문에
소스 코드를 실행할수 있는 환경의 설치 및 실행이 필요하다
Microsoft VSCode 설치
(하단 링크를 통해 공홈 접속 후 자신의 운영 체제에 맞는 버전 설치)
https://code.visualstudio.com/
NodeJs 설치
(하단 링크를 통해 공식홈페이지 접속 후 자신의 운영체제에 맞는 버전 설치)
프로젝트 생성
자신이 원하는 경로에 프로젝트 (일반 폴더) 생성 후
설치한 VSCode를 실행하여 해당 폴더를 선택한다
NPM 설치
폴더 선택 후 프로젝트 화면에서
터미널을 켠 후 터미널 화면에 아래와 같이 입력한다
터미널 켜는 단축키는
macOs는 ctrl + shift + `키
Window는 ctrl + `키
//생성된 터미널 창에 아래와 같이 입력 후 엔터 (설치시 왼쪽에 폴더 몇개 생성됨)
npm install selenium-webdriver
프로젝트 내 index.js 파일 생성
하단의 스크린 샷과 같이 index.js 파일을 생성한다
자신의 현재 chrome 버전 확인
chrome 브라우저 > 설정 > 왼쪽에 chrome 정보 클릭 시 버전 확인 가능
chrome 자동 드라이버 다운
자신의 브라우저 버전과 똑같은 자동 드라이버 하단 링크 통해서 다운
http://chromedriver.storage.googleapis.com/index.html
chrome 자동 드라이버 이동
다운 받은 크롬 자동 드라이버를 자신의 프로젝트에
드래그 & 드랍을 통해 옮기기
소스 코드 입력
하단의 소스코드를 index.js 내에 복사 / 붙여넣기를 통하여 입력
const { Builder, By, until, Key } = require('selenium-webdriver');
//Information ''내에 정보 입력
const Information = {
nid : '네이버아이디',
npw : '네이버비번',
keyword : '키워드',
comment : '댓글 내용',
count : 30
};
let commentCount = Information.count;
//지식인 자동 댓글
const KinAutoComment = async (nid,npw,keyword,comment) => {
let driver = await new Builder('./chromedriver').forBrowser('chrome').build();
await driver.get('https://www.naver.com');
await driver.wait(until.elementLocated(By.css('#footer')));
//메인 브라우저 값 저장
const defaultHandle = await driver.getWindowHandle();
//console.log('기본 핸들 저장 완료');
//로그인
await Nlogin(driver,nid,npw);
//검색어 입력
await NSearch(driver,keyword);
//지식인 탭 이동
await MoveToKin(driver);
//지식인 댓글 모든 페이지 자동
await KinAutoWritePages(driver,defaultHandle,comment);
//종료
console.log('끝');
await driver.quit();
};
//네이버 로그인
const Nlogin = async (driver,nid,npw)=>{
//로그인
const loginBtn = await driver.findElement(By.css(`a.link_login`));
await loginBtn.click();
//console.log('로그인 화면 전환 완료');
//대기 (아이디 비번)
await driver.wait(until.elementLocated(By.css('#id')));
await driver.wait(until.elementLocated(By.css('#pw')));
//아이디 비번 입력
await driver.executeScript(`
document.querySelector('#id').value = '${nid}';
document.querySelector('#pw').value = '${npw}';
`);
//대기 (로그인 버튼)
await driver.wait(until.elementLocated(By.css('.btn_global')));
//console.log('아이디 비번 입력 완료');
//로그인 버튼 클릭
const loginSubmit = await driver.findElement(By.css(`.btn_global`));
await loginSubmit.click();
//console.log('로그인 버튼 클릭 완료');
//대기 (등록안함 버튼)
await driver.wait(until.elementLocated(By.css('.btn_cancel > .btn')));
//등록안함 버튼 클릭
//아이디 비번 입력
const afterLoginBtn = await driver.findElement(By.css('.btn_cancel > .btn'));
await afterLoginBtn.click();
//console.log('등록안함 버튼 클릭 완료');
}
//네이버 키워드 검색
const NSearch = async (driver,keyword)=>{
//대기 (검색어 입력)
await driver.wait(until.elementLocated(By.css('#query')));
//검색어 입력
const searchTag = driver.findElement(By.css('#query'));
await searchTag.sendKeys(keyword, Key.ENTER);
//console.log(`검색어(${keyword}) 입력 완료`);
}
// 지식인 탭 이동
const MoveToKin = async (driver)=>{
//대기 (탭검색)
await driver.wait(until.elementLocated(By.css('#footer')));
//탭 검색
const menuTab = await driver.findElement(By.css('ul.base'));
const menuItems = await menuTab.findElements(By.css('li.menu a'));
for (let i = 0; i < menuItems.length; i++) {
let inText = await menuItems[i].getText();
if (inText === '지식iN'){
await menuItems[i].click();
break;
}
}
//console.log('지식인 탭 이동 완료');
}
//다음 페이지 존재 여부 확인
const CanMoveNextPage = async(driver) =>{
//대기 (글목록 검색)
await driver.wait(until.elementLocated(By.css('#footer')));
//페이지 검색
let btn_next = await driver.findElement(By.css('.sc_page .btn_next'));
let hasNextPage = await btn_next.getAttribute('aria-disabled');
return hasNextPage;
}
//지식인 페이지 이동
const KinAutoWritePages = async(driver,defaultHandle,comment)=>{
//다음 페이지 존재 여부 확인
let hasNextPage = await CanMoveNextPage(driver);
//지식인 목록 없을시 리턴
if(hasNextPage === 'true') return;
do{
hasNextPage = await CanMoveNextPage(driver);
//대기 (글목록 검색)
await driver.wait(until.elementLocated(By.css('#footer')));
//글목록 검색
let subMenuList = await driver.findElements(By.css(`ul.lst_total._list div.question_group a`));
//지식인 댓글 입력
await CommentToKin(driver,subMenuList,defaultHandle,comment);
//남은 댓글 개수 소진시 리턴
if(commentCount <= 0) break;
//다음 페이지 클릭
await (await driver.findElement(By.css('.sc_page .btn_next'))).click();
}while(hasNextPage !== 'true');
}
//지식인 댓글
const CommentToKin = async (driver,subMenuList,defaultHandle,comment)=>{
//지식인 글
for (let i = 0; i < subMenuList.length; i++) {
//글 제목 출력
let title = await subMenuList[i].getText();
console.log(title);
//글 순차 클릭
await subMenuList[i].click();
//console.log('글 클릭 완료');
//새탭 핸들값 저장 및 핸들 값 새탭으로 변경
let windows = await driver.getAllWindowHandles();
windows.forEach(async handle => {
if (handle !== defaultHandle) {
await driver.switchTo().window(handle);
}
});
//현재 URL 얻기
let currentUrl = await driver.getCurrentUrl();
console.log('현재 URL : '+currentUrl);
//console.log('새탭으로 핸들 변경 / 열기');
//리플 버튼 대기
await driver.wait(until.elementLocated(By.css('.footer_wrap')));
//console.log('리플 버튼 대기');
//리플 버튼 클릭
let replyBtn = await driver.findElement(By.css('i.icon.icon_compose_opinion'));
await replyBtn.click();
//console.log('리플 버튼 클릭');
//글입력 대기
await driver.wait(until.elementLocated(By.css('textarea.c-opinion__write-textarea.placeholder')));
//글입력
await driver.executeScript(`document.querySelector('textarea.c-opinion__write-textarea.placeholder').value='${comment}'`);
//console.log('글입력 완료');
//업로드 버튼 클릭
let btnArea = await driver.findElement(By.css('div.c-opinion__write-upload'));
await (await btnArea.findElement(By.css('button[type="submit"]'))).click();
//console.log('업로드 버튼 클릭 완료');
await driver.sleep(3500);
await driver.close();
//console.log('새탭 닫기 / 핸들 변경');
//기존 핸들 돌아가기
await driver.switchTo().window(defaultHandle);
await driver.sleep(2500);
commentCount--;
console.log(`남은 댓글 개수 : ${commentCount}`);
if(commentCount <= 0) return;
}
}
//지식인 자동 댓글 살행
(async ()=>{
await KinAutoComment(Information.nid,Information.npw,Information.keyword,Information.count);
})();
터미널 창에 하단과 같이 입력 후 프로그램 실행
//터미널 창을 통해 프로그램 실행
node index.js
실행 결과
제작 후 느낀점
간단한 프로그램이라 작성하는데 오래 걸리진 않았다
그 만큼 많은 기능이 포함되어있진 않은데
소스코드 작성시 알아보기 쉽게 주석을 통해서 자세한 설명을 해놓았으니
필요한 사람은 응용하여 더 다양한 기능을 구현하길 바란다
예를들면 이미 댓글을 작성한 글은 건너 뛰거나
답글을 달수 있는 경우 댓글이 아닌 답글을 달고
엑셀 같은 파일에 미리 댓글 / 답글 샘플을 여러개 작성해놓고
이를 랜덤하게 불러와서 댓글 및 답글을 달고
그날 업무 내역을 엑셀 파일에 저장하는 기능 등
업무 자동화를 통한 응용 가능한 기능은 무수히 많은 것 같다
PS. 위 프로그램에 더 다양한 기능을 구현을 원하거나
업무 자동화 웹 사이트 개발 등 상업적 이용을 위해 필요하신
업체 담당자님은 답글을 통해 연락 주십시오
'샘플코드' 카테고리의 다른 글
[Javascript] todo리스트 / 쇼핑 리스트 샘플 코드 (front-end) (0) | 2021.05.24 |
---|---|
[Javascript] 페이스북 아이디로 로그인 하기 코드 샘플 (소스코드) (0) | 2021.05.15 |
[프론트엔드] 쇼핑몰 상품 정렬 코드샘플 (Html,Javascript,Css) Sample Code (1) | 2021.02.24 |
[프론트엔드] 애플 메인 페이지 샘플 코드(변경가능) (0) | 2021.02.20 |
[프론트엔드] 유튜브 페이지 코드 샘플 (0) | 2021.02.17 |
댓글