PhantomJS: 「最小限なheadlessのWebKitベースのJavaScriptツール」

こりゃ面白い。http://code.google.com/p/phantomjs/

"PhantomJS is a minimalistic, headless, WebKit-based, JavaScript-driven tool"
headless=スクリーンがない=コマンドと考えればいい。要はブラウザから画面と取り除いてJavaScriptによるスクリプティングを可能にしたコマンドツール。逆に言うとDOM+JavaScript+Networkingをコマンドにしたもの。
説明してもピンとこないだろうから実例を紹介する。http://code.google.com/p/phantomjs/wiki/QuickStart

hello world

hello.js


console.log('Hello, world!');
phantom.exit();
$ phantomjs hello.js

ブラウザにはないsynchronous sleep機能

phantom.sleep(1000)で簡単に寝れる。ただしブロッキングなのでその間、他のオペレーションは停止する。当然、通常のwindow.setTimeoutもできる。

コマンドラインインターフェス

argvはphantom.argsとしてアクセス可能。


if (phantom.args.length === 0) {
console.log('Try to pass some args when invoking this script!');
} else {
phantom.args.forEach(function (arg, i) {
console.log(i + ': ' + arg);
});
}
phantom.exit();
伝統的なCコマンドのようにargで始まりexit()で終るjavascriptが書けるってのは違和感のある楽しさだ。

ページをロードしてスクリプトを走らせる (Loading)

$ phantomjs hoge.js
とするとhoge.jsというスクリプトをURLからロードされたページに対して実行できる。ページを読み込む時間を測るスクリプトを例にしている。


$ phantomjs loadspeed.js http://www.google.com
Loading http://www.google.com
Page title is Google
Loading time 719 msec

URLを画像化する (Rendering)

$ phantomjs rasterize.js http://ariya.github.com/svg/tiger.svg tiger.png
ネットワーク上のSVGpngに変換。

DOM操作 (DOM Manipulation)

WebKitを使っているので、DOM操作やCSSもできる。ページを読み込んで、エレメントから値を抽出することが簡単にできる。
console.log(document.getElementById('myagent').innerText);
これで読み込んだページの#myagentエレメントのテキストが出力できる。

Googleからニューヨークのピザ屋の住所と電話番号を抽出する例がある。10行ちょっとこのコードだ。


if (phantom.state.length === 0) {
phantom.state = 'pizza';
phantom.open('http://www.google.com/m/local?site=local&q=pizza+in+new+york');
} else {
var list = document.querySelectorAll('div.bf');
for (var i in list) {
console.log(list[i].innerText);
}
phantom.exit();
}

googleはあの手この手でスクレーピングをさせない工夫をしてきた。しかし、このようなツールができると、ブラウザとスクレーピングプログラムとの境界がぼける。ブラウザと同じコードを使っているの区別のつけようもないだろう。いたちごっこはやめてYahooのBOSSのようにAPIを公開すればいいのに。どっちにしろこれでgoogleがスクレープしやすくなった。前から考えている「グーグルはアドセンスを掲載しているコンテントファームに甘いのではないか」という仮定を検証するのにちょうどいい。
話がそれた。

インストール

make installは何もしない。必要なのはbin/phantomjsだけなのでsudo cp bin/phantomjs /usr/local/bin/でいいだろう。

参照