Selenium WebDriver找不到元素的三种情况

时间:2024-05-20 20:02:33

今天抽点时间总结下Selenium WebDriver找不到元素的情况。
当然这里说的是css或者XPath都没写错,定位准确,也并非使用了不稳定的定位语句。


情况一:StaleElementReferenceException: Message: Element not found in the cache...
页面刷新


原因:页面被刷新了。
在当前页面找不到这个元素了,但是你自己手动复制到页面开发者工具上查看明明有啊,为啥在代码里面就找不到了呢?这时,你还可能会问“可是明明元素就在那里,没有变,甚至我是回退回来的,页面都没有变,怎么会说是新页面?”。
其实呢是在操作的过程中页面发生了变化,刷新了,虽然表面上看起来两个元素长得一模一样,事实上是每一个元素都有自己的一个ID号。
用代码(Python)来证明!

# -*- coding: utf-8 -*-
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://cn.bing.com/')
print(driver.find_element_by_id('sb_form_q'))  # sb_form_q before refresh
driver.refresh()  #刷新
#driver.back()    #此处不管是刷新还是点击了其他操作又会回到这个页面都是一样的
print(driver.find_element_by_id('sb_form_q'))  # sb_form_q after refresh
driver.quit()

结果如下图:很明显,element有一个对应的ID是不一样的,只能在当前页面时去使用、存取才会有效。
Selenium WebDriver找不到元素的三种情况

分析:
refresh,不论你是主动刷新还是页面自动刷新
back,已经跳转到了其他页面,然后你用driver.back()跳回来,这也是一张新的页面了
跳转到了新的页面,但这张新页面上有一些元素跟之前页面是长得一样的,这也是一张新的页面了。比如:一排分页按钮,你点击下一页跳转到了第二页,想要还用原来的元素操作到下一页,那也是不可能的了。

解决:
只要刷新页面之后重新获取元素就行,不要提前获取一组元素,然后去循环操作每一个元素,这种情况还是获取元素的个数,然后在循环中获取相应位置的元素,在用的时候才去获取,这样你就获取到最新的id了,也不会出现找错人的尴尬了。

我今天就遇到一个,其实之前也遇到了,只是没有着重记录一下而已。
有一个四个菜单,分别要去带四个传入的数据点击四次,检查是否能到另外一个页面,页面返回是否正常。
我就使用了一个循环,但是最开始没细看,直接循环成了元素,到新页面验证完成之后又返回原来的页面继续定位,发现定位不了了;这时我才想起来不应该循环元素,应该循环元素的个数,在这个循环的过程中再来定位获取元素。
Selenium WebDriver找不到元素的三种情况

情况二:iframe原因定位不到元素需要切换Iframe


【参考此文】这种情况一般发生在有内嵌的iframe的情况下,需要切换一下iframe 
另外注意的是有的页面会有多个iframe,找不到元素同样是没有切换iframe,切换即可。

driver.switchTo()
driver.switchTo(iframeName)

 

情况三:点击速度过快,页面没有加载出来就需要点击页面上的元素。


这个需要增加一定等待时间,显示等待时间可以通过WebDriverWait 和util来实现

 

  1. 添加固定的休眠时间,引入time包 
    这个只能大概估算一下,给个固定值,不是很推荐使用这个,不灵活。
    Python:time.sleep(10) 
    Java:Thread.sleep(1000);//单位是毫秒,1000毫秒=1秒

     
  2. 添加智能等待,隐式的等待一个元素被发现或一个命令完成
    webdriver提供的超时等待,implicitly_wait()方法
    Python:driver.implicitly_wait(20)
     
  3. 添加智能等待时间,在设置的时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置时间检测不到则抛出异常。
    可参考博文:Selenium使用之——添加等待时间的三种方式