【Selenium講座】第6章: 複雑な操作を実装
Seleniumを用いたWeb操作の基本を習得した方は、さらに複雑な操作に挑戦することで、より高度な自動化スクリプトを構築できるようになります。
本講座の第6章では、複数のタブやウィンドウの管理、スクロール、スクリーンショットの取得、動的に生成される要素への対応、キーボード操作など、より高度な操作方法を解説します。これらのテクニックを習得することで、複数ページにまたがる情報取得やユーザーの操作を再現する自動化を効率的に実装できるようになります。また、XPathを用いた要素指定の詳細についても説明し、より柔軟で精確な要素の取得方法を学びます。
各機能をしっかり理解しながら、さまざまなシチュエーションに対応できる自動化スクリプトを構築していきましょう。
目次
講座の全体像
複数タブやウィンドウの操作
Seleniumでは、複数のタブやウィンドウを管理することができます。これにより、異なるページやセクションを同時に操作できます。新しいタブやウィンドウを開く際には、最初のウィンドウのハンドルを保存し、後で必要に応じて切り替えることが重要です。
新しいタブを開く
driver.switch_to.new_window("tab")
driver.get("https://example.com")
タブやウィンドウを切り替える
main_window = driver.current_window_handle
# 新しいタブに切り替え
driver.switch_to.window(driver.window_handles[1])
# 何らかの操作を行う
# 戻る場合はメインウィンドウに切り替える
driver.switch_to.window(main_window)
例として、投稿一覧画面に遷移して、投稿詳細画面を別タブで開いてキャプションを取得する実装を紹介します。
投稿一覧画面に遷移
posts_link = driver.find_element(By.LINK_TEXT, "新着投稿")
posts_link.click()
time.sleep(5)
投稿の一覧を取得
posts = driver.find_elements(By.CLASS_NAME, "posts")
find_elements(By.CLASS_NAME, "posts")
: ページ上に表示されている投稿の一覧を取得します。find_elements
は、複数の要素を取得するメソッドです。ここでは、class="posts"
を持つ要素すべてをリストとして取得しています。
投稿詳細画面を別タブで開き、キャプションを取得
for post in posts:
href = post.get_attribute("href")
driver.switch_to.new_window("tab")
driver.get(href)
time.sleep(3)
caption = driver.find_element(By.CLASS_NAME, "caption")
print(caption.text)
driver.close()
driver.switch_to.window(driver.window_handles[0])
for post in posts:
:取得した投稿一覧を1つずつループで処理します。
post.get_attribute("href")
: 各投稿のリンク先URLを取得します。href
はリンク先のURLを指す属性です。
driver.switch_to.new_window("tab")
: 新しいタブを開きます。"tab"
を指定することで、新しいブラウザのタブで動作します。
driver.get(href)
: 新しいタブで、指定した投稿の詳細ページを開きます。
caption = driver.find_element(By.CLASS_NAME, "caption")
: 投稿詳細画面で、class="caption"
を持つ要素を探し、その要素をcaption
に格納します。
print(caption.text)
: 取得したキャプションをコンソールに表示します。
driver.close()
: 新しいタブを閉じます。
driver.switch_to.window(driver.window_handles[0])
: 元のタブ(最初の投稿一覧画面)に戻ります。
スクロール操作
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
このスクリプトは、ページの一番下までスクロールします。特定の要素までスクロールする場合は、その要素の位置を指定できます。
スクリーンショット
driver.save_screenshot("screenshot.png")
このコードは、現在表示されているページのスクリーンショットをPNG形式で保存します。デバッグやテスト結果の記録に役立ちます。
動的に生成される要素への対応
要素が動的に追加される場合、即座に操作を試みるとエラーになります。こうした場合は、要素がDOM内に出現するのを待つためのWebDriverWait
やexpected_conditions
を利用します。
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 要素が表示されるまで待機
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "dynamic-element"))
)
のように、動的に追加された要素でも、DOMの変化を待って操作することが可能です。
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
driver = webdriver.Chrome()
driver.get("https://inusta-next.vercel.app/login")
time.sleep(3)
email_input = driver.find_element(By.NAME, "email")
password_input = driver.find_element(By.NAME, "password")
email_input.send_keys("user+1@example.com")
password_input.send_keys("password")
button = driver.find_elements(By.TAG_NAME, "button")[0]
button.click()
# 要素が表示されるまで待機
img = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//button[@id='menu-button']/img"))
)
print(img.get_attribute("src"))
WebDriverWait(driver, 10)
: この部分は、指定した要素が表示されるまで最大10秒間待つ設定です。ページが読み込み中や遅延がある場合に、すぐに次の操作を行わずに待機することができます。
.until(EC.presence_of_element_located((By.XPATH, "//button[@id='menu-button']/img")))
: この部分で待機条件を設定しています。
EC.presence_of_element_located
: 要素がDOM(HTMLの構造)に存在することを確認する条件です。表示されるまで待機します。
By.XPATH, "//button[@id='menu-button']/img"
: 取得したい要素を指定しています。ここでは、XPATH
という形式を使って指定しています。
//button[@id='menu-button']/img
: 意味としては「id
属性がmenu-button
のボタン要素内にあるimg
タグの画像要素を探す」ということになります。
WebDriverWait
とuntil
を使うことで、要素が読み込まれるまで待機できるため、要素がまだ見えていない状態でエラーが出ることを防ぎます。
By.XPATH
を用いることで、より複雑な構造の要素を精確に指定することができます(id
やclass
がない場合に便利)。
キーボード操作
このコードは、Seleniumを使ってSNSの特定の投稿に対してコメントを送信する例です。キーボード操作を用いて、コメントを入力し、Enter
キーを押すことで実際にコメントを送信しています。
driver.get("https://inusta-next.vercel.app/posts/cm10dkzze002syyeqvt5k5qe7")
time.sleep(5)
comment_input = driver.find_element(By.NAME, "text")
comment_input.send_keys("こんにちは")
comment_input.send_keys(Keys.ENTER)
driver.get(...)
: これはSeleniumが指定されたURLのページにアクセスするための命令です。今回はSNSサイトの特定の投稿ページ(/posts/cm10dkzze002syyeqvt5k5qe7
)に移動しています。
find_element(By.NAME, "text")
: これは、ページ内のname
属性が"text"
で指定された入力欄を探す命令です。name="text"
という属性は通常、コメント欄やテキスト入力欄を表すことが多いため、これを使ってコメント入力エリアを取得します。comment_input
という変数にその入力欄を格納することで、以降の操作でコメント欄を指定して操作できます。
send_keys(...)
: このメソッドは、指定されたテキスト(今回は「こんにちは」)を入力欄に送信するものです。つまり、コメント欄に「こんにちは」という文字をタイプしているのと同じ動作を行っています。
send_keys(Keys.ENTER)
: ここで、Keys.ENTER
を使ってEnter
キーを押す操作を行います。Keys
はSeleniumが用意しているキーボード操作を表すクラスで、ENTER
を使うことで、手動でEnter
キーを押すのと同じ動作を実現します。これにより、入力した「こんにちは」というコメントが送信されます。
XPath
XPathとは?
XPathは、HTMLやXMLドキュメントの構造をたどって、特定の要素を見つけ出すためのパス指定の方法です。ウェブページ上のどこにあるかがわからない要素でも、XPathを使うことで正確に指定できるようになります。
HTMLはツリー構造になっているので、XPathを使ってこのツリーを「道順」に沿ってたどるイメージです。XPathの記法を使うと、親要素、子要素、属性などを指定して、欲しい要素を取り出せます。
XPathの基本記法
絶対パス (/
)
絶対パスは、HTMLドキュメントの最上部(html
タグ)から目的の要素まで、全ての階層を指定してたどる方法です。
例:/html/body/div/h1
このXPathは、html
タグから始まり、body
の中のdiv
要素、その中のh1
要素を指定しています。
相対パス (//
)
相対パスは、ページのどこからでも始められる柔軟な方法です。特定のタグや属性を基準にして、そのタグがどこにあっても探し出せます。
例://h1
これは、ページ全体の中で、h1
タグを持つ全ての要素を探し出します。
要素の属性を指定する (@
)
特定の属性(例えばid
やclass
など)を持つ要素を絞り込む場合、@
を使って属性を指定できます。
例://input[@name='username']
input
タグの中で、name
属性がusername
である要素を探します。
部分一致で検索 (contains
)
特定の属性やテキストが完全に一致しない場合でも、部分一致を使って検索できます。
例://button[contains(text(), 'ログイン')]
ボタンのテキストに「ログイン」を含む要素を探します。
特定の順番の要素を指定する ([index]
)
同じタグの要素が複数ある場合、その中から特定の順番にある要素を指定できます。
例1://div[2]
2番目のdiv
要素を指定します。
例2://ul/li[1]
ul
タグの最初のli
要素を指定します。
親子関係の指定 (/
と //
)
//
はどこからでも指定できる柔軟な相対パスでしたが、/
を使うことで親から直接の子要素を指定できます。
例://div/p
は、div
の直接の子要素であるp
を探します。
まとめ
Seleniumを使用した複雑な操作を理解することで、より複雑なウェブアプリケーションに対するスクレイピングが可能になります。タブやウィンドウの操作、ドロップダウンメニューの選択、JavaScriptの実行など、様々な機能を活用することで、実際の使用シーンに応じた柔軟な操作ができるようになります。
次の章では、収集したデータをどのように保存するかについて学びます。データの保存は、スクレイピングプロジェクトの重要な部分であり、適切な形式での保存方法やデータベースとの連携について詳しく解説していきます。
この記事へのコメントはありません。