node.js에서 phantom.js사용하기 (kakao YelloID)

2018. 1. 12. 16:00javascript/node.js

오늘은 node.js에서 phantom.js를 사용해 web 파싱을 해볼려고한다.

필자는 kakao Yellow봇을 개발하던 도중 필요하게 되어서 공부한김에 글을 적어본다.

개발환경
OS: Ubuntu. Window10
node.js version: 6.12.3

1. npm 다운 받기




2. 코드 작성 하기


2-1. html 코드 파싱하기

우선 이페이지의 html코드를 파싱해와 보겠다.

node.js 소스코드

소스 코드는 kakao Yello bot소스 코드와 섞여 있습니다.

var express = require('express');
var router = express.Router();
var phantom = require('phantom');
var _ph, _page, _outObj;
router.post('/',function (req,res,next) {
    if(req.body.content == "E 순위"||req.body.content == "E순위" || req.body.content == "L 순위"||req.body.content == "L순위" ||req.body.content == "B 순위"||req.body.content == "B순위" ) {
        phantom.create().then(function (ph) {
            _ph = ph;
            return _ph.createPage();
        }).then(function (page) {
            var selectPage;
            if(req.body.content == "E 순위"||req.body.content == "E순위")
                selectPage = 'http://sports.news.naver.com/wfootball/record/index.nhn';
            else if( req.body.content == "L 순위"||req.body.content == "L순위")
                selectPage = 'http://sports.news.naver.com/wfootball/record/index.nhn?category=primera&tab=team';
            else if(req.body.content == "B 순위"||req.body.content == "B순위")
                selectPage = 'http://sports.news.naver.com/wfootball/record/index.nhn?category=bundesliga&tab=team';
            _page = page;
            return _page.open(selectPage);
        }).then(function (status) {
            console.log(status);
            return _page.property('content');
        }).then(function (content) {
            var bye_message = {"message":{"text":content.toString()}};
            console.log(content);
            _page.close();
            _ph.exit();
            res.set('200', {'Content-Type': 'application/json;charset=utf8'});
            res.send(bye_message);

        }).catch(function (e) {
            console.log(e);
        })
    }
}

 

결과

html 소스가 너무 길어서 일부분만 올립니다. 아래 사진과 같이 결과물을 확인 해볼 수 있습니다.




2-2 getElementByID를 통해 파싱하기

아래의 아이디 값을 통해 파싱 해와 보겠습니다. html안에 있는 텍스트만 파싱하겠습니다.

소스 코드

var express = require('express');
var router = express.Router();
var phantom = require('phantom');
var _ph, _page, _outObj;
router.post('/',function (req,res,next) {
    if(req.body.content == "E 순위"||req.body.content == "E순위" || req.body.content == "L 순위"||req.body.content == "L순위" ||req.body.content == "B 순위"||req.body.content == "B순위" ) {
        phantom.create().then(function (ph) {
            _ph = ph;
            return _ph.createPage();
        }).then(function (page) {
            var selectPage;
            if(req.body.content == "E 순위"||req.body.content == "E순위")
                selectPage = 'http://sports.news.naver.com/wfootball/record/index.nhn';
            else if( req.body.content == "L 순위"||req.body.content == "L순위")
                selectPage = 'http://sports.news.naver.com/wfootball/record/index.nhn?category=primera&tab=team';
            else if(req.body.content == "B 순위"||req.body.content == "B순위")
                selectPage = 'http://sports.news.naver.com/wfootball/record/index.nhn?category=bundesliga&tab=team';
            _page = page;
            return _page.open(selectPage);
        }).then(function (status) {
            console.log(status);
            return _page.evaluate(function(){
                return document.getElementById('wfootballTeamRecordBody').textContent;
                })
        }).then(function (content) {
            var bye_message = {"message":{"text":content.toString()}};
            console.log(content);
            _page.close();
            _ph.exit();
            res.set('200', {'Content-Type': 'application/json;charset=utf8'});
            res.send(bye_message);

        }).catch(function (e) {
            console.log(e);
        })
    }
}

이번에도 마찬가지 결과가 너무 길어서 짤라서 사진을 올립니다.





2-3 getElementsByTagName을 통해 파싱하기

TagName을 통해 파싱할때에는 조금 다른 방식으로 파싱을 한다.

 
var express = require('express');
var router = express.Router();
var phantom = require('phantom');
var _ph, _page, _outObj;
router.get('/',function (req,res,next) {
    if(req.body.content == "E 순위"||req.body.content == "E순위" || req.body.content == "L 순위"||req.body.content == "L순위" ||req.body.content == "B 순위"||req.body.content == "B순위" ) {
        phantom.create().then(function (ph) {
            _ph = ph;
            return _ph.createPage();
        }).then(function (page) {
            var selectPage;
            if(req.body.content == "E 순위"||req.body.content == "E순위")
                selectPage = 'http://sports.news.naver.com/wfootball/record/index.nhn';
            else if( req.body.content == "L 순위"||req.body.content == "L순위")
                selectPage = 'http://sports.news.naver.com/wfootball/record/index.nhn?category=primera&tab=team';
            else if(req.body.content == "B 순위"||req.body.content == "B순위")
                selectPage = 'http://sports.news.naver.com/wfootball/record/index.nhn?category=bundesliga&tab=team';
            _page = page;
            return _page.open(selectPage);
        }).then(function (status) {
            console.log(status);
            return  _page.evaluate(function(){
                var tdLength = document.getElementsByTagName('td');
                var returnText="";
                var ranking =1;
                for(var i = 0; i < tdLength.length;i++){
                    if(i % 10 == 1){
                        returnText +=ranking+'위' + tdLength[i].textContent+'\n';
                        ranking++;
                    }
                }
                return returnText;
            })
        }).then(function (content) {
            content = content.replace(/^\s+|\s+$/gm,''); //깔끔하게 보이기 위한 정규식
            var bye_message = {"message":{"text":content.toString()}};
            console.log(content);
            _page.close();
            _ph.exit();
            res.set('200', {'Content-Type': 'application/json;charset=utf8'});
            res.send(bye_message);

        }).catch(function (e) {
            console.log(e);
        })
    }
}



결과