Selenium でページ全体のスクリーンショットを撮る (Python)

Pocket

02/25 更新: Chrome で水平スクロールバーがスクリーンショットに写ってしまう問題を修正。

Selenium を使って自動テストを行っていると、表示された結果のスクリーンショットを撮って保存したい時がままある。

ところが、 Chrome や Firefox で Selenium のスクリーンショット機能を使うと、 ウィンドウに表示されている内容だけしか取得できない。
(ブラウザやそのバージョンによって動作が異なる)


この記事によると、これは Selenium の仕様らしい。

ブラウザごとの挙動の差はさておき、 ウィンドウサイズでの取得となってしまう Chrome と Firefox で、何とかページ全体のスクリーンショットを保存したい。
ここでは、 Selenium の Python Binding を使って、実現する方法を考えてみる。

実装

ウィンドウの高さをページの高さと同じに変えようとしてみても、 ウィンドウはデスクトップの高さより大きくならない。
仕方がないので、ウィンドウ範囲のスクリーンショットを保存して、ウィンドウの高さ分スクロールして... を繰り返し、 最後にくっつけるという強引な方法で解決してみよう。

ページ最後に到達すると、スクロール量がウィンドウの高さより小さい点には注意が必要だ。
また、 最近の高DPIディスプレイで画面をスケーリングしていると、 Javascript で取得できるウィンドウの高さと、実際にスクリーンショットで取得できる高さにズレが生じてしまうので、それについてもケアが必要だ。

Python の Pillow ライブラリを使えば、以下のようにそこそこシンプルに実装できる。

スクリーンショットを撮りたいページを表示させた webdriver を、 get_full_screenshot_image 関数の引数に与えてやれば、 Pillow の Image オブジェクトが手に入る。
あとはそれを image.show() で表示するなり、 image.save(fp) で保存するなりすればよい。

Python 2.7 と Python 3.6 以降 のどちらでも動くはずだ。

ブラウザは以下のいずれかの組み合わせで動くことを確認している。

  • Chrome 71.0 + ChromeDriver 2.45
  • Firefox 64.0 + GeckoDriver 0.23.0

手元ではなぜか Internet Explorer Driver が動かなかったので IE では試していないが、 IE では、 おそらく Selenium が直接ページ全体のスクリーンショットを返すため、うまく動かないだろう。

ちなみに、ヘッドレスモード (GUI表示なし) が使えるのであれば、 以下の記事のようにウィンドウサイズをページサイズまで最大化してしまうほうが手っ取り早いだろう。

コメントを残す

メールアドレスが公開されることはありません。

This site uses Akismet to reduce spam. Learn how your comment data is processed.