Node.js + PhantomJS でウェブサイトのスクリーンショットを作成

PhantomJSとNode.jsを使ってWebサイトのスクリーンショットを取得してみます。

PhantomJSについては、PhantomJS公式サイトに詳しく記載されていますが、代表的な使い方として以下のような例が取り上げられています。

  • HEADLESS WEBSITE TESTING
  • SCREEN CAPTURE
  • PAGE AUTOMATION
  • NETWORK MONITORING

PhantomJS

  1. PhantomJSインストール

     brew install phantomjs
    
  2. 以下のコマンドを入力してインストールされている事を確認します。

     $ phantomjs
    

Node.jsでPhantomJS

node-phantom : alexscheelmeyer / node-phantom を使ってみます。

npm search phantomで、数多くのPhantomJS用パッケージが見つかります。

例;

Webサイトのスクリーンショットを撮るだけならば、PhantomJSをラップした

も親切でわかりやすかったです。

使い方

  1. package.jsonにnode-phantomを追加

  2. インストール

     npm install
    

サンプルコード

ファイルに保存する場合

   var phantom = require('node-phantom');

    略
    
    function webCapFile(url,filename,viewW,viewH,clipW,clipH){
        phantom.create(function(error,ph){
            ph.createPage(function(err,page){
                page.set('viewportSize',{width:viewW,height:viewH},function(err){
                    page.set('clipRect',{width:clipW,height:clipH},function(err){
                        page.open(url,function(err,status){
                            page.render(filename,function(err){
                                ph.exit();
                            });
                        });
                    });
                });
            });
        });
    }

コールバック・ネストの嵐になっていますね・・ 非同期処理ライブラリを使うといいと思います。エラーハンドリングは省略していますがしないとアプリがクラッシュします。

ちなみにpage.setで与えてるパラメータは

  • viewportSize : ブラウザのサイズ。
  • clipRect : クリップしたいサイズ。開始地点のX,Y座標を指定することもできます。

です。詳細は、PhantomJSのAPIリファレンスに書いてあります。

base64で扱う場合

base64エンコードしたものを受け取りたい場合は、renderBase64()関数を使ってコールバック関数の中でバイナリを受け取ります。

サーバサイド(app.js)

サーバで画像のbase64をを生成して、socket.io経由でクライアントのimgタグに表示させる場合の例です。

    var phantom = require('node-phantom');

    略

    function webCapB64(url,viewW,viewH,clipW,clipH){
        phantom.create(function(error,ph){
            ph.createPage(function(err,page){
                page.set('viewportSize',{width:viewW,height:viewH},function(err){
                    page.set('clipRect',{width:clipW,height:clipH},function(err){
                        page.open(url,function(err,status){
                            page.renderBase64('PNG', function(err, b64){
                                ph.exit();
                                socket.emit('display_web_image', { image:b64 });

                            });
                        });
                    });
                });
            });
        });
    }

クライアントサイド

ヘッダ部'data:image/png;base64,'を付けるのがポイントです。

    socket.on('display_web_image', function(data){
        //imgタグ(id=web_image)に表示させる場合    
        $('#web_image').attr('src', 'data:image/png;base64,' + data.image);

    });