Yuigo・ん・・・湿っぽい

モルック、システムエンジニア、その他趣味。大学生のころから使っているので、昔の記事は恥ずかしいし今の思想とは異なっていることが多いです。

Selenium with Python: Chrome driverでWeb特定部分のスクリーンショットを取得する

はじめに

概要

PythonSeleniumをつかって、特定要素のスクリーンショットを保存する方法を書きます。

使用した環境

説明しないこと

方法

seleniumのpip install

以下はPowerShellでの実行例です。seleniumの使用自体はこれだけでOKです。

PS C:\python\pywork\selenium> pip install selenium

seleniumライブラリのインポート

seleniumを使用する場合はだいたいこの2行を書きます。理由は分かっていないのですがどこで調べてもこうなっています。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# seleniumには関係ないけど今回は以下も使用します
import os
import time

webdriverの起動

chromeとwebdriverのパスは直接指定しても問題ないですが、今回はそれぞれ環境変数から取得します。コメントアウトしていますが、headlessでもスクリーンショットの取得は可能です。

options = Options()
# chromeのパスを指定する。今回は環境変数から取得
options.binary_location = os.environ['CHROME_BINARY_LOCATION']

# headlessで使用する場合は以下の2行を利用する。
# options.add_argument('--headless')
# options.add_argument('--disable-gpu')

# webdriverを起動する。引数executable_pathにwebdriverのパスを指定する。
# こちらも環境変数から取得
driver = webdriver.Chrome(
    options=options, executable_path=os.environ['CHROME_DRIVER_PATH'])

# ドライバが設定されるまでの待ち時間を設定する。
driver.implicitly_wait(10)

画像オブジェクトの取得

画像を取得するのに特別な操作は必要ありません。seleniumでよく使う要素取得の方法を用いて、取得した要素のscreenshot_as_pngを利用するだけでOKです。

#トップ画面を開く。
driver.get('http://m4usta13ng.hatenablog.com/')

# ローディング待ち
time.sleep(3)

# タイトル部分の画像オブジェクトを取得する。
png = driver.find_element_by_id('blog-title-inner').screenshot_as_png

画像の保存

Pythonで一般的に使っているファイル操作方法がそのまま使えます。

# バイナリ書き込みモードで`open`し、保存する。
with open('./img.png', 'wb') as f:
    f.write(png)

ドライバーの終了

使用しなくなったwebdriverは終了する必要があります。

# ドライバーを終了
driver.close()
# driver.quit()

コード全体

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import os
import time

options = Options()
# chromeのパスを指定する。今回は環境変数から取得
options.binary_location = os.environ['CHROME_BINARY_LOCATION']

# headlessで使用する場合は以下の2行を利用する。
# options.add_argument('--headless')
# options.add_argument('--disable-gpu')

# webdriverを起動する。引数executable_pathにwebdriverのパスを指定する。
# こちらも環境変数から取得
driver = webdriver.Chrome(
    options=options, executable_path=os.environ['CHROME_DRIVER_PATH'])

# ドライバが設定されるまでの待ち時間を設定する。
driver.implicitly_wait(10)

#トップ画面を開く。
driver.get('http://m4usta13ng.hatenablog.com/')

# ローディング待ち
time.sleep(3)

# タイトル部分の画像オブジェクトを取得する。
png = driver.find_element_by_id('blog-title-inner').screenshot_as_png

# 画像を保存
with open('./img.png', 'wb') as f:
    f.write(png)

# ドライバーを終了
driver.close()
# driver.quit()

結果

今回はブログのタイトル部分を取得しました。

f:id:m4usta13ng:20181118172122p:plain

備考

driverの終了方法について

下記リンクを参照。driver.quit()をしないままだとセッションが残存し、メモリリークする可能性があります。

https://www.zyxware.com/articles/5552/what-is-close-and-quit-commands-in-selenium-webdriver

ウインドウサイズの変更

画面サイズによって要素も変わってくる場合は、webdriverのサイズを変更することで対応できます。

#カレントウインドウのサイズを幅:1280,高さ:720に設定する
driver.set_window_size(1280, 720)

参考

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

set_window_size-Python

7. WebDriver API — Selenium Python Bindings 2 documentation