各種スクレイピングのために、レンダリング後(JavaScript実行後)のHTMLを出力するAPIを作る
api PhantomJS JavaScript GoogleAppsScript PHP
はじめに
スクレイピングをしようとして、いざJavaScriptやPHPやGoogle Apps ScriptでHTMLの取得をすると、JavaScript実行前のソースが取得されてしまう。Seleniumなどを使えばいいが、環境を構築したり起動させっぱなしにしなければいけないので、コストやハードルが高いと感じる。 なのでレンダリング後のHTMLを取得してくれるAPIがあれば様々なプログラムから参照でき、スクレイピングが捗るのではないかと思う。 自分はGoogle Apps Scriptで株価を取得しようとしたところ、参照先がAjaxで株価を動的に生成していたため、スクレイピングできなかっためこのようなAPIが欲しいと思った。 今回は、簡単に実装したかったので、コマンドラインブラウザとしてPhantomJS、API実装としてPHPを使用した。
やりたいこと
開発環境
実装の手順
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をコマンドラインに出力する を行なっている。
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を出力している
<?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に発展させていきたい。