자동 글등록 봇 만들기 -디씨봇- (1)

2019년 2월 26일 화요일

목차

  1. 준비
  2. phontomjs 설치및 테스트
  3. node.js phontomjs 연동
  4. 실제예제
  5. raspberry pi 이용

준비

자동으로 글을 등록하는 가장 간단한 방법은 post로 필드값을 보내는 것이다. 하지만 로그인을 해야한다거나 복잡한 전처리가 필요하다면 하나하나 분석하여 값을 서버로 넣고.. 쿠키를 저장하는등 구현하기 까다러워진다. 이것은 개발이후에도 조금만 변경이 되어도 다시 일일히 분석해야해서 관리가 힘들어진다.

좀더 간편하게 관리하기위해서는 실제 브라우저를 이용해 글을 작성하듯이 구현하면된다. 사람이 작성하듯 브라우저를 열고 로그인창으로 이동해서 아이디, 패스워드를 입력하고 글을 작성한다.

이걸 정리하면 간단하게 아래의 5가지 동작으로 나눌수 있다.

  1. 브라우저 열기 2) 로그인창으로 이동 3) 아이디, 패스워드 입력 4) 게시판으로 이동 5) 제목, 내용 입력

정리보면 굉장히 단순한 작업들이다. 직접 브라우저를 띄우는 매크로를 작성할수도 있겠지만 좀더 효율적으로 관리하기위해 headless browser를 이용하면 된다.

대표적인 headless browser로 오픈소스 프로젝트인 phantomjs가 있다. phantomjs 를 직접 이용해서 프로그래밍도 가능하지만 추후 확장성을 고려해 node.js에서 phantomjs를 연동하는 방식으로 하겠다.

실제예제로 등록이 까다로운 커뮤니티중 한 곳인 dcinside.com에 등록되는 프로그램을 작성해보도록 하겠다.

phantomjs 설치

대표적인 headless browser인 phontomjs를 설치한다. 여기서는 windows 기준으로 설명한다.

http://phantomjs.org/download.html

d:\ 에 설치하였다.

명령프롬프트를 열고 path를 잡아준다.

set path=%path%;d:\phantomjs-2.1.1-windows\bin;

잘실행되는지 확인한다.

phantomjs -v

간단하게 phantomjs 스크립트 파일을 작성해서 실행해보겠다. 스크립트언어는 javascript 이다. 간단하게 웹페이지를 열고 캡쳐하는 소스이다. 자세한 api는 http://phantomjs.org/api/ 여기에서 확인 할 수 있다.

test.js

var page = require('webpage').create()
page.open('http://www.naver.com', function (status) {
  console.log('Status: ' + status)
  if (status === 'success') {
    page.render('naver.png')
  }
  phantom.exit()
})

실행해본다.

phantomjs test.js

naver.png 파일이 저장된다.

node.js

node.js를 설치한다. async await를 사용하기위해 7.6 이후버전으로 설치한다.

글작성 시점에 LTS버전은 10.15.1이다.

https://nodejs.org

phantom 모듈을 설치한다.

npm install phantom

phantomjs를 node.js에서 사용할수 있도록 감싸진 모듈이다. phantomjs api와 거의 똑같다. phantom은 기본적으로 Promise를 지원한다. 좀 더 자세한 설명은 이곳에서 확인가능하다. https://www.npmjs.com/package/phantom

이제 node.js 를 이용하여 작성해보겠다.

test.js

'use strict'
const phantom = require('phantom')

const url = 'http://www.naver.com'
;(async () => {
  try {
    const instance = await phantom.create()
    var page = await instance.createPage()

    const status = await page.open(url)
    if (status == 'success') {
      await page.render('naver.png')
    }

    await instance.exit()
  } catch (err) {
    console.log(err)
  }
})()

phantomjs 스크립트와 거의 흡사하다. async/await를 사용해 좀 더 깔끔하게 표현된다. async/await 없이 아래와 같이 사용할 수도 있겠다. Promise를 사용해 callback지옥은 없지만 async/await에 비해 가독성은 확실히 떨어진다.

;(() => {
  var page = null
  var instance = null
  phantom
    .create()
    .then(function (inst) {
      instance = inst
      return instance.createPage()
    })
    .then(function (p) {
      page = p
      return page.open(url)
    })
    .then(function (status) {
      if (status == 'success') {
        return page.render('naver.png')
      }
      return null
    })
    .then(function () {
      return instance.exit()
    })
    .catch(function (err) {
      console.log(err)
    })
})()

실행해본다.

node test.js