「ブラウザで見たままのスクリーンショットが欲しい」
このシンプルな要望に応えるのは、Seleniumです。
もちろん、文字化けや文字フォントの問題とは無縁です。
本記事では、キレイなスクリーンショットを取得する方法を解説します。
コピペで使えるコードも載せています。
本記事の内容
- Seleniumを準備する
- PythonでAmazonのスクリーンショットを取得する
- PythonでTwitterのスクリーンショットを取得する
それでは、上記に沿って解説していきます。
Seleniumを準備する
Pythonでスクリーンショットを撮るには、Seleniumを利用します。
そのため、Seleniumを利用できることが前提となります。
Seleniumのインストールに関しては、次の記事をご覧ください。
以上、Seleniumの準備について説明しました。
次は、スクリーンショットを撮っていきます。
PythonでAmazonトップのスクリーンショットを取得する
このスクリーンショットは、次のコードで取得しています。
screenshot_1.py
from selenium import webdriver from selenium.webdriver.chrome.options import Options CHROMEDRIVER = "chromedriver.exeのパス" URL = "https://www.amazon.co.jp/" options = Options() # スクロールバーを非表示にする options.add_argument('--hide-scrollbars') # シークレットモードでChromeを起動する options.add_argument('--incognito') # ブラウザを表示しない options.add_argument('--headless') driver = webdriver.Chrome(CHROMEDRIVER, options=options) # ウィンドウサイズ=画像サイズ driver.set_window_size(1024, 768) # 対象ページへアクセス driver.get(URL) # スクリーンショットを取得 driver.save_screenshot('result.png') driver.quit()
次の箇所が理解できない場合は、上記で紹介した記事をご覧ください。
CHROMEDRIVER = "chromedriver.exeのパス"
プログラムの内容は、コメントで確認してください。
できる限りでコメントをつけています。
どうでしょうか?
なんてことないですよね。
でも、このコードだとスクリーンショットを取得できないケースがあります。
次は、そのケースについて確認しましょう。
PythonでTwitterのスクリーンショットを取得する
先ほどのプログラム(screenshot_1.py)における「URL」の値を変更します。
URL = "https://twitter.com/AmazonJP"
そのように変更して取得したスクリーンショットが、上の画像となります。
なぜ、このような空っぽの画面になるのでしょうか?
その理由は、タイミングにあります。
Twitterは、Ajaxにより動的にコンテンツを表示しています。
そのため、コンテンツが表示し終わるまでにしばらく時間がかかります。
screenshot_1.pyのプログラムでは、Ajax処理の途中でスクリーンショットを撮るのです。
だから、空っぽの画面のスクリーンショットを取得することになります。
このタイミングの問題を解決したコードは、以下。
screenshot_2.py
from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.common.exceptions import NoSuchElementException CHROMEDRIVER = "chromedriver.exeのパス" URL = "https://twitter.com/AmazonJP" options = Options() options.add_argument('--hide-scrollbars') options.add_argument('--incognito') options.add_argument('--headless') driver = webdriver.Chrome(CHROMEDRIVER, options=options) driver.set_window_size(1024, 768) # 暗黙的に指定時間待つ(秒) driver.implicitly_wait(10) driver.get(URL) try: # articleタグを探す element = driver.find_element_by_tag_name("article") except NoSuchElementException: print("探した要素は存在しない") finally: driver.save_screenshot('result.png') driver.quit()
この変更したプログラムを実行すると、次のスクリーンショットを取得できます。
追記した箇所には、コメントをつけています。
ポイントは、以下の部分です。
# 暗黙的に指定時間待つ(秒) driver.implicitly_wait(10)
# articleタグを探す element = driver.find_element_by_tag_name("article")
これらは、二つで一つです。
セットで使うと覚えておいてください。
find_element_by_tag_nameに限らず、find_element_〇が対象となります。
機能としては、implicitly_waitに指定した時間だけ要素を探します。
要素が見つかった時点で、次の処理へ進みます。
もし見つからなかったら、エラーとなります。
エラーになるのは嫌なので、例外処理を対応しています。
また、implicitly_waitを設定するだけでは待機しません。
find_element_〇を実行することにより、最大で10秒間は探します。
調査した限りでは、2秒以内にはarticleタグが見つかっています。
なお、articleタグは以下の要素になります。
articleタグが見つかった時点で、コンテンツ表示は完了しているとみなしています。
仮にarticleタグが見つからなかった場合、10秒間は待機することになります。
10秒経てば、さすがにコンテンツ表示は完了しています。
だから、見つかる・見つからないに関わらず、スクリーンショットは上手く撮れます。
ただし、見つからない場合は10秒間待たないといけません。
まあ、10秒ぐらいはデフォルトで待機するのもアリとは思いますけどね。
以上、PythonでTwitterのスクリーンショットを取得するための説明でした。
追記 2021年11月29日
この記事は、Selenium 3を利用した場合の内容となります。
Selenium 4の場合は、次の記事を参考にしてみてください。