CUBE SUGAR CONTAINER

技術系のこと書きます。

Python: Selenium + Headless Chrome で Web ページ全体のスクリーンショットを撮る

スクレイピングした Web サイトからページ全体のスクリーンショットを撮影したい機会があった。 そこで Selenium の Python バインディングと Headless Chrome を使ったところ実現できたのでメモしておく。 ちなみに、ページ全体でなければ Headless Chrome 単体でも撮れる。 その方法についても末尾に補足として記載しておいた。

使った環境は次の通り。

$ sw_vers             
ProductName:    Mac OS X
ProductVersion: 10.13.5
BuildVersion:   17F77
$ python -V   
Python 3.6.5
$ pip list --format=columns | grep -i selenium
selenium   3.13.0 
$ chromedriver --version
ChromeDriver 2.40.565386 (45a059dc425e08165f9a10324bd1380cc13ca363)

下準備

まずは Chrome Driver をインストールしておく。

$ brew cask install chromedriver

続いて Selenium の Python バインディングをインストールする。

$ pip install selenium

インストールできたら Python の REPL を起動する。

$ python

これで下準備ができた。

スクリーンショットを撮る

まずは必要なパッケージをインポートする。

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

続いて Chrome Driver を Headless モードで起動する。

>>> options = Options()
>>> options.add_argument('--headless')
>>> driver = webdriver.Chrome(chrome_options=options)

スクリーンショットを撮りたいページの内容を取得する。

>>> driver.get('https://www.python.org')

続いてページ全体の横幅と高さを取得したら、それをウィンドウサイズとしてセットする。 これによって Web ページ全体のスクリーンショットを一つの画像として撮影できる。 ちなみに Headless モードにしていないと、ここで設定できる値がモニターの解像度に依存してしまう。

>>> page_width = driver.execute_script('return document.body.scrollWidth')
>>> page_height = driver.execute_script('return document.body.scrollHeight')
>>> driver.set_window_size(page_width, page_height)

ウィンドウサイズを変更したら、ページ内の要素が読み込まれるまで少し待った方が良い。 読み込みを待ちたい要素があらかじめ分かっているなら Wait をかけることもできそう。

5. Waits — Selenium Python Bindings 2 documentation

あとはスクリーンショットを撮るだけ。 上手くいけば返り値として True が返ってくる。

>>> driver.save_screenshot('screenshot.png')
True

上手くいったらドライバと REPL を終了する。

>>> driver.quit()
>>> exit()

撮影した画像を確認してみよう。

$ open screenshot.png

次のような結果が得られた。

f:id:momijiame:20180728183758p:plain

めでたしめでたし。

補足

ちなみに Headless Chrome 単体でもスクリーンショット自体は撮れる。 ただし、このやり方では残念ながらページ全体を撮ることはできない。

$ alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
$ chrome --headless --disable-gpu --screenshot https://www.python.org

こんな感じになっちゃう。

f:id:momijiame:20180728184056p:plain

参考

developers.google.com