Selenium実践:複雑なWebページの自動操作テクニック集

Webブラウザ操作を自動化するツールSeleniumは、テスト自動化や定型作業の効率化に非常に強力です。しかし、実際のWebページ、特に社内システムなどは、単純なクリックや入力だけでは操作できない複雑な構造を持っていることが少なくありません。

今回は、Seleniumを使って少し複雑なWebシステムの操作を自動化する過程で役立った、いくつかの実践的なテクニックをご紹介します。


目次

1. Iframe(インラインフレーム)の壁を越える

Webページの中に別のWebページが埋め込まれているような構造をIframeと呼びます。Seleniumは通常、メインのページしか認識できないため、操作したい要素がIframeの中にある場合は、まずそのIframeに操作の対象を切り替える必要があります。

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

# WebDriverWaitのインスタンスを作成
wait = WebDriverWait(driver, 10) # 最大10秒待機

# Iframeが表示され、切り替え可能になるまで待機し、切り替える
# IDで指定する場合
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "your_iframe_id")))
# Name属性で指定する場合
# wait.until(EC.frame_to_be_available_and_switch_to_it((By.NAME, "your_iframe_name")))
# class名などで取得した要素を指定する場合
# iframe_element = driver.find_element(By.CLASS_NAME, "your_iframe_class")
# driver.switch_to.frame(iframe_element)

print("Iframeへの切り替え成功")

# --- ここにIframe内の要素を操作するコードを書く ---

# 操作が終わったら、元のメインページに戻る
driver.switch_to.default_content()
print("メインページに戻りました")

ポイント:

  • 操作したい要素がどのIframeに属しているかを、ブラウザの開発者ツール(F12)で確認することが重要です。
  • WebDriverWaitEC.frame_to_be_available_and_switch_to_itを組み合わせることで、Iframeの読み込みを待ってから確実に切り替えられます。
  • 操作後はdriver.switch_to.default_content()で必ず元の階層に戻りましょう。

2. マウスオーバー(ホバー)で表示されるメニューの操作

クリックではなく、マウスカーソルを乗せるとサブメニューが表示されるタイプのUIもよく見られます。これはActionChainsを使ってシミュレートできます。

from selenium.webdriver.common.action_chains import ActionChains

# マウスオーバーする対象のメニュー要素を取得
menu_element = wait.until(EC.presence_of_element_located((By.ID, "main_menu_id")))

# ActionChainsのインスタンスを作成
actions = ActionChains(driver)

# メニュー要素の上にマウスを移動させ、実行
actions.move_to_element(menu_element).perform()

print("メニューにマウスオーバーしました")

# サブメニューが表示されるのを少し待つ
import time
time.sleep(1)

# 表示されたサブメニュー項目を探してクリック
submenu_item = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, "submenu_item_class")))
submenu_item.click()

print("サブメニュー項目をクリックしました")

ポイント:

  • ActionChainsを使うと、マウス移動、クリック、ドラッグ&ドロップなど、より複雑なユーザー操作を模倣できます。
  • .perform()を実行するまで、一連の動作は実行されません。
  • マウスオーバー後、サブメニューがアニメーションなどで表示される場合は、短いtime.sleep()を入れるか、サブメニュー要素が現れるまでWebDriverWaitで待機すると安定します。

3. クリックが効かないボタンへの対処法:JavaScript実行

Seleniumの標準の.click()メソッドでは、クリックイベントが正しく発生しないボタンが存在します(特に複雑なJavaScriptで制御されている場合)。このような場合は、JavaScriptを直接実行してクリックさせる方法が有効です。

# クリックしたいボタン要素を取得
button_element = wait.until(EC.element_to_be_clickable((By.ID, "complex_button_id")))

# JavaScriptを実行してクリック
driver.execute_script("arguments[0].click();", button_element)

print("JavaScriptでボタンをクリックしました")

# ボタンにonclick属性で直接関数が指定されている場合
# driver.execute_script("return functionName();")

ポイント:

  • driver.execute_script()は、ブラウザ上で直接JavaScriptコードを実行できる強力な機能です。
  • arguments[0]は、続く引数(ここではbutton_element)を参照します。
  • 見た目の要素ではなく、実際にonclickイベントを持っている内部の要素に対して実行する必要がある場合もあります。

4. 操作の完了を確実に待つ:要素の状態変化を確認

特にダイアログボックスの操作などで、「OKボタンを押したらダイアログが閉じる」といった一連の動作を確実に待機したい場合があります。単にtime.sleep()で待つのではなく、要素の状態変化を監視することで、より確実で効率的な待機が可能です。

# 例:OKボタンをクリックした後、ダイアログ(Iframe)が消えるのを待つ

# クリック対象のOKボタン要素を取得
ok_button = wait.until(EC.element_to_be_clickable((By.ID, "dialog_ok_button_id")))

# 消えるはずの要素(ここではダイアログのIframe)をクリック直前に特定
dialog_iframe_element = driver.find_element(By.CLASS_NAME, "dialog_iframe_class")

# OKボタンをクリック(JavaScript実行など)
driver.execute_script("arguments[0].click();", ok_button)
print("OKボタンをクリックしました")

# 確認:ダイアログのIframe要素がDOMから消える(古くなる)まで待機
print("ダイアログが閉じるのを待ちます...")
wait.until(EC.staleness_of(dialog_iframe_element))
print("ダイアログが閉じたことを確認しました")

# 確認:要素が非表示になるのを待つ場合
# wait.until(EC.invisibility_of_element_located((By.CLASS_NAME, "dialog_iframe_class")))

ポイント:

  • EC.staleness_of(element): 指定した要素オブジェクトが古くなる(DOMから削除されたり、再描画されたりする)まで待ちます。要素をfind_elementで取得しておく必要があります。
  • EC.invisibility_of_element_located(locator): 指定したロケータ(例:(By.CLASS_NAME, "..."))に該当する要素が非表示になるか、DOM上に存在しなくなるまで待ちます。

5. 独自UIへの対応:見た目と実際の入力要素が異なる場合

表計算ソフトのようなグリッド表示で、セルをクリックすると入力ボックスが現れる、といった独自のUIを採用しているシステムもあります。

# 1. 見た目のセル要素(例:<span>)を取得してクリック
display_cell = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, "display_cell_class")))
display_cell.click()
print("表示セルをクリックしました")

# 2. クリック後に出現する実際の入力ボックス(例:<input>)を探す
input_box = wait.until(EC.visibility_of_element_located((By.ID, "actual_input_box_id")))
print("入力ボックスを発見")

# 3. 入力ボックスに値を入力し、Enterキーで確定
input_box.clear()
input_box.send_keys("入力したい値")
input_box.send_keys(Keys.RETURN) # Enterキーを押す
print("値を入力し、Enterで確定しました")

ポイント:

  • 開発者ツールで、クリック前後のHTML構造の変化をよく観察することが重要です。
  • 見た目の要素をクリックした後、実際に文字を入力するための<input><textarea>要素が動的に生成されたり、表示されたりします。
  • 入力後、Enterキーを押す(Keys.RETURN)か、別の場所をクリックすることで入力内容がセルに反映されることが多いです。

まとめ

複雑なWebページの自動操作は一筋縄ではいかないこともありますが、

  • Iframeの存在を意識する
  • WebDriverWait要素の出現や状態変化を適切に待つ
  • ActionChainsマウス操作を再現する
  • 標準のクリックが効かない場合はJavaScript実行を試す
  • 開発者ツールでHTML構造の変化をよく観察する

といった点を押さえることで、多くの課題を乗り越えることができます。Seleniumを使いこなし、日々の作業を効率化していきましょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次