PhantomJS入門 CasperJSを使う
ここんとこのブログの題材として2週間ほどPhantomJSを触ってみましたが、これけっこう難しいです。JavaScript独特のイベント処理や、WebKitの仕組みうんぬんで、リンクをクリックするのにもハマったりします。
何かいい方法あるはず、、と調べてたら、やっぱりあるんですね。
CasperJS
CasperJS is a navigation scripting & testing utility for PhantomJS, written in Javascript
http://casperjs.org/
CasperJSは、JavaScriptで実装されたPhantomJSのユーティリティです。ざっくり以下のことができます。
Installation
Macユーザーはbrewコマンドでインストールできます。
% brew install casperjs
詳しくは公式サイトで。
http://casperjs.org/installation.html
Quickstart
http://casperjs.org/quickstart.html
本家サイトのQuickstartを見てみると大体のイメージがつかめます。
サンプルはGoogleの検索結果を出力するものです。*1
var casper = require('casper').create(); casper.start('http://google.fr/', function() { // search for 'casperjs' from google form this.fill('form[action="/search"]', { q: 'casperjs' }, true); });
たとえば、上記の場合だと、まずcasperオブジェクトを作っています。このcasperオブジェクトを操作していくことが処理の中心になります。
casper.startメソッドにURLとコールバック処理を定義しています。コールバックの中では、フォームの入力処理(fill)を実行しています。第3引数にtrueを指定しているので、フォームの入力と共にsubmitします。
ナビゲーションステップ
サンプルの説明
勉強も兼ねてサンプルを作ってみました。
Webサーバー上に3つのページがあります。
- /index
- /page1
- /page2
/indexには/page1、/page2へのリンクがあります。
これを以下の手順でスクリーンショットを撮ってみたいと思います。
CasperJSプログラムを作成する
casper = require('casper').create() casper.start 'http://localhost:4567', -> @capture('index.png') @click("#link1") casper.then -> @capture('page1.png') @back() casper.then -> @click("#link2") casper.then -> @capture('page2.png') casper.run()
上記のプログラムを実行するとindex、page1、page2のスクリーンショットを取得できます。
サンプルはCoffeeScriptで書いています。そのため、コード量も少なくなり、より直感的になっています。*3
コードの解説も加えておくと、casperオブジェクトに対して、まずstartメソッドを呼び出しています。その後、thenメソッドで処理を順に定義していきます。実際に実行するためにはrunメソッドを呼び出す必要があります。
CasperクラスのAPI
CasperクラスのAPIを見れば他にどんなことができるのか参考になります。たとえば、echoでコンソール出力したり、evaluateでDOMを解析したりというのがわかります。
http://casperjs.org/api.html#casper
背景色について
PhantomJSでスクリーンショットを撮ると背景色が透過されてしまいます。
公式のFAQによると、PhantomJSプログラム側で細工してあげる必要があるようです。
http://phantomjs.org/faq.html
page.evaluate(function() { document.body.bgColor = 'white'; });
おまけサーバーサイドプログラム
本題と関係ないですが、サンプルで使用したサーバーサイド処理です。静的な処理だけで済んだから、Webサーバーで良かったんですけど、Sinatra使ってみたかったので。
require 'sinatra' require 'sinatra/reloader' require 'haml' get "/index" do haml :index end get "/page1" do haml :page1 end get "/page2" do haml :page2 end __END__ @@index %html %body(style="background-color: white") %h1 index %ul %li %a(href="/page1" id="link1") page1 %li %a(href="/page2" id="link2") page2 @@page1 %html %body(style="background-color: white") %h1 page1 @@page2 %html %body(style="background-color: white") %h1 page2
サーバーサイド処理の依存ライブラリ(Gemfile)はこちら。
# A sample Gemfile source "https://rubygems.org" gem "thin" gem "sinatra" gem "sinatra-contrib" gem "haml"