【PhantomJS】ajaxなページをスクレイピングする方法メモ

やりたかったこと

今回やりたかったのはjavascriptでコンテンツを表示するページの解析。
今までもたまにスクレイピング用のスクリプト作ったことはあったけど、wgetphpのfile_get_contentsで取得したhtmlを解析するようのものしかなかった。

ちょっと調べてみるとPhantomJS使う方法とSeleniumを使う方法がたくさん出てきた。
今回はページを読み込むとjavascriptが動いてhtmlを生成するようなページが対象で、やりたいことも簡単だったのでより導入が簡単そうだったPhantomJSを使ってみた。

実装

まずはPhantomJSのインストール。node.jsは入っている前提で。

$ npm install phantomjs
・・・
$ ./node_modules/phantomjs/bin/phantomjs -v
2.1.1

スクレイピング対象のテストサイトを用意

index.html

<!DOCTYPE html>
<head><title>テスト</title></head>
<body>
  <div id="content">読み込み中...</div>
  <script src="./index.js"></script>
</body>
</html>

index.js

window.addEventListener("load", function() {
    setTimeout(function() {
        document.getElementById("content").innerHTML =
            "1,田中<br/>" +
            "2,高橋<br/>" +
            "3,亀井";
    }, 3000);
});

ページが読み込まれてから3秒後にHTMLを表示するようなページ。
実際はajaxでデータを取得してくるイメージだけど今回はこれで。

次は本題の取得用スクリプト
まずは上手くいかないやつ

get.js

var page = require('webpage').create();
var url = "http://example.com/index.html";

page.open(url, function() {
    console.log(page.content);
    phantom.exit();
});

実行すると取得したいものと違う

$ ./node_modules/phantomjs/bin/phantomjs get.js
<!DOCTYPE html><html><head><title>テスト</title></head>
<body>
  <div id="content">読み込み中...</div>
  <script src="./index.js"></script>
</body></html>

修正版

var page = require('webpage').create();
var url = "http://example.com/index.html";

page.open(url, function() {
    // ★5秒後にページを取得する形に変更
    setTimeout(function() {
        console.log(page.content);
        phantom.exit();
    }, 5000);
});

実行

$ ./node_modules/phantomjs/bin/phantomjs get.js
<!DOCTYPE html><html><head><title>テスト</title></head>
<body>
  <div id="content">1,田中<br>2,高橋<br>3,亀井</div>
  <script src="./test3.js"></script>
</body></html>

取得できた!以上です