ChromiumをHeadlessにしてスクリーションショット画像を作成する

ChromiumをHeadlessにしてスクリーションショット画像を作成する

ChromiumでHeadless

最近、ChromeがHeadlessに対応しているという情報を目にしましたので備忘録として手順を共有したいと思います。

Amazon Linuxでやろうとしたけどツライ

最初にAmazon Linuxを使ってChromiumをインストールしようとしましたが、各種パッケージが足りないとエラーが続き諦めました。

Ubuntuでラクラクセットアップ

とても簡単にセットアップできましたのでこちらの方法をご紹介します。

まずはじめに適当なタイプのEC2インスタンスを起動します。サーバーの種類は、Ubuntu Server 16.04 LTS (HVM), SSD Volume Typeを選択しました。

次に、SSHでサーバーにアクセスを行い、以下の手順で必要なソフトウェアをインストールします。

$ sudo apt-get update
$ sudo apt-get install chromium-browser -y
$ sudo apt-get install fonts-ipafont-gothic fonts-ipafont-mincho -y
$ chromium-browser --version
Chromium 60.0.3112.113 Built on Ubuntu , running on Ubuntu 16.04

基本的にこれで終わりです。次に動作を確認します。

$ chromium-browser --headless --screenshot --window-size=1280,3000 https://dev.classmethod.jp/

結果として画像ファイルが保存されます。これをダウンロードして開くと以下のようになっていました。

SS 2017-09-12 1.19.42

期待通りの結果になりました!

Pythonから実行してみる

コマンドラインから実行できましたので、次にプログラムから実行してみたいと思います。まずは事前にライブラリ等をインストールします。

$ sudo apt-get install unzip
$ sudo apt-get install libgconf2-4
$ sudo apt-get install python3-selenium

$ wget https://chromedriver.storage.googleapis.com/2.32/chromedriver_linux64.zip
$ unzip chromedriver_linux64.zip
$ sudo mv chromedriver /usr/bin/

$ chromedriver --version
ChromeDriver 2.32.498513 (2c63aa53b2c658de596ed550eb5267ec5967b351)

そして、Python3のコード例です。

#!/usr/bin/python3

import os

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

CHROME_BIN = "/usr/bin/chromium-browser"
CHROME_DRIVER = os.path.expanduser('/usr/bin/chromedriver')

options = Options()
options.binary_location = CHROME_BIN
options.add_argument('--headless')
options.add_argument('--window-size=1280,3000')

driver = webdriver.Chrome(CHROME_DRIVER, chrome_options=options)

driver.get("https://dev.classmethod.jp")
driver.save_screenshot("/tmp/devio.png")
driver.quit()

以下コマンドを実行しました。ちゃんとスクリーンショットが保存されましたね。

$ python3 chromesample.py
$ ls -la /tmp/devio.png
-rw-rw-r-- 1 ubuntu ubuntu 962955 Sep 12 00:12 /tmp/devio.png

ブラウザのエラーを取得する

うまくスクリーンショットが取れましたので、ついでにWebサイトを読み込んだ時に発生したエラーを出力してみたいと思います。 先ほどのPythonコードに以下を追加するだけです。

for entry in driver.get_log('browser'):
    print(entry)

出力結果は以下のようになりました。なにやらファイルが見つからないエラーのようですね。

$ python3 chromesample.py
{'timestamp': 1505176354710, 'source': 'network', 'level': 'SEVERE', 'message': 'https://eval.classmethod.jp/entry/ - Failed to load resource: the server responded with a status of 403 ()'}
{'timestamp': 1505176354710, 'source': 'network', 'level': 'SEVERE', 'message': 'https://eval.classmethod.jp/entry/ - Failed to load resource: the server responded with a status of 403 ()'}
{'timestamp': 1505176354710, 'source': 'network', 'level': 'SEVERE', 'message': 'https://eval.classmethod.jp/entry/ - Failed to load resource: the server responded with a status of 403 ()'}

まとめ

最近のChromium(Chrome)によって、ブラウザーのスクリーンショット作成を簡単に実現できるようになりました。今回はEC2に入れて試しましたが、複数のWebサイトのスクリーンショットを自動的に収集することを考えると、DockerやLambdaによるスケジュール実行や並列実行が良さそうですね。これらのやり方は別の機会にご紹介したいと思います。

参考資料

headless chromeをPythonのseleniumから動かして引数を考えた (Ubuntu 16.04)

GOOGLE CHROME 59のHEADLESSモードを使ってみる