🐔

Seleniumの使い方 第6回 待機処理(python×Microsoft Edge)

に公開

こんにちは、星杜なぎさです
今回は、seleniumで文字入力やクリックを行う方法について学びます。

環境構築がまだの人は、以下の記事で準備してから本記事を読まれるとよいでしょう
https://zenn.dev/hoshinagi1219/articles/b61f220e0908c5

1. はじめに

  • Seleniumは、Webブラウザの操作を自動化するためのツール
  • オープンソースなので、無料で利用可能
  • WebスクレイピングやRPA(Robotic Process Automation)などに活用できる

1.1 この記事について

  • SeleniumのWebDriverWait および expected_conditions(EC)について、サンプルコードを記載した
  • Chromeを使用した例が(公式サイト含め)多かったため、Microsoft Edgeでの使い方をまとめる
    企業などの方針でChromeがインストールできない人でも大丈夫です!

1.2 対象読者

  • プログラム言語(特にpython)が多少読める、書ける
  • PCの基本操作(Drag and Dropなど)を知っている
  • Webブラウザの基本操作を知っている

1.3 動作環境

  • PC
    • OS:Windows 11 Home
  • python : 3.12.5
    • selenium : 4.31.0

2. とりあえず、動かしてみよう

expected_conditionsは種類が多いため、全部は試しませんでした。
もし、一覧が知りたい方は下記の公式リファレンスを参照してください
https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html

2.1 実行時の出力

今回はWeb画面上ではわかりづらかったため、コンソール出力主体で表示
似たメソッド名でも返り値がboolean(True, False), elemenet, alart, listなどいろんなものがあってややこしい
また、locatedと書いてなくても、引数の指定がelementではなくlocatorだったりするので、直感的にわかりづらかった

2.2 プログラム例

全てのメソッドを試すとわかりづらかったため、一部抜粋

  1. title関連
  2. URL関連
  3. 要素関連
  4. 不可視・存在していないこと
  5. 選択(チェック)の有無
  6. 画面上に表示されているか
  7. クリック可能か
  8. ウィンドウの個数
  9. ポップアップの有無
  10. 複合条件(any, all, none)
locatorについて

引数:locatorについてですが、使う上では「find_elementで指定するBy.XXX と 値のtuple」の理解でよいかと思います
実際、次のプログラムではlocator=(By.TAG_NAME, "h1")等を指定しています

公式では、locator : Tuple[str, str]とありますが、By.XPATH等は実際文字列なので、リファレンス上は間違ってないですが、ドキュメントとしてはわかりにくいと感じました...

※同じ変数名に違う意味の値を入れるのは良くないですが、今回は許容しております。

from time import sleep
from selenium import webdriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

"""
WebDriverWait および expected_conditionsの動作確認
"""

SERVICE = Service("./edgedriver_win64/msedgedriver.exe")  # exeのPATH
TARGET_URL = "https://www.selenium.dev/selenium/web/web-form.html"

try:
    # 下準備(URLへアクセス、ウィンドウの最大化)
    driver = webdriver.Edge(service=SERVICE)
    driver.maximize_window()  # windowを最大化
    driver.get(TARGET_URL)  # URLへアクセスする

    # 1.title関連
    print("=== 1.title関連 ===")
    boolean = WebDriverWait(driver, 3).until(EC.title_is("Web form"))
    print(f"EC.title_is : {boolean=}")
    boolean = WebDriverWait(driver, 3).until(EC.title_contains("Web"))
    print(f"EC.title_contains : {boolean=}")

    # 2.URL関連
    print("\n=== 2.URL関連 ===")
    boolean = WebDriverWait(driver, 3).until(EC.url_to_be(TARGET_URL))
    print(f"EC.url_to_be : {boolean=}")
    boolean = WebDriverWait(driver, 3).until(EC.url_contains("selenium.dev"))
    print(f"EC.url_contains : {boolean=}")
    boolean = WebDriverWait(driver, 3).until(EC.url_matches("selenium"))
    print(f"EC.matches : {boolean=}")
    boolean = WebDriverWait(driver, 3).until(EC.url_changes("localhost:5000"))
    print(f"EC.url_changes : {boolean=}")

    # 3.要素関連
    print("\n=== 3.要素関連 ===")
    locator = (By.TAG_NAME, "a")  # <a>タグのlocator
    boolean = WebDriverWait(driver, 3).until(
                  EC.text_to_be_present_in_element(locator, "Return to index")
              )
    print(f"EC.text_to_be_present_in_element : {boolean=}")
    boolean = WebDriverWait(driver, 3).until(
                  EC.text_to_be_present_in_element_attribute(locator, 
                       "href", 
                       'https://www.selenium.dev/selenium/web/index.html'
                  )
              )
    print(f"EC.text_to_be_present_in_element_attribute : {boolean=}")

    # 4. 不可視・存在していないこと
    print("\n=== 4.不可視・存在していないこと ===")
    locator = (By.ID, "XXXXX")  # 存在しないIDのlocator
    boolean = WebDriverWait(driver, 3).until(
                  EC.invisibility_of_element_located(locator)
              )
    print(f"EC.invisibility_of_element_located : {boolean=}")


    # 5.選択(チェック)の有無
    print("\n=== 5.選択(チェック)の有無 ===")
    element = driver.find_element(By.ID, "my-check-1")  # チェックボックス
    boolean = WebDriverWait(driver, 3).until(EC.element_to_be_selected(element))  # 選択できるか?
    print(f"EC.element_to_be_selected : {boolean=}")
    boolean = WebDriverWait(driver, 3).until(EC.element_selection_state_to_be(element, True))  # チェックが入っているか?
    print(f"element_selection_state_to_be : {boolean=}")

    # 6.画面上に表示されているか
    print("\n=== 6.画面上に表示されているか ===")
    locator = (By.TAG_NAME, "h1")  # <h1>タグ
    element = WebDriverWait(driver, 3).until(EC.visibility_of_element_located(locator))
    print("EC.visibility_of_element_located : ", element)

    # 7.クリック可能か
    print("\n=== 7.クリック可能か ===")
    locator = (By.ID, "my-radio-2")  # ラジオボタン
    element = WebDriverWait(driver, 3).until(EC.element_to_be_clickable(locator))
    print("EC.element_to_be_clickable : ", element)

    # 8.ウィンドウの個数
    print("\n=== 8.ウィンドウの個数 ===")
    boolean = WebDriverWait(driver, 3).until(EC.number_of_windows_to_be(num_windows=1))
    print(f"EC.num_of_window_to_be : {boolean=}")

    # 9.ポップアップの有無
    print("\n=== 9.ポップアップの有無 ===")
    driver.execute_script("alert('Hello')")  # alertを出現させる
    alert = WebDriverWait(driver, 3).until(EC.alert_is_present())
    print("EC.alert_is_present : ", alert)
    sleep(1)
    alert.accept()  # OKを押す
    sleep(1)

    # 10.複合条件
    print("\n=== 10.複合条件 ===")
    boolean = WebDriverWait(driver, 3).until(
                  EC.any_of(EC.title_is("Web form"), EC.alert_is_present())
              )
    print(f"EC.any_of : {boolean=}")
    boolean_list = WebDriverWait(driver, 3).until(
                       EC.all_of(EC.title_is("Web form"), EC.url_to_be(TARGET_URL))
               )
    print(f"EC.all_of : {boolean_list=}")
    boolean = WebDriverWait(driver, 3).until(
                  EC.none_of(EC.title_is("XXXXX"), EC.alert_is_present())
              )
    print(f"EC.none_of : {boolean=}")
finally:
    driver.quit()

print("conplete run!!")

参考URL

Discussion