nprogram’s blog

気ままに、プログラミングのトピックについて書いていきます

Python + Selenium + ChromeでGoogleの検索を自動化する [非headlessモード]

はじめに

本記事は、Python + Selenium + ChromeでGoogleの検索を自動化する手法について記載したものです。

ChromeのWeb操作は、ChromeDriverを用います。

ChromeDriverを導入する方法として、以下の2つの方法がありますが、本記事は前者の方法を使用します。

  • バイナリを直接ダウンロードする
  • pipコマンド(pip install chromedriver-binary)でインストールする

以下のサイトから入手できます。Google Chrome Versionと合わせる必要があるので、ダウンロードするバージョンについては注意してください。

https://chromedriver.chromium.org/

また、ChromeDriverは非headlessモードで動作させます。

(※記事記載時点(2019/10/15)では本記事のコードが動作することを確認していますが、Googleのデザイン等が変われば動作しなくなる可能性があります。ご了承ください)

環境

環境は以下のとおりです。パッケージの管理はAnacondaで実施しています。pythonコードの実行はjupyter Noteboookを使用しました。

  • OS : Windows 10 Pro
  • conda version : 4.7.12
  • conda-build version : 3.18.8
  • python version : 3.7.3.final.0
  • selenium : 3.141.0
  • ChromeDriver : 77.0.3865.40

GoogleのWebサイトを開く

以下のコードでGoogleのWebサイトを開くことができます。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from time import sleep

options = Options()
driver = webdriver.Chrome(chrome_options=options, executable_path="F:\\tool\\ChromeDriver_77_0_3865_40\\chromedriver.exe")
web_site = 'https://www.google.com/'
driver.get(web_site )

from selenium.webdriver.common.keys import Keysは、文字を削除、入力、エンターキーの実行を行うためのキー操作を可能にするための宣言です。

from time import sleepはスリープさせるための宣言になります。

特に、webdriver.Chromeのパス指定(executable_path)は注意してください。Windowsの場合は、フォルダー階層はバックスラッシュ2回にする必要があります。

GoogleのWebサイトで検索を実行する

Googleの検索を自動化しようとした場合、以下のような課題があります。

  • Webページが完全に読み込まれる前にコードを実行しようとするとコードの処理が失敗する
  • Webページの要素が存在しないのに、要素を操作しようとするとコードの処理が失敗する

上記の課題を解決するためには、WebDriverWaitを使って任意のHTMLの要素が特定の状態になるまで待つことで解決可能です。

presence_of_element_locatedを実行することで、指定した要素がDOM上に現れるまで待機することが出来ます。

An expectation to locate an element and check if the selection state specified is in that state. locator is a tuple of (by, path) is_selected is a boolean

[例]

WebDriverWait(driver, MAX_WAIT_TIME_SEC).until(EC.presence_of_element_located((By.CLASS_NAME, INPUT_BOX_CLASS_NAME)))

EC.presence_of_element_located((By.CLASS_NAME, INPUT_BOX_CLASS_NAME))で2重の括弧になっていますが、バグではありません。 内側の括弧がタプル(tuple of (by, path))を示します。byは要素の種類、pathは要素の位置を示します。外側の括弧が関数presence_of_element_locatedの括弧です。

Webページの要素を操作する場合は、Webページの要素にアクセス可能か必ず確認してから操作したほうがよいでしょう。

サンプルコード

以下のサンプルコードでは、以下の操作を自動化しています。

  1. GoogleのWebサイトを開く
  2. 入力フィールドをクリアする (Back Spaceボタンを100回押す)
  3. 入力フィールドに、文字列testを入力する
  4. Enterボタンを押す
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

# ChromeDriverのパスを引数に指定しChromeを起動
CHROME_DRIVER_PATH = "F:\\tool\\ChromeDriver_77_0_3865_40\\chromedriver.exe"
options = Options()
driver = webdriver.Chrome(executable_path=CHROME_DRIVER_PATH, options=options)

# 指定したURLに遷移する
web_site = 'https://www.google.com/'
driver.get(web_site )

# 指定された要素(検索テキストボックス)がDOM上に現れるまで待機する (最大でMAX_WAIT_TIME_SEC秒待つ)
MAX_WAIT_TIME_SEC = 100
INPUT_BOX_CLASS_NAME = "gLFyf"
element = WebDriverWait(driver, MAX_WAIT_TIME_SEC).until(EC.presence_of_element_located((By.CLASS_NAME, INPUT_BOX_CLASS_NAME)))

# 検索テキストボックスをクリアする
for item in range(0,100) :
    element.send_keys(Keys.BACK_SPACE)

# 検索テキストボックスに文字列を入力する
code = "test"
element.send_keys(code)

# Enterボタンを押す
element.send_keys(Keys.RETURN)

参考ページ

あとがき

Webページの要素の指定をさらに簡単にしたいので、「XPath」で指定できるようにしたいと思います。また、GoogleのUIを使用しないHeadless Chromeでの自動化ができるようにしたいと思います。