2018/03/26 追記
これからやるなら Headless Chrome を Node.js から操作する、というのが王道でしょうか。
この記事でわかること
- 自分で書いた Phantom JS スクリプトを PHP から実行する方法
- PHP から Phantom JS スクリプトにパラメータを渡す方法
概要
PHP Phantom JS ではスクリプトのテンプレートが予め準備されており、「URL指定で特定のページにアクセスし、特定の要素を取り出す」のような用途ではパラメータを渡すだけで簡単に目的を実現できます。
その一方で、自分で作成した Phantom JS スクリプトを実行したり、PHP からパラメータを渡したりする仕組みも備えており、割と自由自在に使うことができます。
この記事ではその方法を説明します。
インストール
公式ページの記述に従って、Composer を使ってインストールします。
一緒に Phantom JS 自体の実行ファイルもついてきます。
// ...
"scripts": {
"post-install-cmd": [
"PhantomInstaller\\Installer::installPhantomJS"
],
"post-update-cmd": [
"PhantomInstaller\\Installer::installPhantomJS"
]
},
// ...
"config": {
"bin-dir": "bin"
},
// ...
composer require "jonnyw/php-phantomjs:4.*"
任意のスクリプトを実行
実行したいスクリプト( .js )の拡張子を .proc に変えておきます。
また、実行権限を付与します。
cp your_script.js /path/to/directory/your_script.proc
chmod 755 /path/to/directory/your_script.proc
以下のように PHP から Phantom JS を実行することができます。
<?php
use JonnyW\PhantomJs\Client;
use JonnyW\PhantomJs\DependencyInjection\ServiceContainer;
// スクリプトファイル(.proc)が設置してあるディレクトリ
$location = '/path/to/directory';
$serviceContainer = ServiceContainer::getInstance();
$procedureLoader = $serviceContainer->get('procedure_loader_factory')->createProcedureLoader($location);
$client = Client::getInstance();
// スクリプトファイル名を指定(拡張子は除く)
$client->setProcedure('your_script');
$client->getProcedureLoader()->addLoader($procedureLoader);
$request = $client->getMessageFactory()->createRequest();
$response = $client->getMessageFactory()->createResponse();
// スクリプト実行
$client->send($request, $response);
// 結果を取得(Phantom JS の標準出力)
$result = $response->getContent();
PHP からパラメータを渡す
PHP から Phantom JS スクリプトにパラメータを渡したい場合、まず JonnyW\PhantomJs\Http\Request
を継承したクラスを作成します。
※公式ドキュメントでは JonnyW\PhantomJs\Messages\Request
を継承するように書かれていますが、JonnyW\PhantomJs\Http\Request
を継承しましょう。
パラメータを設定する際には getter に対応した setter メソッドを作るのが無難でしょう。
<?php
use JonnyW\PhantomJs\Http\Request;
class CustomRequest extends Request
{
// パラメータを格納するプロパティ
protected $hoge;
// パラメータを設定するメソッド
public function setHoge($hoge)
{
$this->hoge = $hoge;
}
// パラメータにアクセスするメソッド(スクリプト側で呼び出す)
public function getHoge()
{
return $this->hoge;
}
}
上記クラスを作成後、先程の PHP ソースを次のように書き換えます。
<?php
use JonnyW\PhantomJs\Client;
use JonnyW\PhantomJs\DependencyInjection\ServiceContainer;
// スクリプトファイル(.proc)が設置してあるディレクトリ
$location = '/path/to/directory';
$serviceContainer = ServiceContainer::getInstance();
$procedureLoader = $serviceContainer->get('procedure_loader_factory')->createProcedureLoader($location);
$client = Client::getInstance();
// スクリプトファイル名を指定(拡張子は除く)
$client->setProcedure('your_script');
$client->getProcedureLoader()->addLoader($procedureLoader);
// createRequest() の代わりに CustomRequest インスタンスを生成
$request = new CustomRequest();
// hoge パラメータに 1 を設定
$request->setHoge(1);
$response = $client->getMessageFactory()->createResponse();
// スクリプト実行
$client->send($request, $response);
// 結果を取得(Phantom JS の標準出力)
$result = $response->getContent();
これで、Phantom JS スクリプトからパラメータにアクセスする準備が整いました。
Phantom JS スクリプトでパラメータにアクセス
スクリプトファイルの先頭と末尾に次の記述を追加します。
[% autoescape false %]
{% autoescape false %}
/* ... スクリプト本体 */
{% endautoescape %}
[% endautoescape %]
スクリプトでパラメータにアクセスしたい部分で次のように記述します。
/* ...(略) */
var hoge = {{ input.getHoge() }};
/* ...(略) */
{{ }}
の中身がそのまま入れ替わる形なので、hoge
パラメータが文字列であるなら var hoge = '{{ input.getHoge() }}';
のように書く必要があります。
気をつけるべきこと
- スクリプトは、エラーが起きても
phantom.exit()
が呼ばれるようにしておく必要がある- そうしないといつまでたってもスクリプトの実行が終了しない
- スクリプトファイルのコメントは
/* */
形式にしないといけない-
//
形式のコメントがあると構文エラーになる模様
-