selenium 基本操作まとめ(自分用)


#テスト自動化からスクレイピングまで幅広いseleniumの基本的な操作について扱う。

テスト自動化業務で少しseleniumを使うので、
自分用によく使うもしくはこれから使うであろう基本的なselenium操作をまとめて見た。

思ったより長くなったので、Ctrl+FとかCommand+Fとかで探すのがいいと思う。


#ページ取得
```python
driver.get("http://www.google.com")
```
getを使ってページ移動する。
#要素を見つけ出す
##idから要素を見つけ出す
```python
<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をしなければいけない
##クラス名から要素を見つけ出す
```python
<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から要素を見つけ出しオブジェクトを格納する
##タグ名から要素を見つけ出す
```python
<iframe src="..."></iframe>
---
frame = driver.find_element_by_tag_name("iframe")
# or
frame = driver.find_element(By.TAG_NAME, "iframe")
```
タグ名から要素を見つけ出しオブジェクトを格納する
##名前属性から要素を見つけ出す
```python
<input name="cheese" type="text"/>
---
cheese = driver.find_element_by_name("cheese")
# or
cheese = driver.find_element(By.NAME, "cheese")
```
名前要素から要素を見つけ出しオブジェクトを格納する
##リンクテキストから要素を見つけ出す
```python
<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")
```
リンクテキストから要素を見つけ出しオブジェクトを格納する
##部分リンクテキストから要素を見つけ出す
```python
<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から要素を見つけ出す
```python
<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とは何か?](https://qiita.com/rllllho/items/cb1187cec0fb17fc650a)

```python
<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オブジェクトに変換されます。

```python
element = driver.execute_script("return $('.cheese')[0]")
```
### javascriptでページ上のすべてのラベルのすべての入力要素を見つける

```python
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で一番下までスクロールする

```python
driver.execute_script('window.scrollTo(0,document.body.scrollHeight);')
```
## テキストの値を取得する
```python
element = driver.find_element_by_id("element_id")
element.text
```
## ユーザ入力-フォームの入力
```python
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状態に切り替え送信する
## ウィンドウ間の移動
```python
driver.switch_to.window("windowName")
```
webアプリケーション上に複数のwindowがある場合自動で切り替えれる。

### windowの名前がわからない場合
```python
<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を使うことで自動で取得する。
## フレーム間の移動
```python
driver.switch_to.frame("frameName")
```
## ポップアップ系を扱う
```python
alert = driver.switch_to.alert
# usage: alert.dismiss(), etc.
```
画面上にポップアップする機能を扱う
## 前の画面に戻る
```python
# 前に進む
driver.forward()
# 後ろに戻る
driver.back()
```
## クッキーを扱う
```python
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()
```

## ユーザーエージェントの変更
```python
profile = webdriver.FirefoxProfile()
profile.set_preference("general.useragent.override", "some UA string")
driver = webdriver.Firefox(profile)
```
## ドラッグ&ドロップ

Actionsクラスを使用してドラッグ&ドロップする方法
*ネイティブイベントの有効が必要

Actionsクラスはマウスとキーボードの２つのアクションを一連の流れで実行するクラス

[Actionsクラス チュートリアル(英語)](https://www.guru99.com/keyboard-mouse-events-files-webdriver.html)

```python
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**を使う

```python
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が投げられる。

### 暗黙的な場合

暗黙的な待機が設定される。

```python
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"
```
## スクリーンショットを撮る

```python
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オブジェクトを使用する以下の手法を使用できます。これにより、システムのプロキシ設定が一時的に変更され、実行時に元の状態に戻ります。」

```python
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に詳しくないのも原因だが

```python
<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して使おう

```python

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('これ以上クリックできません')

```





#　終わり

とりあえず自分的に使うかなーと思うものを集めて見ました。

下記のウェブサイトを参考にさせてもらいました。
ありがとうございます。いろいろ助かりました。

参考文献

- [クローラ作成に必須！XPATHの記法まとめ](https://qiita.com/rllllho/items/cb1187cec0fb17fc650a)
- [SeleniumHQ](https://www.seleniumhq.org/docs/03_webdriver.jsp#setting-up-a-selenium-webdriver-project)
- [Mouse Click & Keyboard Event: Action Class in Selenium Webdriver](https://www.guru99.com/keyboard-mouse-events-files-webdriver.html)