Python/Selenium:要素はあるのにNoSuchElementExceptionが出る
Python・Seleniumで作ったとあるプログラム。
こんな状況に出くわしました↓
- 毎日普通に動いていた
- ある日「NoSuchElementException・no such element」、つまり「そんな要素ないよ」と怒られ動かなくなった
- HTML構造を見ると、確実にその要素はある
- でもエラーが続く。要素が取れない
念の為、出ていたエラーはこれ↓。
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"li.categoryItem:nth-child(3)"}
同じような状況におちいっているかたへ向けて「こうしたらとりあえず直った」という方法をメモしておきます。
結論、
WebDriverWaitモジュールを使って明示的に待機を指示する
ことで動くようになりました。
まだ要素が描画される前に取得しようとしていたようです(それまで全く問題なく動いていたので100%納得はできていませんが)。
ちなみに:
「要素はあるけど描画が遅れる」対策で、
driver.implicitly_wait(30)
のように待機指示を書いていましたがダメでWebDriverWaitを使ってさらに明示的な待機を指示したら直りました。
Selenium:要素はあるのにNoSuchElementExceptionが出る
以下、これをこう書き換えたら直った例です。
▼BEFORE
Pythonfrom webdriver_manager.chrome import ChromeDriverManager
from selenium import webdriver
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('xxx URL xxx')
elem_text = driver.find_element_by_class_name('category').text
▼AFTER
Pythonfrom webdriver_manager.chrome import ChromeDriverManager
from selenium import webdriver
# ▼追加
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('xxx URL xxx')
# ▼こんな感じで書き換え
elem_text = WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.CLASS_NAME, 'category'))).text
ちなみに:
上記コードは、chromedriverの更新を自動化するwebdriver_managerという便利ライブラリを使っています。
AFTER 11行目は、
WebDriverWait(driver, 30)
→ 30秒待て
.until(EC.presence_of_element_located((By.CLASS_NAME, 'category')))
→ "category"というクラス名の要素がDOM上に現れるまで
...という意味です。
EC.presence_of_element_located((By.CLASS_NAME,〜の部分は、
- EC.element_to_be_clickable((By.ID, 〜
→ idで指定した要素がクリック可能な状態になるまで待つ - EC.presence_of_all_elements_located((By.CSS_SELECTOR, 〜
→ CSSセレクタで指定した全ての要素がDOM上に現れるまで待つ
のように状況に応じたバリエーションが用意されています。
そのあたりのWebDriverWaitモジュールをざっと把握するには以下を参考にどうぞ。
参考サイト明示的な待機 — Selenium Python Bindings 2 ドキュメント
▼体型的なスクレイピング学習におすすめ