2018年5月6日: Headless ChromeがStableになった後の現状に合わせた新しい記事を書きました。こちらもご参照ください。
先日PhantomJSのVitalyさんがメンテナーを引退するという話が話題になっていました。ヘッドレスなブラウザーを気軽に使う手段としてPhantomJSにはお世話になりました。今後はHeadless Chromeを使って欲しいとのことなので、試してみました。
Node.jsを使うサンプルは多く見つかりますが、諸事情でPythonを使いたかったので、ここではSelenium経由でHeadless Chromeを使います。
Headless Chromeとは
Google Chrome 59から使えるようになる予定の、画面を表示せずに動作するモードです。自動テストやWebスクレイピングなどに役立ちます。
2017年4月28日現在、Mac版とLinux版のDevチャネルまたはCanaryチャネルで使用できるようです。私はMac版のCanaryチャネルで試しました。Windows版のCanaryチャネルでも試してみましたが--headless
を指定しても画面が表示されてしまいました。そのうち使えるようになると思います1。
とりあえずNode.jsのchrome-remote-interfaceから使うのが簡単かつ情報も多いので、ここから試してみると良いでしょう。
- Headless Chromium
https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md - ChromeのヘッドレスモードをMacOSXで試してみた - Qiita
http://qiita.com/g_ryotaro/items/da3cf376890bf3366a62
ちなみに、昔からXvfbなどの仮想ディスプレイにChromeを起動してヘッドレスで使っていた例も多くあるようです。ググる時はどちらの意味で使われているか確認しましょう。
SeleniumからHeadless Chromeを使う
Headlessだからと言って、通常のChromeを使うときと大きく変わるわけではありません。SeleniumからChromeDriverを通して、Chromeを操作します。ChromeのWebDriverの作成時に引数としてChromeOptionsを渡し、その中で実行するChromeのパスや引数を指定します。
環境
試した環境は以下のとおりです。
- OS X El Capitan
- Google Chrome Canary 60.0.3082.0
- ChromeDriver 2.29
- Python 3.6.0
- Selenium 3.4.0
準備
前提: Python 3.6はインストールされている。
-
Google Chrome Canaryをインストールする(Stableチャネルで
--headless
が使えるようになったら不要なはず)。CanaryはStableと共存できる。 - ChromeDriverをダウンロードして、PATHの通ったところに置く。
- Seleniumをインストールする(ここでは仮想環境を使う)。
(venv) $ pip install selenium
サンプルコード
Google検索を行います。Pythonクローリング&スクレイピングのサンプルコードを改変したもので、PhantomJSを使っていた箇所をHeadless Chromeに置き換えてみました。
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
options = Options()
# Chromeのパス(Stableチャネルで--headlessが使えるようになったら不要なはず)
options.binary_location = '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary'
# ヘッドレスモードを有効にする(次の行をコメントアウトすると画面が表示される)。
options.add_argument('--headless')
# ChromeのWebDriverオブジェクトを作成する。
driver = webdriver.Chrome(chrome_options=options)
# Googleのトップ画面を開く。
driver.get('https://www.google.co.jp/')
# タイトルに'Google'が含まれていることを確認する。
assert 'Google' in driver.title
# 検索語を入力して送信する。
input_element = driver.find_element_by_name('q')
input_element.send_keys('Python')
input_element.send_keys(Keys.RETURN)
time.sleep(2) # Chromeの場合はAjaxで遷移するので、とりあえず適当に2秒待つ。
# タイトルに'Python'が含まれていることを確認する。
assert 'Python' in driver.title
# スクリーンショットを撮る。
driver.save_screenshot('search_results.png')
# 検索結果を表示する。
for a in driver.find_elements_by_css_selector('h3 > a'):
print(a.text)
print(a.get_attribute('href'))
driver.quit() # ブラウザーを終了する。
以下のように実行すると、ブラウザーの画面が表示されない状態で検索結果が出力されました。
(venv) $ python selenium_google.py
Python - ウィキペディア
https://ja.wikipedia.org/wiki/Python
Python チュートリアル — Python 3.6.1 ドキュメント
http://docs.python.jp/3/tutorial/
Python基礎講座(1 Pythonとは) - Qiita
http://qiita.com/Usek/items/ff4d87745dfc5d9b85a4
初心者でもほぼ無料でPythonを勉強できるコンテンツ10選 - paiza開発日誌
http://paiza.hatenablog.com/entry/2015/04/09/%E5%88%9D%E5%BF%83%E8%80%85%E3%81%A7%E3%82%82%E3%81%BB%E3%81%BC%E7%84%A1%E6%96%99%E3%81%A7Python%E3%82%92%E5%8B%89%E5%BC%B7%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%8410
【入門者必見】Pythonとは?言語の特徴やシェア、仕事市場を徹底解説 | 侍 ...
http://www.sejuku.net/blog/7720
Pythonに咬まれるな : 注意すべきセキュリティリスクのリスト | プログラミング ...
http://postd.cc/a-bite-of-python/
Pythonとは - はてなキーワード - はてなダイアリー
http://d.hatena.ne.jp/keyword/Python
Python入門から応用までの学習サイト
http://www.python-izm.com/
Pythonで学ぶ 基礎からのプログラミング入門 (1) Pythonでプログラミングを ...
http://news.mynavi.jp/series/python/001/
Download Python | Python.org
https://www.python.org/downloads/
PhantomJSとの差異など
- 実行中に画面は表示されないが、DockにはChromeのアイコンが表示される。
- 明示的に
driver.quit()
としないとChromeは終了しない。 - PhantomJSだと検索語を入力して送信した時にonloadまで待ってくれていたが、ChromeだとAjaxで遷移するので別途待つ必要があった(これはGoogleの挙動の違いによるものでChromeやGoogleの問題ではない)。
ヘッドレスモードだと、save_screenshot()
で撮影したスクリーンショットが1x1の画像になってしまった。何かオプションが必要なのかも。
まとめ
少なくともOS Xでは気軽にHeadless Chromeを使用できました。Stableチャネルで使用できるようになればさらに簡単です。--headless
オプションを取り除けば画面が表示されるので、デバッグしやすそうなのも嬉しいです。