#テスト自動化からスクレイピングまで幅広いseleniumの基本的な操作について扱う。
テスト自動化業務で少しseleniumを使うので、
自分用によく使うもしくはこれから使うであろう基本的なselenium操作をまとめて見た。
思ったより長くなったので、Ctrl+FとかCommand+Fとかで探すのがいいと思う。
#ページ取得
driver.get("http://www.google.com")
getを使ってページ移動する。
#要素を見つけ出す
##idから要素を見つけ出す
<div id="coolestWidgetEvah">...</div>
---
element = driver.find_element_by_id("coolestWidgetEvah")
# or
from selenium.webdriver.common.by import By
element = driver.find_element(by=By.ID, value="coolestWidgetEvah")
idから要素を見つけ出しオブジェクトを格納する
byを使う場合はimport Byをしなければいけない
##クラス名から要素を見つけ出す
<div class="cheese"><span>Cheddar</span></div><div class="cheese"><span>Gouda</span></div>
---
cheeses = driver.find_elements_by_class_name("cheese")
# or
cheeses = driver.find_elements(By.CLASS_NAME, "cheese")
classから要素を見つけ出しオブジェクトを格納する
##タグ名から要素を見つけ出す
<iframe src="..."></iframe>
---
frame = driver.find_element_by_tag_name("iframe")
# or
frame = driver.find_element(By.TAG_NAME, "iframe")
タグ名から要素を見つけ出しオブジェクトを格納する
##名前属性から要素を見つけ出す
<input name="cheese" type="text"/>
---
cheese = driver.find_element_by_name("cheese")
# or
cheese = driver.find_element(By.NAME, "cheese")
名前要素から要素を見つけ出しオブジェクトを格納する
##リンクテキストから要素を見つけ出す
<a href="http://www.google.com/search?q=cheese">cheese</a>>
---
cheese = driver.find_element_by_link_text("cheese")
# or
cheese = driver.find_element(By.LINK_TEXT, "cheese")
リンクテキストから要素を見つけ出しオブジェクトを格納する
##部分リンクテキストから要素を見つけ出す
<a href="http://www.google.com/search?q=cheese">search for cheese</a>>
---
cheese = driver.find_element_by_partial_link_text("cheese")
# or
cheese = driver.find_element(By.PARTIAL_LINK_TEXT, "cheese")
部分的に一致するリンクテキストから要素を見つけ出しオブジェクトを格納する
##CSSから要素を見つけ出す
<div id="food"><span class="dairy">milk</span><span class="dairy aged">cheese</span></div>
---
cheese = driver.find_element_by_css_selector("#food span.dairy.aged")
# or
cheese = driver.find_element(By.CSS_SELECTOR, "#food span.dairy.aged")
CSSから要素を見つけ出しオブジェクトを格納する
##Xpathから要素を見つけ出す
###Xpathとは何か?
<input type="text" name="example" />
<INPUT type="text" name="other" />
---
inputs = driver.find_elements_by_xpath("//input")
# or
inputs = driver.find_elements(By.XPATH, "//input")
javascriptを使う
任意のJavaScriptを実行して要素を見つけることができます。DOM要素を返す限り、自動的にWebElementオブジェクトに変換されます。
element = driver.execute_script("return $('.cheese')[0]")
javascriptでページ上のすべてのラベルのすべての入力要素を見つける
labels = driver.find_elements_by_tag_name("label")
inputs = driver.execute_script(
"var labels = arguments[0], inputs = []; for (var i=0; i < labels.length; i++){" +
"inputs.push(document.getElementById(labels[i].getAttribute('for'))); } return inputs;", labels)
javascriptで一番下までスクロールする
driver.execute_script('window.scrollTo(0,document.body.scrollHeight);')
テキストの値を取得する
element = driver.find_element_by_id("element_id")
element.text
ユーザ入力-フォームの入力
select = driver.find_element_by_tag_name("select")
allOptions = select.find_elements_by_tag_name("option")
for option in allOptions:
print "Value is: " + option.get_attribute("value")
option.click()
driver.find_element_by_id("submit").click()
クリックを使って、optionをselect状態に切り替え送信する
ウィンドウ間の移動
driver.switch_to.window("windowName")
webアプリケーション上に複数のwindowがある場合自動で切り替えれる。
windowの名前がわからない場合
<a href="somewhere.html" target="windowName">Click here to open a new window</a>
for handle in driver.window_handles:
driver.switch_to.window(handle)
window名をdriver.window_handlesを使うことで自動で取得する。
フレーム間の移動
driver.switch_to.frame("frameName")
ポップアップ系を扱う
alert = driver.switch_to.alert
# usage: alert.dismiss(), etc.
画面上にポップアップする機能を扱う
前の画面に戻る
# 前に進む
driver.forward()
# 後ろに戻る
driver.back()
クッキーを扱う
driver.get("http://www.example.com")
## ドメイン全体に対してクッキーを設置
# クッキーの名前をkey,値をvalueにする
driver.add_cookie({'name':'key', 'value':'value', 'path':'/'})
# 以下は他に使えるキー
# 'domain' -> String,
# 'secure' -> Boolean,
# 'expiry' -> Milliseconds since the Epoch it should expire.
## 現在のURLに使えるクッキーを全て出力
for cookie in driver.get_cookies():
print "%s -> %s" % (cookie['name'], cookie['value'])
## クッキーを削除する方法
# 名前から削除する場合
driver.delete_cookie("CookieName")
# 全体を削除する場合
driver.delete_all_cookies()
ユーザーエージェントの変更
profile = webdriver.FirefoxProfile()
profile.set_preference("general.useragent.override", "some UA string")
driver = webdriver.Firefox(profile)
ドラッグ&ドロップ
Actionsクラスを使用してドラッグ&ドロップする方法
*ネイティブイベントの有効が必要
Actionsクラスはマウスとキーボードの2つのアクションを一連の流れで実行するクラス
from selenium.webdriver.common.action_chains import ActionChains
element = driver.find_element_by_name("source")
target = driver.find_element_by_name("target")
ActionChains(driver).drag_and_drop(element, target).perform()
明示的or暗黙的な待ち時間
自動化されたタスクの実行では一定時間経過してから次のステップに進む。
よって、待ち時間を明示的もしくは暗黙的に選択しないといけない。
明示的な場合
あまりよくない方法としてimport time.sleepなど使うこと
なぜならsleep(10)なら確実に10秒待つことになる。
その代わりに明示的にWebDriverWaitを使うと必要な分しか待たないので便利
また、待つ条件としてexpected_conditionを使う
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
ff = webdriver.Firefox()
ff.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(ff, 10).until(EC.presence_of_element_located((By.ID, "myDynamicElement")))
finally:
ff.quit()
これは10秒以内に要素を見つけて返すことを試みる。
それ以降何も見つからない場合は、TimeoutExceptionが投げられる。
暗黙的な場合
暗黙的な待機が設定される。
from selenium import webdriver
ff = webdriver.Firefox()
ff.implicitly_wait(10) # seconds
ff.get("http://somedomain/url_that_delays_loading")
myDynamicElement = ff.find_element_by_id("myDynamicElement"
スクリーンショットを撮る
from selenium import webdriver
driver = webdriver.Remote("http://localhost:4444/wd/hub", webdriver.DesiredCapabilities.FIREFOX.copy())
driver.get("http://www.google.com")
driver.get_screenshot_as_file('/Screenshots/google.png')
プロキシを使う
「最も簡単で推奨される方法は、テストを実行する予定のマシンに手動でプロキシを設定することです。それが不可能な場合、またはテストを別の構成またはプロキシーで実行したい場合は、Capababilitiesオブジェクトを使用する以下の手法を使用できます。これにより、システムのプロキシ設定が一時的に変更され、実行時に元の状態に戻ります。」
from selenium import webdriver
PROXY = "localhost:8080"
# desired capabilities objectのコピーを作る
desired_capabilities = webdriver.DesiredCapabilities.INTERNETEXPLORER.copy()
# そのコピーのプロキシプロパティを変更する
desired_capabilities['proxy'] = {
"httpProxy":PROXY,
"ftpProxy":PROXY,
"sslProxy":PROXY,
"noProxy":None,
"proxyType":"MANUAL",
"class":"org.openqa.selenium.Proxy",
"autodetect":False
}
# リモートのものを使ってください
# そうでないならpythonで動的にシステムプロキシの選択をしてください
driver = webdriver.Remote("http://localhost:4444/wd/hub", desired_capabilities)
tips
詰まった所1
僕があんまりcssやjsvascriptに詳しくないのも原因だが
<a class="samp sample">
--
driver.find_elements_by_class_name("samp sample")
上記のようなclass名のやつは使わないようにする。
driver.find_elements_by_class_name("samp.sample")とすることで通ると書いてる場所もあるけど基本的にうまくいかないので、
driver.find_elements_by_class_name("sample")という感じに1つだけを指定して読み込むようにする。
詰まった所2
ページ移動ボタン自動クリックなどループを必要とする時
ページ数の取得などがめんどくさいので要素(element)がなくなったら終了するコードを書きたい場合NoSuchElementExceptionをimportして使おう
from selenium.common.exceptions import NoSuchElementException
while True:
try:
wait = WebDriverWait(driver,500)
wait.until(EC.element_to_be_clickable((By.CLASS_NAME,"next_page")))
element = driver.find_element_by_class_name("next_page")
element.click()
except NoSuchElementException:
print('これ以上クリックできません')
# 終わり
とりあえず自分的に使うかなーと思うものを集めて見ました。
下記のウェブサイトを参考にさせてもらいました。
ありがとうございます。いろいろ助かりました。
参考文献