ajaxなページもクローラーに読ませたいですよね。
そこでPhantomJS, CasperJS, SpookyJSです。
簡単に説明するとこんな感じ
PhantomJS
コマンドラインから使える画面がないwebkitブラウザ
CasperJS
PhantomJSのユーティリティ、PhantomJSをもっと便利に使えるようにするやつ
SpookyJS
casperJSをNodejsから使えるようにするやつ
こういうことをしたい
クローラーがアクセスしてきた時だけ、アクセスしたURLをSpookyJSサーバーに投げて、SpookyJSがそのURLにアクセスし、DOMを取得してからクローラーに返すってことをしたらよさそうです。
SpookyJSをインスコ
SpookyJSはもちろんphantomJSとcasperJSに依存してるので、まずはこの2つをグローバルに入れる必要があります。
1 2 | npm install phantomjs -g npm install casperjs -g |
必ず -g オプション!
次にプロジェクトのディレクトリで
1 | npm install spooky |
これしたら、OK
express用サンプル
ajaxの部分が全部読み込まれましたよーっていう判断をどうやってしようかなーって思って、
今回は「js-spooky-complate」ってclassが読み込まれたら、その時点のDOMを返すようにしようと思います。
もし、そのクラスがなかった場合、404を返すようにします。
spookyJSはデフォルトで8081ポートを使うので、expressとのバッティングに注意
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | var Spooky = require( 'spooky' ); exports.index = function (req, res){ var url = req.param( 'u' ); var spooky = new Spooky({ child: { transport: 'http' }, casper: { logLevel: 'error' , verbose: true , waitTimeout : 3000 } }, function (err) { spooky.start(url); spooky.waitFor( function check() { return this .evaluate( function () { return document.querySelectorAll( '.js-spooky-complate' ).length >= 1; }); }, function then() { this .emit( 'complate' , this .getHTML()); this .exit(); }, function timeout() { this .emit( 'timeout' , this .getHTML()); this .exit(); }); spooky.run(); }); spooky.on( 'error' , function (e, stack) { res.send(404); spooky.removeAllListeners(); this .exit(); }); spooky.on( 'timeout' , function (e, stack) { res.send(404); spooky.removeAllListeners(); this .exit(); }); spooky.on( 'complate' , function ( html ) { res.send( html, { 'Content-Type' : 'text/html' }, 200); spooky.removeAllListeners(); this .exit(); }); } |
(ホントは new Spookyをexports.indexの外に出したかったけど、うまくいかなかった、、、)
spookyはcasperをラップしてるだけっぽいので、casperjsのコマンドは全部使えます。
20行目のspooky.waitForの中で、js-spooky-complateが読み込まれるまでwaitしています。
デフォルトの待ち時間は5000ms ですが、上記のように「waitTimeout : 3000」を書くと3秒になります。
指定秒数内で js-spooky-complate が読み込まれた場合、spooky.waitForで, function then() に行き、クラスがなくて3秒たってしまった場合、function timeout() が呼ばれます。
クラス指定じゃなくて、強制的に数秒待つ場合
ajaxを多用してるページなどで、特定のクラスを読み込んだら完了っていう判断をしづらい場合、強制的にクローラーからのアクセスは数秒待ってから出力って事もできます。
上記のソースの spooky.waitForの部分を以下に置き換えます。
1 2 3 4 5 | spooky.wait(2000, function () {}); spooky.then( function () { this .emit( 'complate' , this .getHTML()); this .exit(); }); |
これだと、強制的に2秒待ってから出力するようになります。
こんな感じで、ajaxページもクローリングさせることができます。
あとは一番上の図のwebサーバーで、spookyJSからの結果をmemcacheに突っ込んどいたりして、キャッシュを効かせるとなおいいかなーって思います。