PHP
JavaScript
api
GoogleAppsScript
PhantomJS

各種スクレイピングのために、レンダリング後(JavaScript実行後)のHTMLを出力するAPIを作る

More than 1 year has passed since last update.


はじめに

スクレイピングをしようとして、いざJavaScriptやPHPやGoogle Apps ScriptでHTMLの取得をすると、JavaScript実行前のソースが取得されてしまう。Seleniumなどを使えばいいが、環境を構築したり起動させっぱなしにしなければいけないので、コストやハードルが高いと感じる。

なのでレンダリング後のHTMLを取得してくれるAPIがあれば様々なプログラムから参照でき、スクレイピングが捗るのではないかと思う。

自分はGoogle Apps Scriptで株価を取得しようとしたところ、参照先がAjaxで株価を動的に生成していたため、スクレイピングできなかっためこのようなAPIが欲しいと思った。

今回は、簡単に実装したかったので、コマンドラインブラウザとしてPhantomJS、API実装としてPHPを使用した。


やりたいこと


  • 簡単にレンダリング後のHTMLを取得できるようにする

  • APIサーバーのメモリ使用量できるだけを抑える

  • GoogleAppsScriptでレンダリング後のHTMLを取得できるようにする


開発環境


  • CentOS 7

  • PhantomJS v2.1 (コマンドラインベースのブラウザ)

  • Httpd 2.4

  • PHP 7.0 (API開発用)


実装の手順

CentOSにHttpdとPHPはインストールされている前提とする


PhantomJSのインストール

Macの場合はbrew installで簡単にインストールできる

$ sudo yum install epel-release 

$ sudo rpm -ivh http://repo.okay.com.mx/centos/6/x86_64/release/okay-release-1-1.noarch.rpm
$ sudo yum search all phantomjs


PhantomJSでレンダリング後のHTMLを取得する

作業ディレクトリ(/var/www/html/rendered-html/など)に以下のファイルを作成する

下記のソースコードでは、

1. 第二引数で指定したURLの取得

2. ページを取得

3. ページの評価(evalute)を行い、レンダリング後のhtmlタグ内のソースを取得

4. htmlをコマンドラインに出力する

を行なっている。


phantomjs-get-html.js

var page = require('webpage').create();

var system = require('system');
var args = system.args;

var url = args[1];
if (url == undefined) {
phantom.exit();
}

page.open(url, function(status) {
if (status === 'success') {
var body = page.evaluate(function() {
return '<html>' + document.getElementsByTagName('html')[0].innerHTML + '</html>';
});
console.log(body);
}
phantom.exit();
});


上記のソースコードを実行すると、HTMLが取得できる

$ phantomjs phantomjs-get-html.js http://google.com

<html><head><meta content="世界中のあらゆる情報を検索するためのツールを提供しています。さまざまな検索機能を活用して、お探しの情報を見つけてください。" name="descrip...


PHPからPhantomJSを実行する

PHPのPhantomJSを使うという方法もあったが、Composerが多少コストが高いため使用せず

execでPhantomJSを実行し、最終的にJSON形式でHTMLを出力している


index.php

<?php

header('content-type: application/json; charset=utf-8');

//URLの取得 URLがない場合エラー
if(!isset($_GET['url'])){
statusFailure();
}
$url = $_GET['url'];

//PhantomJSの実行
$cmd = 'phantomjs phantomjs-get-html.js ' . $url;
exec($cmd, $arr);

//データがない場合エラー
if(!$arr){
statusFailure();
}

//文字列結合
$html = '';
foreach($arr as $val){
$html .= $val;
}

//JSONにてHTMLを出力
echo json_encode([
'status' => 'success',
'html' => $html
]);

//エラー出力関数
function statusFailure(){
echo json_encode([
'status' => 'failure',
'html' => ''
]);
die();
}



実行結果

ブラウザにて、http://IPアドレス/rendered-html/?url=http://google.com にアクセスする

正常に取得できれば、successがかえってきて、HTMLが取得できる


実行結果

{"status":"success","html":"<html><head><meta content=\"\u4e16\u754c...



おわりに

クライアントJavaScriptやGASでもレンダリング後のスクレイピングができるようになったので、やれることが多くなった。今後はクリックやDOM操作もできるAPIに発展させていきたい。