2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

selenium × python開発TIPS集

Last updated at Posted at 2024-12-28

はじめに

ブラウザポチポチ作業をselenium * pythonで自動化したいときのtips集。

seleniumは4系を利用。

PS > pip list | Select-String selenium

selenium           4.27.1

導入

・pythonにseleniumのライブラリをインストール

pip install selenium

・利用するブラウザに応じたWebDriverをDLして配置

手元では、使っているchrome のバージョンに合わせて128.0.6613.138を利用。
https://developer.chrome.com/docs/chromedriver/downloads/version-selection?hl=ja にも
https://googlechromelabs.github.io/chrome-for-testing/ にも見つからないので
https://storage.googleapis.com/chrome-for-testing-public/128.0.6613.138/win64/chromedriver-win64.zip
を直接ブラウザに打ってDL。

seleniumからchromeを起動

DLしたchromeのドライバを指定して、seleniumからchromeを起動する。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

options = webdriver.ChromeOptions()
options.add_experimental_option("detach", True)

service = ChromeService(executable_path="./chromedriver-win64/chromedriver.exe")
driver = webdriver.Chrome(service=service, options=options)

driver.get('https://www.google.co.jp/')

要素の取得・操作

chrome起動後は、
・要素を取得
 →要素の操作(クリック・値の入力・ボタン押下など)
を何度も繰り返していくことになる。

特に前者は、「欲しい要素が持つid, name, class, text() 等から、その要素を一意に特定できるものを選んで指定し、要素を取得する」という動きを繰り返しすることになる。

どうやって一意に指定するか、という部分が肝。
明らかに一意なid(本来一意のはず), classが振られていれば、それを指定すれば済むが、
それが難しい場合、XPATHでフルパスを指定するか、and条件を使うなど工夫することになる。

要素の取得方法は以下などを参照。

sample_idというid属性を持つ要素をクリックする

sample_id= driver.find_element(By.ID, "sample_id")
sample_id.click()

例えば以下が引っかかる。

<button id="sample_id" class="btn-class">ボタン</button>

※find_elementだと、仮に複数見つかっても最初の一つしか返さない。
 find_elementsにすると、リストで返してくれる。
 ※単一のつもりが誤ってfind_elementsを指定してしまっていて、思っていた返り値と違う・・・というミスが発生しがち。

LoginIdというname属性を持つinputフィールドに値を入れる

input_login_id = driver.find_element(By.NAME, "LoginId")
input_login_id.send_keys("alphajinsei")

例えば以下が引っかかる(値入力後)

<input name="LoginId" type="text" value="alphajinsei" class="input-class">

XPATHをフルパスで指定して要素を指定・クリックする

wariai = driver.find_element(By.XPATH, "/html/body/form[1]/div/div[11]/table[1]/tbody/tr/td[3]/a")
wariai.click()

XPATHのフルパスの指定は開発者ツールから。

「サンプルテキスト」という文字列を含む要素をクリックする

driver.find_element(By.XPATH, '//*[contains(text(),"サンプルテキスト")]').click()

たとえば以下のような要素が引っかかる

<span>サンプルテキスト</span>
<button class="btn-class">サンプルテキスト</button>

ボタンのタグで、「選択」というテキストを含んでいて、かつname属性がselectButtonである要素を取得する

driver.find_element(By.XPATH, '//button[contains(text(),"選択") and @name="selectButton"]').click()

例えば以下が引っかかる

<button type="button" name="selectButton">選択</button>
XPATHの表記について

上記のXPATHの表記'//button[contains(text(),"選択") and @name="selectButton"]は、

  • // : 本来XPATHは /html/body/form[1]のようにフルパス表記するが、ワイルドカード的に省略して//とできる。
  • button[] : buttonタグである要素。ここも省略して//*[XXX]のようにしてもよい。
  • contains(text(),"選択") : 持っているテキストが「選択」を含んでいること。決め打ちでよければ//button[text()='選択']と書いても良い
  • @name="selectButton" : name属性にselectButtonと表記されていること を指定。属性(<button name="XX">のようにタグ内に書かれているやつ)は@で指定する

以下に詳しい。

複数のclassが指定されている要素を全て指定して選択する

以下のように、classが複数指定されていて、指定されているclassの全量("aaa bbb ccc")でひっかけたい場合、

<div class="aaa bbb ccc"> ★これを取得したい
<div class="aaa bbb ddd">

以下のように(By.CLASS_NAMEではなく)XPATHで複数クラスを全量指定することで取得できる。

aaa_bbb_ccc = driver.find_element(By.XPATH, '//div[@class="aaa bbb ccc"]')

driver.find_element(By.CLASS_NAME, 'aaa bbb ccc')とは書けない。

find_elementで取得したWebElementに対して、さらに子要素をXPATHで指定したい

より、XPATHの指定の先頭に、.を付ける。

##get elements from parent element using XPATH
##NOTE: in order to utilize XPATH from current element, you must add "." to beginning of path

    # Get first element of tag 'ul'
element = driver.find_element(By.XPATH, '//ul')

    # get children of tag 'ul' with tag 'li'
elements  = driver.find_elements(By.XPATH, './/li')

selenium開発TIPS集

途中まで動かしたあと、対話モードで自由に確認したい

python -i selenium_test.py

とすることで、実行後にそのまま対話モードに移行する。
また、単にpythonで対話モードを起動したのち、

exec(open("./selenium_test.py", encoding="utf-8").read())

とすることで、対話モード内で書いたスクリプトを実行させることができる。
この後も対話モードのままなので、スクリプトで利用した変数、WebElementの内容を確認することができる。

今driverが認識しているURL,htmlの内容を確認したい

driver.current_url
driver.page_source

選択した要素のhtml表記を確認したい

.get_attribute('outerHTML')でhtml要素を確認できる

date_item = driver.find_element(By.XPATH, "/html/body/div[4]/table/tbody")
date_item.get_attribute('outerHTML')

選択した要素が持つ特定の属性の値を確認したい

例えば以下のようなhtmlがあった際に、

<input type="hidden" name="input_value" value="99" disabled="">

以下のようにget_property()メソッドを利用することで、所望の属性の値(value=99)を取得することができる

value = driver.find_element(By.NAME, "input_value").get_property("value")
# valueに99が入る

その他、WebElement(find_elementで取得できるクラス)に備わったプロパティ・メソッド集は下記。

その他

selenium3 → 4に変わって、要素の選択の記述方法が微妙に変わっている点に注意。

jsk_send_btn = driver.find_element(By.ID, "send_btn") # 新 (直近はこちらを利用)
jsk_send_btn = driver.find_element_by_id("send_btn") # 旧
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?