Selenium(Python)の個人的スニペット集

# はじめに
本記事はSeleniumで私が個人的に使うためのスニペットのまとめです。
自分が使うためのスニペット集なので内容は偏っています。また一部Seleniumとは直接関係ないものも含まれています。

Seleniumの一通りの使い方を知りたい方は、以下のような素敵な記事がありますので、そちらをご参照ください。

- [Python + Selenium で Chrome の自動操作を一通り](https://qiita.com/memakura/items/20a02161fa7e18d8a693)
- [Selenium webdriverよく使う操作メソッドまとめ](https://qiita.com/mochio/items/dc9935ee607895420186)

## 環境
主に以下の環境向けの情報です。他の環境では一部動作しないものがあると思います。
・macOS Catalina
・Python 3.8.3
・selenium 3.141.0
・Google Chrome 91.0.4472.19

#目次（スニペット+α）
<details><summary>タップで展開</summary><div>

1. [とりあえず動かす](#とりあえず動かす)
1. [終了時に閉じる](#終了時に閉じる)
1. [WebDriverを自動更新する](#webdriverを自動更新する)
1. [要素の取得・操作](#要素の取得操作)
1. [普通のスクリーンショット取得](#普通のスクリーンショット取得)
1. [ページ全体のスクリーンショット(ヘッドレスモード)](#ページ全体のスクリーンショットヘッドレスモード)
1. [Headlessモードで起動](#headlessモードで起動)
1. [JavaScript実行](#javascript実行)
1. [要素をクリックする直前・直後に何か処理をする](#要素をクリックする直前直後に何か処理をする)
1. [Basic認証を突破する](#basic認証を突破する)
1. [Chrome DevTools Protocolコマンドの実行](#chrome-devtools-protocolコマンドの実行)
1. [【Chrome】ページ全体のスクリーンショットを撮る](#chromeページ全体のスクリーンショットを撮る)
1. [【Headless Chrome】WebページをPDFに保存する](#headless-chromewebページをpdfに保存する)
1. [【Chrome】ページをMHTML形式で1つのファイルに保存する](#chromeページをmhtml形式で1つのファイルに保存する)
1. [【Chrome】「この接続ではプライバシーが保護されません」が表示されるページにアクセスする](#chromeこの接続ではプライバシーが保護されませんが表示されるページにアクセスする)
1. [【Chrome】カスタムヘッダの付与](#chromeカスタムヘッダの付与)
1. [ネットワーク情報を取得する](#ネットワーク情報を取得する)
1. [最新のChromeDriverのバージョンが知りたい](#最新のchromedriverのバージョンが知りたい)
1. [【Docker】Ubuntu 20.04にSeleniumの環境を構築](#dockerubuntu-2004にseleniumの環境を構築)
1. [【Docker】CentOS 7.9にSeleniumの環境を構築](#dockercentos-79にseleniumの環境を構築)
1. [【Google Colab】Seleniumを使うための準備](#google-colabseleniumを使うための準備)
1. [【Google Colab】ノートブック上に画像を表示する](#google-colabノートブック上に画像を表示する)
1. [【Google Colab】Googleドライブをマウントする](#google-colabgoogleドライブをマウントする)
1. [【Google Colab】Googleスプレッドシートの中身を読み取る](#google-colabgoogleスプレッドシートの中身を読み取る)
1. [LINEに通知を送る](#lineに通知を送る)
1. [テスト用サイト](#テスト用サイト)
1. [開発者ツールでXPathで要素を取得する](#開発者ツールでxpathで要素を取得する)
1. [ドキュメント等](#ドキュメント等)

</div></details>

# とりあえず動かす
```console
$ pip install selenium
$ pip install webdriver-manager
```

```python:selenium-sample.py
import time
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager

# Webdriver ManagerでChromeDriverを取得
driver = webdriver.Chrome(ChromeDriverManager().install())

# Qiitaトップページにアクセス
driver.get('https://qiita.com/')
time.sleep(5)

driver.close()
driver.quit()
```

# 終了時に閉じる
Seleniumを触っていくうちに、いつの間にかWebDriverのプロセスが増殖しがちです。
それをできるだけ防ぐためにプログラム終了時にDriverを終了させておきます。

```python
import atexit

# プログラム終了時に実行させる関数
def tear_down():
    driver.close()
    driver.quit()

# 終了ハンドラの設定
atexit.register(tear_down)
```

[Seleniumのドキュメント](https://www.selenium.dev/documentation/en/)のサンプルコードを見ると、with構文で書かれていたので、こちらの方がスマートかもしれません。

```python
with webdriver.Chrome(ChromeDriverManager().install()) as driver:
    # Qiitaトップページにアクセス
    driver.get('https://qiita.com/')
    time.sleep(5)
```

# WebDriverを自動更新する
既に上で使っていますが、[Webdriver Manager](https://github.com/SergeyPirogov/webdriver_manager)を使うと、自分でブラウザのバージョンに合ったdriverを取ってきたりする手間が省けます。
Webブラウザが更新されて、driverの対応バージョンと合わずエラーになるということも防げます。

```console
$ pip install webdriver-manager
```

```python
from webdriver_manager.chrome import ChromeDriverManager
# Webdriver ManagerでChromeDriverを取得
driver = webdriver.Chrome(ChromeDriverManager().install())
```

参考：[Python+SeleniumWebDriverではwebdriver_managerを使うといちいちdriverのexeを置き換えなくて済む](https://qiita.com/YoshikiIto/items/000f241f6d917178981c)

https://qiita.com/YoshikiIto/items/000f241f6d917178981c

# 要素の取得・操作
Pythonの[Selenium APIドキュメント](https://www.selenium.dev/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.find_element)や[Selenium API(逆引き)](https://www.seleniumqref.com/api/webdriver_gyaku.html)、[Python + Selenium で Chrome の自動操作を一通り](https://qiita.com/memakura/items/20a02161fa7e18d8a693#%E8%A6%81%E7%B4%A0%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B)を参照するのがわかりやすいです。

あえて書くこともないので、ここでは、[テスト自動化練習サイト](https://hotel.testplanisphere.dev/ja/signup.html)の会員登録ページで使ったコードを貼り付けておきます。

```python
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.select import Select

# フォームに会員情報を登録する関数
def register_member(email, password, username, rank, address, tel, gender, birthday, notification):
    # 性別用
    gender_index = {"男性": "1", "女性": "2", "その他": "9"}
    if gender in gender_index:
        gender_value = gender_index[gender]
    else:
        gender_value = "0"
    # 会員種別用
    rank_value = 'normal' if rank == '一般会員' else 'premium' 
    # 各項目の入力
    driver.find_element_by_name("email").send_keys(email)
    driver.find_element_by_name("password").send_keys(password)
    driver.find_element_by_name("password-confirmation").send_keys(password)
    driver.find_element_by_name("username").send_keys(username)
    driver.find_element_by_xpath('//input[@name="rank" and @value="' + rank_value + '"]').click()
    driver.find_element_by_name("address").send_keys(address)
    driver.find_element_by_name("tel").send_keys(tel)
    # 性別の入力
    select = Select(driver.find_element_by_id("gender"))
    select.select_by_value(gender_value)
    # 生年月日の入力
    driver.find_element_by_name("birthday").clear()
    driver.find_element_by_name("birthday").send_keys(birthday)
    # お知らせを受け取る場合にチェックボックスにチェック
    if notification == "受け取る":
        driver.find_element_by_name("notification").click()

    driver.find_element_by_xpath('//button[text()="登録"]').click();
    # 登録完了ページのスクリーンショットを取得
    driver.save_screenshot('complete.png')

    driver.find_element_by_xpath('//button[text()="ログアウト"]').click();

# テスト用の会員登録フォームに移動
driver.get('https://hotel.testplanisphere.dev/ja/signup.html')
# 会員登録
register_member("murtwiry@example.com", "fpfuo2x9", "鈴木　陽葵",
                "一般会員", "北海道札幌市中央区北３条西６丁目", "09022223333",
                "女性", "11/22/1995", "受け取る")
```

# スクリーンショットを撮る
Chrome DevTools Protocolコマンドを使ったChromeでのページ全体のスクリーンショット取得は、本記事内の[【Chrome】ページ全体のスクリーンショットを撮る](#chromeページ全体のスクリーンショットを撮る)もご参照ください。

## 普通のスクリーンショット取得
普通にブラウザに表示されている範囲のスクリーンショットを取得する場合は、以下のコードでできます。

```python
import os

driver.get('https://qiita.com/')
# スクリーンショットを取得し保存
filename = os.path.join(os.path.dirname(os.path.abspath(__file__)), "screenshot.png")
driver.save_screenshot(filename)
```

## ページ全体のスクリーンショット(ヘッドレスモード)
JavaScriptでページ全体のサイズを取得し、ウィンドウをページ全体のサイズに設定してから、スクリーンショットを撮影します。

```python
def save_full_screenshot(driver, img_path):
    width = driver.execute_script("return document.body.scrollWidth;")
    height = driver.execute_script("return document.body.scrollHeight;")
    driver.set_window_size(width, height)
    driver.save_screenshot(img_path)

save_full_screenshot(driver, filename)
```

# Headlessモードで起動
ChromeでHeadlessモードを利用する場合は、`--headless`のオプションを使います。
環境や対象ページによって、その他にオプションが必要になることがあります。

```python:headless.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# Headless Chromeのためのオプション
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-gpu')

with webdriver.Chrome(options=options) as driver:
    driver.get('https://qiita.com/')
    driver.save_screenshot('headless.png')
```

Headlessモードでのオプションについては、以下の記事の「発展編 ブラウザを起動しないでスクレイピング」が参考になります。

参考：[実践/現場のPythonスクレイピング](https://qiita.com/ulwlu/items/c84501993635c72540a7)

https://qiita.com/ulwlu/items/c84501993635c72540a7#%E7%99%BA%E5%B1%95%E7%B7%A8-%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%AA%E3%81%84%E3%81%A7%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0

<!--
参考：[Getting Started with Headless Chrome](https://developers.google.com/web/updates/2017/04/headless-chrome)

https://developers.google.com/web/updates/2017/04/headless-chrome
-->

# JavaScript実行
`driver.execute_script`メソッドを使います。

```python
# Qiitaトップページにアクセス
driver.get('https://qiita.com/')
# 投稿記事のタイトル一覧を取得して表示
titles = driver.execute_script('''
    var nodeList = document.querySelectorAll('article > h2 > a');
    titles = Array.from(nodeList).map(a => a.textContent);
    return titles;
''')
for title in titles:
    print(title)
```

  参考：[JavaScriptを書ける人であれば誰でもスクレイピングはできるよっていう話](https://qiita.com/centerfield77/items/425780a673568d3008e6)

https://qiita.com/centerfield77/items/425780a673568d3008e6

# 要素をクリックする直前・直後に何か処理をする
要素のクリックイベントの前後に処理を行うことができます。
その他にもいくつかイベントの前後に処理を行うことができるものが存在します。詳しくは、`abstract_event_listener`の[APIドキュメント](https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.abstract_event_listener.html#module-selenium.webdriver.support.abstract_event_listener)をご参照ください。

```python
from selenium.webdriver.support.events import EventFiringWebDriver, AbstractEventListener

# イベント補足クラスを定義
class CustomListener(AbstractEventListener):
    # クリック前に要素までスクロール
    def before_click(self, element, driver):
        driver.execute_script('arguments[0].scrollIntoView({behavior: "smooth", block: "center"});', element)
    # クリック後に3秒待つ
    def after_click(self, element, driver):
        time.sleep(3)

base_driver = webdriver.Chrome(ChromeDriverManager().install())
driver = EventFiringWebDriver(base_driver, CustomListener())
```

参考：[【Python】before_click/after_click・・・要素がクリックされる直前/直後の処理を実施する](https://www.seleniumqref.com/api/python/event/Python_after_click.html)

https://www.seleniumqref.com/api/python/event/Python_after_click.html

# Basic認証を突破する
```python
driver.get("http://username:password@example.com")
```
  参考：[SeleniumでBasic認証有のサイトにログインする](https://yoshikiito.net/blog/archives/473/)

https://yoshikiito.net/blog/archives/473/

ユーザ名が例えば、`mail@example.com`のようなメールアドレスの場合は、`@`を`%40`に置き換えて、以下のようにします。

```python
driver.get("http://mail%40example.com:password@example.com")
```

`@`や`#`等、URLの中で特別な意味を持つ文字は、パーセントエンコーディングしてあげる必要があります。

  参考：[Percent-encoding (パーセントエンコーディング) | MDN Web Docs](https://developer.mozilla.org/ja/docs/Glossary/percent-encoding)

# Chrome DevTools Protocol関連
Chrome系のブラウザに限定されるかもしれませんが、ブラウザの開発者ツールにあるような機能を実行できる[Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/)に関するスニペットです。

## Chrome DevTools Protocolコマンドの実行
```python
driver.execute_cdp_cmd("Chrome DevTools Protocolのコマンド", "コマンドのパラメータ")
```

  参考：[execute_cdp_cmd](https://www.selenium.dev/selenium/docs/api/py/webdriver_chromium/selenium.webdriver.chromium.webdriver.html#selenium.webdriver.chromium.webdriver.ChromiumDriver.execute_cdp_cmd)

https://www.selenium.dev/selenium/docs/api/py/webdriver_chromium/selenium.webdriver.chromium.webdriver.html#selenium.webdriver.chromium.webdriver.ChromiumDriver.execute_cdp_cmd

## 【Chrome】ページ全体のスクリーンショットを撮る
  詳細記事：[【Chrome】Seleniumでページ全体のスクリーンショットを撮る](https://qiita.com/mochi_yu2/items/d1a2c91776eba93c25e5)

```python
import base64

def take_full_screenshot(driver, file_path):
    width = driver.execute_script("return document.body.scrollWidth;")
    height = driver.execute_script("return document.body.scrollHeight;")
    viewport = {
        "x": 0, 
        "y": 0,
        "width": width,
        "height": height,
        "scale": 1
    }
    # Chrome Devtools Protocolコマンドを実行し、取得できるBase64形式の画像データをデコードしてファイルに保存
    image_base64 = driver.execute_cdp_cmd("Page.captureScreenshot", {"clip": viewport, "captureBeyondViewport": True})
    image = base64.b64decode(image_base64["data"])
    with open(file_path, 'bw') as f:
        f.write(image)

driver.get('https://qiita.com/')
take_full_screenshot(driver, 'screenshot.png')
```

## 【Headless Chrome】WebページをPDFに保存する
  詳細記事：[SeleniumとHeadless ChromeでページをPDFに保存する](https://qiita.com/mochi_yu2/items/a845e52b8aa677f132bf)

```python
import base64

def save_to_pdf(driver, file_path):
    parameters = {
        "printBackground": True, # 背景画像を印刷
        "paperWidth": 8.27, # A4用紙の横 210mmをインチで指定
        "paperHeight": 11.69, # A4用紙の縦 297mmをインチで指定
    }
    # Chrome Devtools Protocolコマンドを実行し、取得できるBase64形式のPDFデータをデコードしてファイルに保存
    pdf_base64 = driver.execute_cdp_cmd("Page.printToPDF", parameters)
    pdf = base64.b64decode(pdf_base64["data"])
    with open(file_path, 'bw') as f:
        f.write(pdf)

driver.get('https://qiita.com/')
save_to_pdf(driver, 'qiita.pdf')
```

## 【Chrome】ページをMHTML形式で1つのファイルに保存する
WebページをMHTML形式(Webページを1つのファイルに保存するための形式)で保存することができます。

```python:cdp-mhtml.py
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
import time

with webdriver.Chrome(ChromeDriverManager().install()) as driver:
    driver.get('https://qiita.com/')
    # ページをMHTML形式で保存
    mhl = driver.execute_cdp_cmd("Page.captureSnapshot", {})
    time.sleep(3)
    with open('qiita.mhtml', 'w') as f:
        f.write(mhl["data"])
```

- [Page.captureSnapshot](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-captureSnapshot)メソッドを利用
- `{"code":-32000,"message":"Failed to generate MHTML"}`というエラーが発生することがありました。原因はわかりませんが、`time.sleep(3)`をとりあえず入れて回避しています。

## 【Chrome】「この接続ではプライバシーが保護されません」が表示されるページにアクセスする

```python
driver.execute_cdp_cmd("Security.setIgnoreCertificateErrors", {"ignore": True})
driver.get('https://expired.badssl.com/')
```

- 諸般の事情により、SSL/TLS証明書の不備があるサイトにアクセスする必要がある時に
- [Security.setIgnoreCertificateErrors](https://chromedevtools.github.io/devtools-protocol/tot/Security/#method-setIgnoreCertificateErrors)を利用
- EXPERIMENTALが付与されたメソッドのため、将来利用できなくなる可能性があります

## 【Chrome】カスタムヘッダの付与
```python
custom_headers = {
    "X-Custom-Header1": "value1",
    "X-Custom-Header2": "value2",
}
driver.execute_cdp_cmd("Network.enable", {})
driver.execute_cdp_cmd("Network.setExtraHTTPHeaders", {"headers": custom_headers})
```

# ネットワーク情報を取得する
パフォーマンス情報内に含まれるネットワーク情報を取得できます。

```python
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

# ネットワークに関するログを取得するための設定
capabilities = DesiredCapabilities.CHROME
capabilities['goog:loggingPrefs'] = { 'performance': 'ALL' }

driver = webdriver.Chrome(
    executable_path=ChromeDriverManager().install(),
    desired_capabilities=capabilities
)

driver.get('https://qiita.com/')

# ネットワーク情報のログをファイルに書き出す
with open('network.log', 'w') as f:
    for entry_json in driver.get_log('performance'):
        print(entry_json, file=f)
```

参考：[【Python】Selenium側からネットワーク情報を取得する](https://blog.motikan2010.com/entry/2019/11/20/%E3%80%90Python%E3%80%91Selenium%E5%81%B4%E3%81%8B%E3%82%89%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E6%83%85%E5%A0%B1%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B)

https://blog.motikan2010.com/entry/2019/11/20/%E3%80%90Python%E3%80%91Selenium%E5%81%B4%E3%81%8B%E3%82%89%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E6%83%85%E5%A0%B1%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B

# 最新のChromeDriverのバージョンが知りたい
Linux等にChromeDriverをインストールする際のTipsです。

```console
$ CHROMEDRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`
$ echo ${CHROMEDRIVER_VERSION}
```

# Docker関連
Seleniumの公式のDockerイメージがあるため、そちらを利用するのが良いと思いますが、ChromeやSeleniumを入れたDockerfileを作成したい場合のために記載しておきます。

https://github.com/SeleniumHQ/docker-selenium

https://hub.docker.com/u/selenium

## 【Docker】Ubuntu 20.04にSeleniumの環境を構築

```Dockerfile:Dockerfile
FROM ubuntu:20.04

# タイムゾーンを設定
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

# 必要なツールとIPAフォント、Pythonをインストール
RUN apt-get update && apt-get install -y wget gnupg curl vim unzip python3 python3-pip fonts-ipafont fonts-ipaexfont
# Google Chromeをインストール
RUN wget https://dl.google.com/linux/linux_signing_key.pub \
 && apt-key add linux_signing_key.pub \
 && echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list \
 && apt-get update \
 && apt-get install -y google-chrome-stable \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

# Chrome Driverをインストール
RUN CHROMEDRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` \
 && curl -sS -o /tmp/chromedriver_linux64.zip http://chromedriver.storage.googleapis.com/$CHROMEDRIVER_VERSION/chromedriver_linux64.zip \
 && unzip /tmp/chromedriver_linux64.zip \
 && mv chromedriver /usr/local/bin/

# Seleniumをインストール
RUN pip install selenium

RUN google-chrome --version
RUN python3 -V
```

- イメージ作成途中でタイムゾーンの選択を求められ、止まってしまったので、`ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime`というタイムゾーン設定を加えました。

参考：[【2019年版】Ubuntu18.04 にChromeとSeleniumをインストール](https://www.mahirokazuko.com/entry/2019/08/16/202008)

https://www.mahirokazuko.com/entry/2019/08/16/202008

## 【Docker】CentOS 7.9にSeleniumの環境を構築

```Dockerfile:Dockerfile
FROM centos:7.9.2009

# Chrome用のyumリポジトリを設定
RUN echo $'[google-chrome]\n\
name=google-chrome\n\
baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch\n\
enabled=1\n\
gpgcheck=1\n\
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub' > /etc/yum.repos.d/google.chrome.repo

# Google Chrome、Python 3、IPAフォントなどをインストール
RUN yum -y update \
 && yum -y install google-chrome-stable unzip python3 ipa-gothic-fonts ipa-mincho-fonts ipa-pgothic-fonts ipa-pmincho-fonts \
 && rm -rf /var/cache/yum/* \
 && yum clean all

# Chrome Driverをインストール
RUN CHROMEDRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` \
 && curl -sS -o /tmp/chromedriver_linux64.zip http://chromedriver.storage.googleapis.com/$CHROMEDRIVER_VERSION/chromedriver_linux64.zip \
 && unzip /tmp/chromedriver_linux64.zip \
 && mv chromedriver /usr/local/bin/

# Seleniumをインストール
RUN pip3 install selenium

RUN google-chrome --version
RUN python3 --version
```

参考：[CentOS7でSelenium＋Pythonを動かすまで](https://qiita.com/mindwood/items/245adeb6da18999bbfc4)

https://qiita.com/mindwood/items/245adeb6da18999bbfc4

# Google Colaboratory関連
Google Colaboratory（Google Colab）を使うと、Webブラウザ上でSeleniumを使う環境を整えることができます。
また、Googleドライブにファイルを保存したり、Googleスプレッドシートと連携することもできます。

https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja

関連記事：[【Selenium】Googleスプレッドシートを読み込んで会員登録フォームに入力する](https://qiita.com/mochi_yu2/items/00aed4443f6895f022f9)

## 【Google Colab】Seleniumを使うための準備
ChromeDriverと日本語フォントを導入して、WebDriverを使えるようにします。

```python
# ChromeDriver、日本語フォントの導入
!apt-get update
!apt-get install -y chromium-chromedriver fonts-ipafont fonts-ipaexfont
!ln -s /usr/lib/chromium-browser/chromedriver /usr/bin/chromedriver
!pip install selenium

from selenium import webdriver

# WebDriverを準備
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--disable-gpu')
options.add_argument('--window-size=1280,1400')
driver = webdriver.Chrome(executable_path="/usr/bin/chromedriver", options=options)
```

参考：[Googlecolab を使って iRuby で selenium と chromium で徘徊する為に](https://qiita.com/dauuricus/items/0717c8a08aba7abc7575)

https://qiita.com/dauuricus/items/0717c8a08aba7abc7575

## 【Google Colab】ノートブック上に画像を表示する
ヘッドレスChromeを使うため動作が見えないので、スクリーンショットを撮って見ていきます。
この時に、以下のようにすることで、ノートブック上に画像を表示することができます。

```python
# ノートブック上に画像を表示するために導入
from IPython.display import Image, display_png
# スクリーンショット取得
driver.get('https://qiita.com/')
driver.save_screenshot('qiita.png')
# ノートブック上に表示
display_png(Image('qiita.png'))
```

## 【Google Colab】Googleドライブをマウントする
Google ColabからGoogleドライブを使うことができます。
実行すると、Googleドライブ利用の許可を求められるので、指示に従ってコードを入力します。

```python
from google.colab import drive
# Googleドライブをマウント
drive.mount('/content/drive')

# スクリーンショットをGoogleドライブの「Colab」という事前に作成したフォルダに保存
driver.save_screenshot('/content/drive/MyDrive/Colab/screenshot.png')
```

## 【Google Colab】Googleスプレッドシートの中身を読み取る
Googleスプレッドシートにアクセスすることもできます。

```python
from google.colab import auth
from oauth2client.client import GoogleCredentials
import gspread
# 認証処理
auth.authenticate_user()
gc = gspread.authorize(GoogleCredentials.get_application_default())
# 「url_list」という名前のスプレッドシートの先頭ワークシートをオープンして、値を読み込み
worksheet = gc.open('url_list').get_worksheet(0)
url_list = worksheet.get_all_values()
# 中身を表示
for url in url_list:
    print(url)
```

# LINEに通知を送る
直接、Seleniumと関係ありませんが、Seleniumを使ったWebサイトの死活監視等の際の通知用に。
詳細記事：[SeleniumでWeb監視をしてLINEに通知する](https://qiita.com/mochi_yu2/items/c1b5fb8279166598cb92)

```python
import os
import requests

# LINE Notifyのアクセストークン
ACCESS_TOKEN = "YOUR ACCESS TOKEN"
LINE_API = "https://notify-api.line.me/api/notify"

# 結果をLINEへ送信
def notify_to_line(message, image_file_path=None):
    headers = {'Authorization': 'Bearer ' + ACCESS_TOKEN}
    payload = {'message': message}
    files = {}
    if ((image_file_path is not None) and os.path.exists(image_file_path)):
        files = {'imageFile': open(image_file_path, 'rb')}

    response = requests.post(LINE_API, headers=headers, params=payload, files=files)

# テキストのみ送信
notify_to_line('テストメッセージ')
# テキスト + 画像を送信
notify_to_line('スクリーンショット付きメッセージ', 'qiita.png')
```

# その他
スニペットとは違いますが、関連する情報です。

## テスト用サイト
Seleniumの検証でお世話になっているサイトです。

- [テスト用サイト - 日本Seleniumユーザーコミュニティ](http://www.selenium.jp/test-site)
- [HOTEL PLANISPHERE - テスト自動化練習サイト](https://hotel.testplanisphere.dev/)

## 開発者ツールでXPathで要素を取得する
Chromeの開発者ツールで、XPathに対応する要素を取得することができます。
`$x('//input[@id="term"]')`等を開発者ツールのコンソールに入力します。
確認してみると、XPathで一つに特定できていると思っていたのが、実は該当する要素が2つ以上あったというのは、良くあることです。

![xpath.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1423540/71c1f6e7-f35d-7826-85ec-bade0b57e619.png)

参考：[ChromeでXPathを取る・検証する](https://qiita.com/ywindish/items/5a992c49387d81df900e)

https://qiita.com/ywindish/items/5a992c49387d81df900e

## ドキュメント等
- https://pypi.org/project/selenium/
- https://www.selenium.dev/documentation/en/
- [selenium package API](https://www.selenium.dev/selenium/docs/api/py/api.html)
- [Selenium API(逆引き)](https://www.seleniumqref.com/api/webdriver_gyaku.html)

# おわりに
Seleniumから脱線している箇所も多々ありますが、自分のためのスニペット集をまとめました。もし気が向いたら更新をしたいと思います。