TL;DR
- pythonのDockerコンテナでSeleniumを実行したスクレイピングで色々はまった。
経緯
とあるサイトにログインして表示される情報をcronで取得したいと思い、pythonのDockerコンテナを利用してChrome,ライブラリ等をインストールしてプログラムを作成した。結構はまったポイントがあったので備忘のため記録する。
オプションが必要
--headless
: まぁ当然--no-sandbox
: 利用するDockerコンテナがrootで動くために必要--disable-dev-shm-usage
:/dev/shm
の容量不足でクラッシュするのを防ぐために必要(https://stackoverflow.com/questions/53902507/unknown-error-session-deleted-because-of-page-crash-from-unknown-error-cannot)--user-agent=Mozilla...
: 今回アクセスしたサイトでは、ユーザーエージェントを変えないとForbiddenが返ってきた
XPathによるアクセスはやめた方がよい
- 階層が深いと何やってるのかわからなくなるし、調査するのも大変。
find_element(By.ID,"...")
を使う。IDあればID、なければクラス名とか、AタグであればLINK_TEXTとか- 該当のターゲットだけで一位にならないのであれば、一位となる上位の要素を取得してそこからfind_elementするとか
画面の描画をsleepで待つのはやめた方がよい
- 対象の要素があれば、以下のように取得する
from selenium.webdriver.support.wait import WebDriverWait ele_email: WebElement = WebDriverWait(driver, timeout=TIMEOUT_PAGE_LOAD).until( lambda d: d.find_element(By.NAME,"some_name"))
- 画面の描画完了待ちであれば、以下のように記述する
WebDriverWait(driver, TIMEOUT_PAGE_LOAD).until( lambda d: d.execute_script('return document.readyState') == 'complete')
sourceを確認しながら1画面ずつ進める
- 処理が進んでたと思ったらエラーページでした、だとつらいので。
logger.debug(driver.page_source)