よっしーの私的空間

機械学習を中心に興味のあることについて更新します

Seleniumエラー:Element is not clickable at point (xxx, xxx)について

Selenium使用時に「Element is not clickable at point (xxx, xxx)」というエラーが出て色々調べたので、その内容についてまとめます。

1.結論

最初に結論だけ述べると、、

  • エラー原因:画面外のelementを操作しようとしたため
  • 解決方法:対象のelementまでSeleniumでスクロールする
2.事象再現

まずは適当にSeleniumを使って事象を再現してみます。

#モジュールのインポート
import glob
import datetime
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# ブラウザ起動
driver = webdriver.Chrome()
driver.maximize_window()

# アクセスするURL
TARGET_URL = "https://suumo.jp/chintai/tokyo/ensen/"

# 対象サイトへアクセス
driver.get(TARGET_URL)
time.sleep(2)

#チェックボックスをクリック
elements = driver.find_elements(By.CLASS_NAME, 'js-fr-checkSingle')
elements[10].click()
elements[30].click()

試していただければ分かると思いますが、実はelement[10].click()をコメントアウトすると、element[30]が画面外にあるボタンであるにも関わらず、エラーは起きないです。つまり、より詳細な原因としては、「一つ目のボタンを選択した状態で、画面外のボタンを操作しようとするとエラーになる」ようです。

3.解決方法

解決するために、Seleniumを使って画面スクロールします。

#element[30]が画面の真ん中らへんに来るように調整
window_size = driver.get_window_size()
loc_y =  elements[30].location['y']
if loc_y < window_size['height']/2:
    scroll_y = 0
else:
    scroll_y = loc_y - window_size['height']/2
driver.execute_script(f"window.scrollBy(0, {scroll_y});")
elements[30].click()

以下のようにシンプルに対象elementまでスクロールしちゃってもいいのですが、WEBページによってはヘッダが邪魔で対象elementが隠れちゃうことがあります。隠れちゃうと同じエラーが出るので、少しめんどくさいですが、対象elementが真ん中らへんに来るように調整してます。スマートな実装があれば教えてほしいです。

4.ソース一式

#モジュールのインポート
import glob
import datetime
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

# ブラウザ起動
driver = webdriver.Chrome()
driver.maximize_window()

# アクセスするURL
TARGET_URL = "https://suumo.jp/chintai/tokyo/ensen/"

# 対象サイトへアクセス
driver.get(TARGET_URL)
time.sleep(2)

#チェックボックスをクリック
elements = driver.find_elements(By.CLASS_NAME, 'js-fr-checkSingle')
elements[10].click()

#element[30]が画面の真ん中らへんに来るように調整
window_size = driver.get_window_size()
loc_y =  elements[30].location['y']
if loc_y < window_size['height']/2:
    scroll_y = 0
else:
    scroll_y = loc_y - window_size['height']/2
driver.execute_script(f"window.scrollBy(0, {scroll_y});")
elements[30].click()