PhantomJS 사용하기

2015. 10. 12. 13:48Programming/python

대부분의 웬만한 웹사이트는 Beautiful soup를 사용하여 parsing을 하면 손쉽게 데이터를 가져올 수 있다.

그런데 간혹 웹사이트들 중 Javascript에서 html을 만들어서 실행되는 동적페이지가 있다. 

곤란하게도 Beautiful soup에서는 Javascript를 실행해주지 않으며, 그 결과로 parsing도 제대로 동작하지 않느다.


이를 해결하기 위해서는 Javascript가 rendering 된 후에 parsing을 할 수 있는 방법을 찾아야 하며 아래 사이트는 그에 대한 해결 방안을 3가지 방법으로 제시하였다.


https://www.quora.com/Can-beautifulsoup-scrape-javascript-rendered-webpages


내가 사용한 방법은 위의 세 가지 중 PhantomJS를 이용한 방법을 사용하였다.


우선 PhantomJS를 설치해 보자.


환경은 우분투 14.04를 기준으로 작성하였다.


처음에는 PhantomJS 실행을 위한 기본 라이브러리들을 설치한다.


$> sudo apt-get install build-essential g++ flex bison gperf ruby perl libsqlite3-dev libfontconfig1-dev libicu-dev libfreetype6 libssl-dev libpng-dev libjpeg-dev python libx11-dev libxext-dev


설치가 완료되었으면, git 저장소에 있는 PhantomJS 소스 파일을 가져온 후, 빌드를 해준다.


$> git clone git://github.com/ariya/phantomjs.git

$> cd phantomjs

$> git checkout 2.0

$> ./build.sh


빌드가 완료되면 bin 폴더 안에 phantomjs라는 실행 파일이 생성될 것이다. 이제 이 파일을 이용해서 동적 웹페이지를 호출하면 된다.


이제 본격적으로 PhantomJS를 어떻게 사용하는지를 살펴보자.

PhantomJS를 사용하기 위해서는 실행 가능한 Javascript 파일이 하나 필요하다.




나는 아래와 같은 내용의 Javascript 파일을 만들었다.


var page = require('webpage').create();

var system = require('system');

var fs = require('fs');


if (system.args.length === 1){

    console.log('Usage: loadspeed.js <some URL>');

    phantom.exit();

}


var address = system.args[1];

page.open(address, function(status){

     if (status) {

         fs.write('test.html', page.content, 'w');

     }

     phantom.exit();

});


로딩될 동적 페이지 주소를 파라미터로 받아서 test.html을 만들어 주는 Javascript 파일이다.


$> ./phantomjs test.js <someURL>


위의 명령을 입력하면 동적페이지가 로딩된 test.html의 이름을 가진 파일이 생성된다.


이제 이렇게 만들어진 html 파일을 beautiful soup에서 parsing하면 크롤링 작업이 완료된다.


나 같은 경우에는 phantomjs 실행 명령 자체를 python 코드에 내재해서 코드를 작성하였다.


import urllib

import urllib2

import os

import sys

import logging

from bs4 import BeautifulSoup


reload(sys)

sys.setdefaultencoding('utf-8')


def getWebSite(link) :

os.system("phantomjs test.js '" + link + "'")

try:

          f = open('test.html')

          tt = f.read()

          soup = BeautifulSoup(tt)

except urllib2.HTTPError, e:

          logging.exception('http Error : ' + e.reason)

          pass

except urllib2.URLError, e:

          logging.exception('url Error : ' + e.reason)

          pass