拙著「株はタイミングで儲けなさい」が発売されました。
過去20年間の株価データを元にバックテストを行い、どのようなタイミングで株を買うのが良いかを解説しています。
自由国民社刊で、定価1,512円(消費税込み)です。
Webページのテストやスクリーンキャプチャに便利な「PhantomJS」
先日、twitterで@chacoさんと@riatwさんの以下のようなやり取りを見かけました。
@chaco Phantom.jsなるものが最近流行っているんだとか。
— Kentaro Suzukiさん (@riatw) 1月 11, 2013
そこで、PhantomJSについて調べてみました。
1.PhantomJSの概要
PhantomJSは、WebKitを組み込んだWebブラウザエミュレータのようなものです。
Webブラウザに対する一連の操作を自動化して、その結果を得ることができます。
自動化したい処理は、JavaScriptで記述します。
たとえば、以下のようなことを行うことができます。
- フォームの送信など、Webページに対する各種の動作テスト
- Webページに対してDOM操作等を行って結果を出力
- スクリーンキャプチャ
- リクエスト/レスポンスの調査
2.PhantomJSのインストール
PhantomJSは、Windows/Mac/Linux用のバイナリファイルと、ソースコードが配布されています。
一般的には、ご自分の環境に合ったバイナリファイルをダウンロードするのが簡単で良いでしょう(ただし、Linux版は依存関係がありますので要注意)。
Windowsの場合だと、ダウンロードしたZipファイルの中のphantomjs.exeが、実行ファイルです。
また、MacではZipファイルの中のbin/phantomが実行ファイルです。
3.スクリプトの基本
PhantomJSで実行するJavaScriptのひな形は、以下のようになります。
var page = require('webpage').create(); page.open(操作対象WebページのURL, function (status) { 各種の操作 phantom.exit(); });
openメソッドを実行すると、PhantomJS内部のWebKitがそのページにアクセスします。
そして、内部的にページの表示が終わると、openメソッドに渡したコールバック関数が実行されます。
その結果、コールバック関数の「各種の操作」の部分が処理され、開いたWebページに対する各種の操作が実行されます。
各種の操作は、pageオブジェクトのメソッドで表します。
主なメソッドとして、以下のようなものがあります。
メソッド | 概要 |
---|---|
addCookie | Cookieをセットする |
evaluate | Webページのコンテキストで関数を実行し、その結果を返す |
includeJs | JavaScriptを挿入する |
render | ページをキャプチャする |
sendEvent | マウスやキーボードのイベントを送信する |
uploadFile | ファイルをアップロードする |
スクリプトを作成したら、ファイルに保存します。
そして、ターミナルを起動し、phantomjsがあるディレクトリに移動して、「phantomjs スクリプトのファイル名」のコマンドを入力してスクリプトを実行します。
4.画面キャプチャの例
画面キャプチャを行うスクリプトの例として、Google/Yahoo/Bingのトップページをキャプチャするスクリプトを作ってみました。
先頭のURLとファイル名の代入部分を書き換えれば、他のWebページをキャプチャすることもできます。
var sites = [ { url: 'http://www.google.co.jp/', image: 'google.png' }, { url: 'http://www.yahoo.co.jp/', image: 'yahoo.png' }, { url: 'http://www.bing.com/', image: 'bing.png' } ]; var captured = 0; function capture(site) { var page = require('webpage').create(); page.open(site.url, function() { page.render(site.image); console.log('captured ' + site.url); captured++; if (captured == sites.length) { phantom.exit(); } }); } for (var i = 0, j = sites.length; i < j; i++) { capture(sites[i]); }