Selenium中的陈旧元素参考错误

我在运行selenium测试时遇到错误

Exception in thread "main" org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document (Session info: chrome=63.0.3239.84) (Driver info: chromedriver=2.34.522932 ( 4140ab217e1ca1bec0c4b4d1b148f3361eb3a03e),platform=Mac OS X 10.12.6 x86_64) (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 0 milliseconds For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html 01T19:05:14.666Z'. 

这是代码

  List category = driver.findElements(By.className("a2s-skill-block")); for(int i = 0;i<category.size();i++) { category.get(i).click(); Thread.sleep(7000); driver.navigate().back(); // WebElement skills1 = driver.findElement(By.id("iApps")); //skills1.click(); Thread.sleep(15000); } 

我在这个问题上经历了类似的主题post并尝试了很多其他成员提到的解决方案,但不知何故,等待和预期的COndition似乎不起作用。任何其他的思想方向都非常感激。

这些是我试过的选项

  1. 通过Thread.sleep()方法增加了等待时间
  2. 引入等待和预期条件

    WebDriverWait wait = new WebDriverWait(driver,150);

    wait.until(ExpectedConditions.aresentOfAllElementsLocatedBy(By.className(“text-heading”)));

您应该花一些时间阅读并了解StaleElementReferenceException是什么。 重要的是要了解导致它的原因以及如何避免它。

在这种情况下,您正在抓取页面并使用第1页的元素加载category 。然后单击某个链接,将您带到第2页。此时, category中的所有引用都已过时,但尚未引发exception因为你还没有访问任何变量。 然后使用.back()返回到第1页并尝试使用category执行某些操作并获取exception。

为避免这种情况,您需要在从另一页使用.back()后将元素重新category到第1页上。 一种方式是我在下面写的。 页面在每个循环的底部被抓取。

 List category = driver.findElements(By.className("a2s-skill-block")); for (int i = 0; i < category.size(); i++) { category.get(i).click(); // sleeps are a bad practice, use WebDriverWait instead driver.navigate().back(); driver.findElement(By.id("iApps")).click(); // sleeps are a bad practice, use WebDriverWait instead category = driver.findElements(By.className("a2s-skill-block")); } 

您可以在循环之前找到页面上的所有类别。 当您点击循环内部的某些内容进入另一个页面时,实际上已经触发了“陈旧元素参考”,最终无法回到最后一页。

以下条件将触发’Stale Element Refrence’

条件1

上次进入页面时使用找到的元素,并且您至少离开页面一次(即使您再次返回)。

您可以认为,当您进入页面时,Selenium将为Selenium内部的页面分配一个引用,即使您进入同一页面,但Selenium无法知道它们是相同的,因此它将分配一个新的引用。

您只能使用找到的元素,哪个页面引用与您当前页面相同。

条件2

留在页面上(不要离开它),但是你的脚本触发了找到的元素的HTML DOM节点更改/重新附加/删除。 例如,DOM节点的某些属性发生了变化,或者DOM节点被删除并再次添加回去,所有这些都没有改变。

因此,找到的元素的DOM节点上的任何更改/移动都将触发“Stale Element Refrence”。 您可以认为条件1只是改变/移动DOM节点的另一种方式。

要解决您的问题,您应该读出所有类别的属性,该属性可用于在循环中稍后标识该类别。

以下代码假设每个类别都有唯一的文字:

 List category = driver.findElements(By.className("a2s-skill-block")); List categoryTexts = new ArrayList(); for(WebElement it: category) { categoryTexts.add(it.getText()); } for(int i = 0;i