hello people

Posted

PhantomJSとCasperJSを使ってWebページを自動でキャプチャする

大規模なWebサイトなどを作っていると、テストやエビデンスとしてWebページのキャプチャがほしい場合があります。
ただし、何百ページもあると、手動でキャプチャを撮るにはあまりにも時間と労力がかかるので、やってられないですよね。
そんな時にはPhantomJSとCasperJSを使用すれば、割と手軽に自動でキャプチャーを撮る事ができます。

PhantomJSとは

phantomjs

PhantomJSはWebkitベースで作られているブラウザです。ただし、画面が存在しないCUIで動作するブラウザで、ヘッドレスブラウザとも呼ばれています。

PhantomJSはSafariと同様にWebkitベースで作られているため、キャプチャを撮る際にもWebkitで表示した際と同様になります。そのため、今回ご紹介する方法ではクロスブラウザでのキャプチャは取得できません。
他にもGeckoを搭載したヘッドレスブラウザにSlimerJSなどがあります。

CasperJSとは

casperjs

CasperJSはPhantomJS(もしくはSlimerJS)を使ってブラウザ操作やテストが出来るユーティリティライブラリです。
CasperJSを使用する事でキャプチャリングやスクレイピングなど色々な事が手軽に出来るようになります。

実装の流れ

今回は以下のような流れで環境構築から自動キャプチャーまでの実装を行います。

  • PhantomJSをインストールする
  • CasperJSをインストールする
  • キャプチャ対象URLをJSONに定義する
  • キャプチャ実行用のプログラムを書く
  • コマンドラインからプログラムを実行する

ちなみに僕の環境はMacOSXのElCapitan(v10.11.3)となっています。
また、環境構築にあたり、パッケージ管理システムのHomebrewをインストールしている前提とします。

PhantomJSをインストールする

いきなりですが、HomebrewでPhantomJSをインストールしようとしたところ、以下のようなエラーが発生してインストール出来ませんでした。

$ brew install phantomjs
phantomjs: This formula either does not compile or function as expected on OS X
versions newer than Yosemite due to an upstream incompatibility.
Error: An unsatisfied requirement failed this build.

そのため、本家のサイトからMacOSX向けのバイナリをダウンロードします。インストールしたら、任意のディレクトリに配置します。
僕の場合は~/tool/phantomjsに一式を格納しました。

その後、実行ファイルのパスを通すために~/.bash_profileに以下を追記します。

export PATH=$HOME/tool/phantomjs/bin:$PATH

コマンドラインからphantomjs --versionと入力し、バージョン情報が表示されたらOKです。

CasperJSをインストールする

CasperJSはhomebrewを使ってインストール出来ました。
ただし、--develオプションを付けないと古いバージョンのモジュールがインストールされてしまうので必ず指定しましょう。

brew install casperjs --devel

コマンドラインからcasperjs --versionと入力し、バージョン情報が表示されたらOKです。

キャプチャ対象URLをJSONに記述する

今回は以下のような形式でJSONを準備します。
urlにキャプチャ対象のURL、fileに保存時のファイル名を記述します。

{
	"captureTarget": [
		{
			"url" : "http://google.com",
			"file": "google.png"
		},
        {
            "url": "http://yahoo.co.jp",
            "file": "yahoo.png"
        }
	]
}

キャプチャ実行用のプログラムを書く

今回は以下の点に考慮して実装します。

  • コマンドラインの引数をもとにキャプチャ時のデバイスをPC,スマホ、タブレットに変更できるようにする
  • コマンドラインのオプション指定をもとにBasic認証のID,Passを指定できるようにする
  • キャプチャ時にWebページ時に背景色が指定されていない場合は、背景色が黒色になってしまうので、プログラム側で背景色を白色に指定する

capture.jsというファイル名で以下のプログラムを記述します。

var AUTO_CAPTURE = {
	CONF: {
		DEST: './image',
		WAIT_TIME: 1
	},
	DEVICE: {
		PC: {
			folder: '/pc',
			ua: 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.63 Safari/537.36',
			width: 1280,
			height: 900
		},
		SP: {
			folder: '/sp',
			ua: 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A405 Safari/600.1.4',
			width: 320,
			height: 568
		},
		TABLET: {
			folder: '/tablet',
			ua: 'Mozilla/5.0 (iPad; CPU OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A405 Safari/600.1.4',
			width: 768,
			height: 1024
		}
	},
	init: function () {
		this.setParameters();
		this.run();
	},
	setParameters: function () {
		this.casper = require('casper').create({
			clientScripts: ['./lib/jquery-1.12.2.min.js']
		});
		this.links = require('./input/capture-list.json');
		this.captureTarget = this.links.captureTarget;
		this.basicId = this.casper.cli.options.id;
		this.basicPass = this.casper.cli.options.pass;
		this.deviceType;

		//コマンドラインの引数をもとにキャプチャ時のデバイスをPC,スマホ、タブレットに変更できるようにする
		var args = String( this.casper.cli.args );
		switch( args ) {
			case 'pc':
				this.deviceType = this.DEVICE.PC;
				break;
			case 'sp':
				this.deviceType = this.DEVICE.SP;
				break;
			case 'tablet':
				this.deviceType = this.DEVICE.TABLET;
				break;
			default:
				this.deviceType = this.DEVICE.PC;
				break;
		}
	},
	run: function () {
		var _this = this;
		this.casper.start();
		this.casper.userAgent( this.deviceType.ua );
		this.casper.viewport( this.deviceType.width, this.deviceType.height );

		//コマンドラインのオプション指定をもとにBasic認証のID,Passを指定できるようにする
		if( this.basicId && this.basicPass ) {
			this.casper.setHttpAuth( this.basicId, this.basicPass );
		}

		this.casper.each(
			this.captureTarget,
			function ( casper, link ) {
				var url = link.url;
				var file = link.file;
				casper.thenOpen( url, function ( response ) {
					//キャプチャ時にWebページ時に背景色が指定されていない場合は、背景色が黒色になってしまうので、プログラム側で背景色を白色に指定する
					casper.evaluate( function () {
						$('body').css('background-color', '#FFF');
					});
					var statusCode = response.status;
					if( statusCode === 200 ) {
						this.echo('GET: capture the "' + url + '".');
					}else {
						this.echo('ERROR: couldn\'t capture the "' + url + '".' );
					}
				});
				casper.wait( _this.CONF.WAIT_TIME, function () {
					casper.capture( _this.CONF.DEST + _this.deviceType.folder + '/' + file );
				});
			}
		);
		this.casper.run();
	}
};
AUTO_CAPTURE.init();

コマンドラインからプログラムを実行する

あとはコマンドラインから以下のコマンドを実行するだけです。

casperjs capture.js

デバイスやBasic認証を指定した場合は以下のように指定します。

//スマホでキャプチャを取得する場合
casperjs capture.js sp

//タブレットでキャプチャを取得する場合
casperjs capture.js tablet

//Basic認証のID,Passを指定する場合
casperjs capture.js --id=your_id --pass=your_pass

以下のような出力結果が表示されれば、imageフォルダ内にキャプチャした画像ファイルが保存されています。

GET: capture the "http://google.com".
GET: capture the "http://yahoo.co.jp".

いやぁ、便利ですね。これで随分と作業を効率化できそうです。

参考

http://qiita.com/hika09/items/1944530465dea06749e6