CasperJSで動的なjsページを操作しキャプチャを撮る
CasperJSで動的なjsページを操作してキャプチャを撮りました。
以前CasperJSでクロールしてキャプチャ撮る記事をあげました。
pppurple.hatenablog.com
普通のクロールではjsで動的にページが生成されるようなページは
クロールできません。
CasperJSを使うとページを操作することができるので、そういうページも
ダウンロードしたりキャプチャを撮ることが出来ます。
クリック操作
例えばこんなjsパーツがあったとします。
これはクリックすると、一覧が表示されます。
クリック時
これをCasperJSで操作する場合、click()で対象のcssセレクタを指定します。
casper.start('http://xxxxxxxxxxxx/'); casper.then(function() { this.click('#search_area > a'); });
evaluateで処理
クリックした後の下記の各エリアをすべて取得する場合、evaluate()で取得します。
こんな感じでdocument.querySelectorAll()で各エリアを取得するgetAreaList()を用意し、
evaluate()で呼び出します。
var getAreaList = function () { var ids = []; var arealist = document.querySelectorAll('#area > div > ul > li > a'); for (var i = 0; i < area.length; i++) { var id = area[i].id; ids.push(id); } return ids; }; var arealist = this.evaluate(getAreaList);
evaluate()は対象ページ内で指定したfunctionを実行するようなイメージです。
繰り返し処理
上記で取得したエリアリストをそれぞれ処理したい場合は、each()を使用します。
casper.each(arealist, function(self, id){ : : });
描画待機
例えばエリアで北海道を選択し、探すボタンを押すと、
下記のような待機画面が表示され、数秒後にjsで動的に検索結果が表示されます。
そのため、すぐに検索結果をオープンしてキャプチャを撮ると、
上記のような待機画面のキャプチャが撮れてしまいます。
そういう場合はwait()でjsによる画面描画を待機します。
var url = 'http://xxxxxxxxxxxxxxxxxxxxx/'; self.thenOpen(url, function(){ self.wait(5000, function() { : : }); });
画面スクロール
画面描画を待機すると下記のような検索結果が表示されます。
が、検索結果が14件となっていますが、実際は10件しか表示されません。
これは、検索結果が初期表示では10件までしか表示されず、
ページを下までスクロールするとjsで残りが表示されるようになっているためです。
twitterで下までスクロールすると過去のツイートが表示されるような感じです。
そんな場合はscrollToBottom()を使用すると画面下までスクロールしてくれます。
スクロールした場合は新しいデータをjsで読み込んでいるので少し待機する必要があります。
なのでスクロールした後少し待機するようにwait()と組み合わせます。
this.scrollToBottom(); self.wait(5000, function() { : : });
ページ取得と画面キャプチャ
その後、ページ取得と画面キャプチャを撮ります。
画面キャプチャは普通にcapture()で取得します。
this.capture(id + '.png');
ページの取得はdownload()で取得できるのですが、
download()ではurlを指定して取得するので、urlの初期表示のhtmlが取得され、
jsで動的に描画されたページのHTMLが取得できません。
// これだと動的に読み込んだページは取得できない this.download(url, id + '.html');
なので、jsで動的に描画している状態のhtmlを取得するgetHTML()を使用します。
fs.write(id + '.html', this.getHTML(), 'w');
取得スクリプト
これらを組み合わせて、jsで動的に生成される某ページのhtmlと画面キャプチャを取得しました。
ソースはこんな感じ。
crawl_dynamic_html.js
var casper = require('casper').create(); var fs = require('fs'); casper.start('http://xxxxxxxxxxxxxxxxxx/'); casper.then(function() { this.click('#search_area > a'); }); casper.wait(1000, function() { var getAreaList = function () { var ids = []; var arealist = document.querySelectorAll('#area > div > ul > li > a'); for (var i = 0; i < area.length; i++) { var id = area[i].id; ids.push(id); } return ids; }; var arealist = this.evaluate(getAreaList); casper.each(arealist, function(self, id){ var url = 'http://xxxxxxxxxxxxxxxxxx/search/index.html#' + id; self.thenOpen(url, function(){ self.wait(5000, function() { this.scrollToBottom(); self.wait(5000, function() { this.capture(id + '.png'); fs.write(id + '.html', this.getHTML(), 'w'); }); }); }); }); }); casper.run();
一応GitHubにソースあげました。
github.com