본문 바로가기
샘플코드

[NodeJs] 네이버 지식인 오토 프로그램 샘플 코드 [feat javascript, selenium-webdriver] 댓글 / 답글 자동

by jinwanseo 2021. 5. 12.
728x90

NodeJs / Javascript 를 활용한 네이버 지식인 오토 자동 댓글 / 답글 프로그램

  프로그램 구동 로직

1. 네이버 로그인

2. 원하는 키워드 입력

3. 해당 키워드 관련 지식인 탭 내 모든 질문 한개씩 접속

4. 미리 입력한 댓글 자동 입력 후 업로드

5. 다음글에 접속 후 위 3,4 과정 반복

 

네이버 지식인 하루 댓글 작성 개수가 
한정되어있는 것으로 알고 있는데
몇개 까지 달수 있는지에 대해 정확히 몰라서
프로그램 사용자가 직접 원하는 댓글 개수를
입력할수 있도록 만들어 보았다

 

  프로그램 설치 및 사용 방법

위 프로그램은 소스 코드로 제작을 하였기 때문에

소스 코드를 실행할수 있는 환경의 설치 및 실행이 필요하다

 

  Microsoft VSCode 설치

(하단 링크를 통해 공홈 접속 후 자신의 운영 체제에 맞는 버전 설치)

https://code.visualstudio.com/

 

Visual Studio Code - Code Editing. Redefined

Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com

 

  NodeJs 설치

(하단 링크를 통해 공식홈페이지 접속 후 자신의 운영체제에 맞는 버전 설치)

https://nodejs.org/ko/

 

Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

 

  프로젝트 생성

자신이 원하는 경로에 프로젝트 (일반 폴더) 생성 후

설치한 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

  실행 결과

터미널 구동 영상 (지식인 제목 / url 출력) [왼쪽]  / 자동 댓글 입력 영상 [오른쪽]

 

  제작 후 느낀점

간단한 프로그램이라 작성하는데 오래 걸리진 않았다

그 만큼 많은 기능이 포함되어있진 않은데

소스코드 작성시 알아보기 쉽게 주석을 통해서 자세한 설명을 해놓았으니

필요한 사람은 응용하여 더 다양한 기능을 구현하길 바란다

예를들면  이미 댓글을 작성한 글은 건너 뛰거나

답글을 달수 있는 경우 댓글이 아닌 답글을 달고

엑셀 같은 파일에 미리 댓글 / 답글 샘플을 여러개 작성해놓고

이를 랜덤하게 불러와서 댓글 및 답글을 달고

그날 업무 내역을 엑셀 파일에 저장하는 기능 등

업무 자동화를 통한 응용 가능한 기능은 무수히 많은 것 같다

 

 

PS. 위 프로그램에 더 다양한 기능을 구현을 원하거나

업무 자동화 웹 사이트 개발 등 상업적 이용을 위해 필요하신

업체 담당자님은 답글을 통해 연락 주십시오

728x90

댓글