AjaxなページもPhantomJS, CasperJS, SpookyJSでいい感じにクローリングできるようにしてSEOする

2014-01-10

ajaxなページもクローラーに読ませたいですよね。
そこでPhantomJS, CasperJS, SpookyJSです。

簡単に説明するとこんな感じ

PhantomJS

コマンドラインから使える画面がないwebkitブラウザ

CasperJS

PhantomJSのユーティリティ、PhantomJSをもっと便利に使えるようにするやつ

SpookyJS

casperJSをNodejsから使えるようにするやつ

こういうことをしたい

Network Diagram

クローラーがアクセスしてきた時だけ、アクセスしたURLをSpookyJSサーバーに投げて、SpookyJSがそのURLにアクセスし、DOMを取得してからクローラーに返すってことをしたらよさそうです。

SpookyJSをインスコ

SpookyJSはもちろんphantomJSとcasperJSに依存してるので、まずはこの2つをグローバルに入れる必要があります。

npm install phantomjs -g
npm install casperjs -g

必ず -g オプション!

次にプロジェクトのディレクトリで

npm install spooky

これしたら、OK

express用サンプル

ajaxの部分が全部読み込まれましたよーっていう判断をどうやってしようかなーって思って、
今回は「js-spooky-complate」ってclassが読み込まれたら、その時点のDOMを返すようにしようと思います。

もし、そのクラスがなかった場合、404を返すようにします。

spookyJSはデフォルトで8081ポートを使うので、expressとのバッティングに注意


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の部分を以下に置き換えます。

spooky.wait(2000, function() {});
spooky.then(function () {
    this.emit('complate', this.getHTML());
    this.exit();
});

これだと、強制的に2秒待ってから出力するようになります。

こんな感じで、ajaxページもクローリングさせることができます。

あとは一番上の図のwebサーバーで、spookyJSからの結果をmemcacheに突っ込んどいたりして、キャッシュを効かせるとなおいいかなーって思います。