📸

Webサイトのスクリーンショットを自動化する方法

2021/03/28に公開約5,500字6件のコメント

Web サイトのスクリーンショットはブラウザの開発ツールや拡張機能を利用すれば手軽に行えます。しかし、あらかじめスクショしたいサイトやページが決まっていてかつ複数ページある場合では都度ページを開いて作業しているとそれなりに時間がかかります。

この記事ではそんな手動でのスクリーンショット作業を自動化させる方法を紹介します。
知らない単語が途中出てきても何ができるのかイメージだけつかんでもらえれば大丈夫です。

実行環境の用意

今回スクリーンショットの自動化を Python という言語で行います。「Python って何!?」という方は以下リンクの情報を軽く見ておいてもらえると多少理解が進むかと思います。

https://www.python.jp/pages/about.html

手元のローカル PC で今回やるような処理を実行するには Python 自体をインストールする必要があります。この記事ではそのような環境構築の手間を省くため Google が提供する Colaboratory と呼ばれるサービスを利用します。

https://colab.research.google.com/notebooks/intro.ipynb

Colaboratory の利用方法は以下記事の一部を参照してみてください。ファイルの準備まで確認できれば OK です。

https://zenn.dev/kazuki_tam/articles/23410c1a4fe91f661db9#colaboratoryとは

スクリーンショット自動化スクリプトの作成

Colaboratory で新規ファイルの用意ができたら今回やりたいことの整理をしたいと思います。
最低限やりたいことは主に以下の 3 つです。

  • サイト URL を指定するだけでスクリーンショットを自動実行したい
  • 取得した画像を一括ダウンロードしたい
  • ウインドウサイズを指定してスクリーンショットを撮りたい

すぐに利用したい方はコピペで利用できるので「スクリーンショット自動化スクリプトの利用方法」から読み進めてください。

必要ファイルやライブラリの読み込み

Colaboratory は標準で日本語フォントが入っていないようで、フォントを入れずに動かすと文字化けしてしまいます。(2021/03/28)

# 日本語フォントインストール
!apt-get -y install fonts-ipafont-gothic
!apt-get -y install fonts-ipafont-mincho

スクリーンショットの自動化スクリプトをすべて一からプログラムを書いていくとめちゃくちゃ時間がかかってしまうので、ライブラリと呼ばれる複雑な処理を抽象化して使いやすくしたプログラムを利用します。

https://ja.wikipedia.org/wiki/ライブラリ#:~:text=ライブラリ(英%3A library)は,コードの集まりと言える。

ブラウザ操作を自動化させるため Selenium をインストールします。Selenium はブラウザ操作を自動化させるのに必要なフレームワークです。

https://qiita.com/Chanmoro/items/9a3c86bb465c1cce738a
https://www.selenium.dev/
# seleniumインストール
!apt-get update
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
!pip install selenium

# ライブラリインポート
from google.colab import files
import time
import shutil
import os

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# Chromeヘッドレスモード起動
options = webdriver.ChromeOptions()
options.headless = True
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver',options=options)
driver.implicitly_wait(10)

ブラウザを裏側で起動させてスクリーンショットをとるために Headless Chrome を利用します。
Headless Chrome はブラウザーの UI を利用せずにブラウザ操作することを可能にします。
たとえば「Chrome を立ち上げてサイトにアクセスして・・・」といった作業をコマンドで指定できます。

https://developers.google.cn/web/updates/2017/04/headless-chrome?hl=ja

スクリーンショットを撮りたいサイトリストを以下のように記述します。

# 対象URL
urls = ['https://example.com', 'https://example.com/about/']

次に調整用の変数を定義しておきます。変数を定義しておくことで、ブラウザのウインドウサイズやファイル名を後から調整しやすくします。

ファイル名の接頭辞は fileNamePrefix で調整できます。screen とすると screen-1.png のように連番で保存されます。

ウインドウ幅 375px でスクリーショットを撮りたい場合は windowSizeWidth = 375 と指定します。ウインドウ幅を指定した場合、 screen-1200-1.png のようにサイズがファイル名に付与されます。

ウインドウの高さを指定したい場合も幅と同様です。
windowSizeHeight = 1000

ファイル名が被らないように連番を付与させるため番号の初期値を指定します。
shotNum = 0

# ファイル名接頭辞
fileNamePrefix = "screen"

# ウインドウ幅指定
# 初期値: False, スマホ: 375
windowSizeWidth = False
# windowSizeWidth = 1200

# ウインドウ高さ指定
# 初期値: False
windowSizeHeight = False
# windowSizeHeight = 1000

# 連番初期値
shotNum = 0

ダウンロードフォルダーの作成を以下の処理で行います。

# ダウンロードフォルダ作成
folderCheck = os.path.exists('screen-shot')
if folderCheck:
  shutil.rmtree('screen-shot')
os.mkdir('screen-shot')

urls で定義したサイトにアクセスし、スクリーショットを撮る処理が以下に記述されています。
スクロールされてから要素が表示されるような表現に対応するため、わざとサイト下部までスクロールする処理を入れています。

# 繰り返し処理
for url in urls:
  # パス指定
  folderPath = 'screen-shot/' + fileNamePrefix + '-' + str(windowSizeWidth) + '-' if windowSizeWidth else 'screen-shot/' + fileNamePrefix + '-'

  # サイトURL取得
  driver.get(url)
  WebDriverWait(driver, 15).until(EC.presence_of_all_elements_located)

  # ウインドウ幅・高さ指定
  windowWidth = windowSizeWidth if windowSizeWidth else driver.execute_script('return document.body.scrollWidth;')
  windowHeight = windowSizeHeight if windowSizeHeight else driver.execute_script('return document.body.scrollHeight;')
  driver.set_window_size(windowWidth, windowHeight)

  # スクロール処理
  driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')

  # 処理後一時待機
  time.sleep(3)

  # ファイル連番追加
  shotNum += 1
  shotNumStringified = str(shotNum)

  # スクリーンショット格納
  driver.save_screenshot(folderPath + shotNumStringified + '.png')

  # サーバー負荷軽減処理
  time.sleep(1)

# ブラウザ稼働終了
driver.quit()

最後に保存したスクリーンショットを zip ファイルにまとめてダウンロードする処理を記述します。

# zipファイル変換ダウンロード
!zip -r download.zip screen-shot
files.download('download.zip')

以上でコードの記述は完了です。

スクリーンショット自動化スクリプトの利用方法

サイト URL を指定するだけでスクリーンショットを自動実行し、一括でファイルをダウンロードできます。次の完成スクリプトをそのままコピペして利用できます。すぐに利用したい方は対象 URL だけ適宜調整してください。

処理の実行

処理を実行する際は赤枠の ▷ ボタンを押下してください。

ダウンロードファイルの管理

スクリーンショットされた画像ファイルは download.zip ファイルに格納されます。
意図的に格納ファイルを削除してリセットしたい場合は左サイドバーの 🗂 アイコンを押下し、download.zip ファイルを削除できます。

まとめ

アニメーションで画面が大きく変わるサイトではうまくスクリーンショットを取れないケースがあるかもしれません。そのような場合は処理のタイミングを遅らせてみるなど調整してみてください。
Web 制作の現場ではスクリーンショットをとる作業がよくあるかと思います。今回紹介した内容が時間の効率化に繋がれば幸いです。

Discussion

yonemotoさま
記事拝見して、とても関心を持ちました。いきなりですが、薄謝ではありますがご提供させていただいたうえで、特定のサイト(観光予報プラットフォーム、公益社団日本観光振興協会)の向こう3か月の観光需要の予測画面を、約1週間おきにスクショし続けるプログラムを組んでいただくことは可能でしょうか?

コメントありがとうございます!この記事で紹介するColaboratoryは定期実行に対応していないため、記載いただいた要件ですと一からスクラッチで開発するより以下のようなサービスを使われるのが良いかと思います。

https://pashaco.app/

ご親切にありがとうございました。よく見てみます。

えーと
seleniumのv4系を入れたらoptions.add_argument("--headless")が使えなくなっており、options.headless = Trueでできるらしいです。

ご指摘ありがとうございます。取り急ぎ修正しました。

僕も同じように混乱したのでお互い様ですね。。。

ログインするとコメントできます