【2022年度版】Python + Selenium よく使う操作メソッドまとめ

# はじめに
WebスクレイピングでSeleniumを使っており、かれこれ1年以上経ちます。

いつも「あれ？？これどうやって書くんだっけ？？」となり、毎回調べているのうんざりし始めたので、本記事にまとていくことにしました。


# ChromeOptions
必要なオプションが設定されていないと、稀に下記のようなタイムアウトエラーが発生します、

```
Timed out receiving message from renderer: 600.000
```

この件について、[Stack Overflowの回答](
https://stackoverflow.com/questions/48450594/selenium-timed-out-receiving-message-from-renderer)では、以下のオプション設定を行えば問題ないそうです。ちなみに「役に立たない増え続ける引数オプション」と呼ばれています。（まさにその通り・・・)

```python
options = webdriver.ChromeOptions()
options.add_argument("start-maximized")
options.add_argument("enable-automation")
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--disable-infobars")
options.add_argument('--disable-extensions')
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-browser-side-navigation")
options.add_argument("--disable-gpu")
options.add_argument('--ignore-certificate-errors')
options.add_argument('--ignore-ssl-errors')
prefs = {"profile.default_content_setting_values.notifications" : 2}
options.add_experimental_option("prefs",prefs)

driver = new ChromeDriver(options);
```

# 要素探索

**親要素**

```python
driver.find_element_by_xpath('//div[@id="cnfm_btn"]').find_element_by_xpath('..')
```

**子要素**

```python
driver.find_element_by_xpath('//div[@id="cnfm_btn"]/div')
```

**子要素（取得要素を基に）**

```python
anchors = driver.find_elements_by_xpath("//*[(@id='movie_link')]")
for anchor in anchors:
    anchor.find_element_by_xpath(".//img") #[.]を付けることで親要素の配下が対象となる
```

**隣の要素（前）**

```python
driver.find_element_by_xpath("//p[@id='one']/preceding-sibling::p")
```

**隣の要素（後）**

```python
driver.find_element_by_xpath("//p[@id='one']/following-sibling::p")
```

**クラス名で探す(単数)**

```python
driver.find_element_by_class_name('content')
```

**クラス名で探す(複数)**

```python
driver.find_elements_by_class_name('content')
```

**テキストコンテントで探す**
React等で作成されたサイトはID等のキーを用いて要素を探索する事が難しくなっています。
例えば、Twitterはログインボタンに`id="login"`と要素特定するためのキーが無いので探索が少し難しいです。。
![20200709.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246142/0467c8c6-2433-e530-2451-6ed5fde1e65a.png)

そこで、一つの打開策としてテキストコンテントで探す方法があります。[(Stack Overflowの回答)](https://stackoverflow.com/questions/12323403/how-do-i-find-an-element-that-contains-specific-text-in-selenium-webdriver-pyth)

・部分一致

```python
driver.find_elements_by_xpath("//*[contains(text(), 'My Button')]")
```


・完全一致

```python
driver.find_elements_by_xpath("//*[text()='My Button']")
```


**ID、クラス名（部分一致）で探す**
こちらも同じくReact等で作成されたサイトはID、Class等のキーを用いて要素を探索する事が難しくなっています。ID、クラス名の部分一致で探す方法があります。

```python
driver.find_element_by_xpath("//div[contains(@class, 'playerStateIcon')]")
```

# 要素操作

**削除**
JavaScriptを実行して要素を削除することが出来ます。

```python
#クラス名で特定して削除する場合
element = driver.find_element_by_class_name('classname')
driver.execute_script("""
var element = arguments[0];
element.parentNode.removeChild(element);
""", element)
```

**ダウンロード**
urllibを用いファイルダウンロードを行います。
```python
import urllib
data = urllib.request.urlopen("https://sample.com/sample.png").read()
with open(f"sample.png", mode="wb") as f:
    f.write(data)
```

# 画面操作
**スクロール**
JavaScriptを実行してスクロールが出来ます。

```python
footer = driver.find_element_by_xpath("//*[(@id='footer')]") #画面下部にある要素を取得する
driver.execute_script("arguments[0].scrollIntoView();",footer)
```

# 明示的な待機処理
WebDriverWait.untilメソッドで、任意のHTMLの要素が特定の状態になるまで待つ明示的な待機時間を設定することができます。詳細は[こちら](https://kurozumi.github.io/selenium-python/api.html#module-selenium.webdriver.support.expected_conditions)。

**クリック可能か判定**

```python
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "cnfm_btn")))
```

**選択可能か判定**

```python
WebDriverWait(driver, 10).until(EC.element_located_to_be_selected((By.ID, "cnfm_btn")))
```