ブラウザのオートメーションへの道(2017年6月版)
自分なりにいろいろ調べた結果をまとめます。 ただし、これは現時点での状況からわかったことで、賞味期限は比較的短いだろうと思います。
ウェブ・ブラウザを、プログラムから操って、自動処理をしたいと思いました。 プログラムはjavascriptで書きます。 ある程度の複雑な手順の処理が想定され、特にスクリーンショットの取得が重要と考えています。
実ブラウザを使ったE2Eテストという技術があり、そのやり方が非常に参考になりますが、やりたいことの内容は結構違ってきます。
Ubuntuを使います。
Dockerを使って実行環境をコンテナ化します。
ChromeもしくはChromiumを、Headlessモードで使うのが良さそう。
普段使っているデスクトップ環境と同じPCで動かしますが、普段の環境と干渉したくありません。
Webアプリケーション実行環境向けのDockerコンテナの中に、Chrome v59 をインストールしてみました。 ワンライナーのコマンドラインから、任意のURIのサイトのスクショを撮ることができました。
次にリモートからDevTool経由で操縦してみました。 しかし、WebGL対応が不十分のようで、特定のWebサイトでは途中で処理が止まってプロセス毎おちてしまいました。 これに対する解決策としては、以下が考えられます。
- 依存するライブラリを個別に調査、インストールする
- Xvfbを使って、デスクトップ環境を整備する
前者は手間が煩雑です。またバージョンが進むと無駄になる可能性があります。 後者は、結局それってHeadlessはどこ行ったの?という疑問が湧きます。結局インストールするものが多く、重くなるってことです。 コンテナのディスク・イメージを小さく保ちたいので、重要な観点です。
Xvfbを使ってHeadlessを実現するのは古来からある由緒正しき方法なのですが、物理画面を使わないという事を除いては、普通にデスクトップ環境を別途構築することと等価なので、今の私の望むものとは離れてしまいます。
もっとも先に挙げた問題は、Chromeの開発が進んで成熟すれば、近いうちに改善することが期待できます。
なお、これとは別に以下のことも模索したのですが、挫折しています。
- VNCを使って、コンテナ内のブラウザをリモートから操作する
- デスクトップ環境が必要
- SSHのX転送を使って、同じくコンテナ内のブラウザをリモートから操作する
- コンテナにはXの環境がなく、従って必要なライブラリが足りず、実現できなかった
- xauthがない!
ブラウザの自動操縦に関するパイオニア的存在。 だがしかし、そもそもSelenium自体がデカイのであまり触りたくない。
- Selenium + 普通のブラウザ(Chrome、Firefox、Edge)
- 自動操縦できますが、デスクトップ環境でブラウザの画面を開いて、それを操縦するイメージです
- 普段遣いのデスクトップでそういうのは邪魔になります
- Selenium + Xvfb + 普通のブラウザ
- 上記と似ていますが、普段のデスクトップ環境の代わりに、仮想の(物理的には存在しない)デスクトップを使います
- 使い勝手は求めるものに近づきますが、環境構築が結局はデスクトップ環境を構築するそれに近く、なんとなく重い
- Selenium + Xvfb + Headless Chrome
- 同
- Selenium + Headless Chrome
- これはまだ調べてない。たぶんまだお手軽な方法が確立されていないかも
もう少し「ブラウザのオートメーション」の原点に立ち返ったとき、PhantomJSは非常に注目に値します。 十分な機能を備え、エコシステムは結構充実しています。
参考:Ingress Ice - PhantomJSを使って、インテルマップのスクショを連続的に自動で取得するアプリ
しかし次のような点が気になります。
- 開発が停滞している
- 黒幕であるQtWebkitがそもそも捨てられた存在なので、仕方がない
- 生のPhantomJS向けスクリプトは、書くのがツラい
- 実は「PhantomJSはNodeスクリプトではない」ので、Node.jsのエコシステムはそのままでは使えない(ラッパーはある)
CasperJSは、PhantomJSのラッパーで、書きやすいです。 先月はこれを使ってプロトタイプを作成していましたが、使い勝手が良く、欲しかった機能が備わっており、まずまずの印象です。 PhantomJSの負の面は引きずっています。
CasperJSと同じく、元々PhantomJSのラッパーでした(v1)。書きやすいようです。 v2になって、Electronベースに移行しました。 Electronは、Node.js+Chromiumという、現在進行系で最先端のテクノロジーを使っているため、PhantomJSよりもさらにデスクトップの実ブラウザに近いです。 しかし、Electronはいまのところ、デスクトップ環境が必要です。(そもそもデスクトップ向けのアプリを作るためのものなので) Headless対応が進行中のようです。
Node.jsの環境の中から、Headless Chromeを操縦するライブラリです。 Nightmare.jsと同じように書けることを目指しているようです。 ぱっと見ですが、必要な機能は揃っているようでした。 ただし、新顔なだけあって、実績に不安があります。参考例がなかったり、ドキュメントが整備されていなかったりするようです。
これ以外にも、プラウザ・テストを実行するためのイロイロや、Headless Chromeを操縦するためのアレコレについてもざっくり調べましたが、期待が持てなさそうだったり、学習コストが大きそうで手付かずだったりします。
そのうえで、まとめ。
今すぐ始める場合は、CasperJSかChromyが良いように思います。 過去の実績や参考例の充実であれば、CasperJSになります。 将来性を取ってChromyを選択しつつ、ElectronのHeadless対応を待って、後々Nightmare.jsに移行するということも、悪くないと思います。
以上でした。
- https://developers.google.com/web/updates/2017/04/headless-chrome?hl=ja
- https://www.npmjs.com/package/chromy
- http://piacco.github.io/2014/11/30/docker%E3%81%A7GUI%E3%81%AE%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%EF%BC%88chromium/
- https://www.npmjs.com/package/chrome-remote-interface
- https://github.com/phusion/passenger-docker
- https://github.com/ariya/phantomjs/blob/master/src/modules/child_process.js