我有一个测试,点击页面上的链接列表。如果我在新页面中打开链接,我可以使用browser.switchTo()。窗口和原始窗口的句柄遍历列表,点击每个链接。
但是,如果我在同一页面(_self)中打开一个链接,并使用browser.navigate()。back()导航回原始链接列表,迭代时单击下一个链接会出现以下错误:
StaleElementReferenceError: stale element reference: element is not attached to the page document
在您离开后,访问先前页面上元素的正确方法是什么?
答案 0 :(得分:0)
当您从Selenium请求对象时,使用内部唯一ID对象的Selenium ID。请参阅以下命令
>>> driver.find_element_by_tag_name("a")
<selenium.webdriver.firefox.webelement.FirefoxWebElement
(session="93fc2bec-c9f8-0c46-aec3-1939af00c917",
element="5173f7fb-63ca-e447-b176-4a226d956834")>
正如您所见,该元素具有唯一的uuid。 Selenium在内部维护这些列表,因此当您执行click操作时,它会从缓存中获取元素并对其执行操作。
刷新页面或加载新页面后,此缓存不再有效。但是您在语言绑定中创建的对象仍然是。如果我尝试在其
上执行某些操作>>> elem.is_displayed()
selenium.common.exceptions.StaleElementReferenceException:
Message: The element reference of [object Null] null
stale: either the element is no longer attached to the DOM or the page has been refreshed
所以简而言之,没有办法使用同一个对象。这意味着你需要改变你的方法。请考虑以下代码
for elem in driver.find_elements_by_tag_name("a"):
elem.click()
driver.back()
上述代码将在elem.click()
的第二次尝试时失败。所以修复是确保不重用集合对象。而是使用基于数字的循环。我可以用许多不同的方式编写上面的代码。考虑以下几种方法
方法1
elems = driver.find_elements_by_tag_name("a")
count = len(elems)
for i in range(0, count):
elems[i].click()
driver.back()
elems = driver.find_elements_by_tag_name("a")
这不是一个非常好的方法,因为我得到一个对象集合,只使用其中一个。一个有500多个奇数链接的页面将使这段代码变得非常慢
方法2
elems = driver.find_elements_by_tag_name("a")
count = len(elems)
for i in range(1, count + 1):
elem = driver.find_element_by_xpath("(//a)[{}]".format(i))
driver.back()
这比方法1更好,因为我只获得一个对象。后来我得到一个并使用一个
方法3
elems = driver.find_elements_by_tag_name("a")
links = []
for elem in elems:
links.append(elem.get_attribute("href"))
for link in links:
driver.get(link)
# do some action
此方法仅在链接基于href时有效。所以根据情况,我会选择或改变我的方法