【错误】Selenium报错:Element is not clickable at point(x, y)原因及解决办法汇总
1. 背景
因为最近在组队学习爬虫,需要用Selenium模拟登录丁香园,其中在尝试运行一位小伙伴的代码的时候,发现自己电脑上(win10台式机)始终会Selenium报错:Element is not clickable at point(x, y)
。很是奇怪,小伙伴上面运行没有问题,到自己这里就无法定位元素点击了。经过2h多的摸索和尝试排除,终于找到了解决办法,然后顺带Google一下其他的原因,一起汇总如下:希望以后遇到相似问题的小伙伴能少走弯路。
2. 问题简述(可以略过)
Element is not clickable at point(x, y)
这种问题通常出现在使用Chrome驱动程序,因为Chrome浏览器使用点位置。 当元素位置未固定且我们尝试对该特定元素执行某些操作时,将导致错误为Element is not clickable at point (xx, xx). Other element would receive the click。当元素加载到DOM中,但UI上的位置不固定时,就会发生这样的错误。 可能存在一些未完全加载的其他div或图像或广告。 ChromeDriver总是尝试单击元素的中间部分。
有一些方法可以解决这个问题。 但要确保最好和最简单的解决方案是找出解决问题的确切原因。 我们需要弄清楚div / image的哪个部分需要时间来加载。 在单击元素之前,我们需要确保元素存在于DOM中,在UI中可见,最后一个是Position是固定的。 当元素位置固定时,问题就解决了。 如果要检查,请尝试Thread.sleep或在调试模式下验证。
下面列出问题及解决方案。
2. 最大化浏览器窗口
这是最简单也是大多数人的问题所在。博主就是其中之一。当你的电脑的屏幕分辨率大于1024X768时,你你可以尝试最大化浏览器来解决问题。博主的是台式机,分辨率1920X080,小伙伴时笔记本。所以导致了程序在小伙伴电脑上可以运行,博主的却不行。因为窗口太小,导致元素被折叠了,无法执行一些Selenium操作。
解决办法:最大化浏览器窗口driver.maximize_window()
# 最大化窗口
driver.maximize_window()
# 自定义窗口大小
driver.set_window_size(width, height)
3. 元素还未加载
这是非常常见的原因之一,因为CPU跑得远远快于网页加载的速度,所以我们需要让程序等一下浏览器,等元素加载出来,再执行下一步操作。可以通过强制等待
、隐式等待
、显示等待
三种方法实现。这三种方法的具体区别,大家有兴趣的可以参照博主的另一篇文章爬虫入门学习(六)Selenium学习与实战,里面有对比这三种方法。
这里就简单介绍:
性能上:显示等待>隐式等待>强制等待
解决办法:
# 强制等待
from time import sleep
sleep(t) # 让线程休眠t秒
# 隐式等待
from selenium import webdriver
ff = webdriver.Firefox()
ff.implicitly_wait(10) # seconds
ff.get("http://somedomain/url_that_delays_loading")
myDynamicElement = ff.find_element_by_id("myDynamicElement")
# 显示等待,Selenium自带的WebDriverWait
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
ff = webdriver.Firefox()
ff.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(ff, 10).until(EC.presence_of_element_located((By.ID, "myDynamicElement")))
finally:
ff.quit()
4. 元素在iframe里面
那就切换到iframe,这里需要用到switch_to_frame方法
来切换Frame。
driver.switch_to_frame("frameName") # 根据框架名来切换
driver.switch_to_frame("frameName.0.child") # 子框架
driver.switch_to_default_content() # 返回
更多请参考官方文档
5. 不在视图,下拉滚动条
很多网站的列表页不是立马返回所有内容,是根据视图来显示的。所以,我们就需要拖动滚动条来把要获取的内容显示到视窗里才可以获取到。
page = driver.find_element_by_partial_link_text(u'下一页')
driver.execute_script("arguments[0].scrollIntoView(false);", page)
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, u'下一页'))).click()
更多请参考Selenium下拉滚动条
6. 元素被覆盖
可以使用动作链来解决。
例如下拉菜单,通过hover,让子菜单显示,就可以点击了。
menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")
ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()
更多请参考官方文档
7. 参考资料
对于用JavaScript的小伙伴,可以重点看前面三个参考。
- Element is not clickable at point SeleniumWebdriverException
- Debugging “Element is not clickable at point” error
- Chrome - Element is not clickable at point #2766
- selenium报错Element is not clickable at point及四种解决方法
后记:
我从本硕药学零基础转行计算机,自学路上,走过很多弯路,也庆幸自己喜欢记笔记,把知识点进行总结,帮助自己成功实现转行。
2020下半年进入职场,深感自己的不足,所以2021年给自己定了个计划,每日学一技,日积月累,厚积薄发。
如果你想和我一起交流学习,欢迎大家关注我的微信公众号每日学一技
,扫描下方二维码或者搜索每日学一技
关注。
这个公众号主要是分享和记录自己每日的技术学习,不定期整理子类分享,主要涉及 C – > Python – > Java,计算机基础知识,机器学习,职场技能等,简单说就是一句话,成长的见证!