nikaido

PhantomJS と CasperJS で複数ページを一括キャプチャする

 

Web 制作をしているとページの表示確認やコンポーネントの洗い出しなどで、大量にキャプチャを撮ってきたい時があります。

しかしブラウザのエクステンションで1枚ずつ撮るのも面倒です。

そこで PhantomJS と CasperJS を使うとキャプチャを自動化することができるということなので、先達たちの情報を参考に、キャプチャしたいURLと想定するデバイスを CSV で管理して、楽にキャプチャがとれるものを作成しました。

 

PhantomJS と CasperJS とは

PhantomJS ですが、グラフィカルな画面のないブラウザで「ヘッドレスブラウザ」と呼ばれるブラウザです。コマンドラインからブラウザの機能を使うことができ、フォームの操作やページの要素を取得することができます。よく CI ツールと組み合わせて自動テストを行ったり Web スクレイピングで使われたりします。

PhantomJS のレンダリングエンジンには Webkit が使われていますが、Gecko を使っている SlimerJS というのもあります。

CasperJS は、その PhantomJS をより手軽に使えるようにするライブラリです。

CasperJS は SlimerJS もサポートしているので、エンジンを切り替えることで両方のエンジンでレンダリングされた結果を検証することができます。

同じレンダリングエンジンを使うウェブブラウザ

ヘッドレスブラウザ エンジン 同じエンジンを使うウェブブラウザ
PhantomJS Webkit Safari
SlimerJS Gecko Firefox

 

自動キャプチャの使い方

必要なモジュールをインストール

PhantomJS と CasperJS をインストールします。

$ npm install -g phantomjs casperjs

 

バージョン情報が表示されれば、正常にインストールされています。

$ phantomjs --version
2.0.0

$ casperjs --version
1.1.0-beta5

 

※ 今回は npm でインストールしましたが、Homebrew や Zip ダウンロードからもインストールできます。

サンプルファイルをダウンロード

サンプルファイルはこちらに置いています。ご自由に編集してお使いください。

 

1つのフォルダの中に全てのファイルをフラットに置いてください。

[適当なフォルダ]
├ capture.js
├ list.csv
├ device.csv
└ jquery.min.js

finder

 

黒い画面でコマンドをたたく

ターミナルなどコマンド入力できるアプリで、サンプルファイルを保存したフォルダまで移動します。

$ cd [フォルダまでのパス]

 

下記のコマンドでキャプチャが実行されます。
「pc」を「sp」や「tablet」に変えるとそれぞれのサイズでキャプチャが撮れます。

$ casperjs capture.js pc

※ キャプチャするURLは list.csv で管理しています。
※ デバイス情報は device.csv で管理しています。

 

デバイス名にスペースがあったりすると「" "」でくくってください。

$ casperjs capture.js "iphone 6 plus"

 

Basic 認証がかかっているテストページなどでは、オプションでIDとPasswordを指定します。

$ casperjs capture.js pc --id=UserName --pass=Password

 

正常に処理が開始されると同フォルダ内に png 画像が入ったフォルダが出来上がります。

capture

 

処理が始まればコマンドラインにログが流れます。

log

 

各ファイルの説明

各ファイルの内容を説明しておきますので、自由に編集してください。

list.csv - キャプチャしたいページリスト

GoogleスプレッドシートなどからCSVファイルを作成します。
サイトマップなどがある場合、そこからデータを抽出できると思います。

  • 1 列目は「ページのURL」
  • 2 列目は「キャプチャを保存したいファイル名」
  • 拡張子はプログラム内で「.png」を付与しているので、この時点では必要ありません。
  • ファイル名は「list.csv」としてください。
list csv

device.csv - キャプチャするデバイスリスト

同じくCSVを作成してください。一度作れば使いまわせると思います。

  • 1列目は「デバイス名」
  • 2列目は「デバイスの横幅」
  • 3列目は「デバイスの高さ」
  • 4列目は「ユーザーエージェント」
  • ファイル名は「device.csv」としてください。
device

capture.js - CasperJSで実行するプログラム本体

// casperJSのインスタンス生成とjQueryの差し込み
var casper = require('casper').create({clientScripts: ['./jquery.min.js']});

// ファイル操作を行うモジュールの読み込み
var fs = require('fs');

// キャプチャするURLリストの取得
var buf = fs.read('./list.csv');
    buf = buf.replace( /\r\n/g , '\n' );
var captureList = makeCSVArray(buf);

// コマンドラインからのデバイス指定を確認
if (casper.cli.args.length < 1) {
    // 指定なしのデフォルト
    var inputDevice = 'pc';
    var viewport = {width: 1280, hight: 800};
    var ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36';
} else {
    // 指定ありの場合CSVから情報を取得
    var inputDevice = casper.cli.args[0];

    var buf = fs.read('./device.csv');
        buf = buf.replace( /\r\n/g , '\n' );
    var deviceSpec = findFromCSV(buf, inputDevice);

    var viewport = {width: parseInt(deviceSpec[1]), hight: parseInt(deviceSpec[2])};
    var ua = deviceSpec[3].replace(/(^\s+)|(\s+$)/g, '"');
}

// キャプチャを撮る間隔
var waitTime = 3000;

// コマンドラインから指定されたBasic認証のIDとPassword
var basicId = casper.cli.options.id;
var basicPass = casper.cli.options.pass;

// キャプチャを保存するフォルダ名に使う文字列を日時から生成
var screenshotNow = new Date();
var screenshotDateTime = screenshotNow.getFullYear() + pad(screenshotNow.getMonth() + 1) +
    pad(screenshotNow.getDate()) + '-' + pad(screenshotNow.getHours()) +
    pad(screenshotNow.getMinutes()) + pad(screenshotNow.getSeconds());

// casperJSの処理を開始
casper.start();

// viewport, UA, Basic認証の情報を設定
casper.userAgent(ua);
casper.viewport(viewport.width, viewport.hight);
casper.setHttpAuth(basicId, basicPass);

// 取得したURLリストからキャプチャを撮る処理
casper.each(captureList, function(casper, data) {
    var url = data[0];  // ページのURL
    var file = data[1];  // 保存する画像名

    // ページを開く
    this.thenOpen(url, function () {
        this.wait(waitTime);
    });
    this.then(function () {
        // コマンドラインにメッセージを出す
        this.echo('URL: ' + url + ' | File: ' + file + '.png');
        // background-colorに指定がない場合透過されるので色をつける
        this.evaluate(function(){
            $('body').css('background-color','#fff');
        });
        // キャプチャした画像を保存する。/ をつけることでフォルダを作成
        this.capture(screenshotDateTime + '-' + inputDevice + '/' + file + '.png');
    });
});

// casperJSの処理を実行
casper.run();

// csvファイルを配列化
function makeCSVArray(buf){
    var csvData = [];
    var lines = buf.split('\n');
    for(var i = 0; i < lines.length; i++){
        var cells = lines[i].split(',');
        if(cells.length !=1){
            csvData.push(cells);
        }
    }
    return csvData;
}

// csvファイルから指定したレコードを取り出す
function findFromCSV(buf, key) {
    var csvData =[];
    var lines = buf.split('\n');
    for(var i = 0; i < lines.length; i++){
        var cells = lines[i].split(',');
        if(cells[0] == key){
            csvData = cells;
            break;
        }
    }
    return csvData;
}

// 数値→文字列変換
function pad(number) {
    var r = String(number);
    if ( r.length === 1 ) {
        r = '0' + r;
    }
    return r;
}

以上、ではよいキャプチャライフを!

 

お世話になった参考サイト

お問い合わせはこちら