Selenium StaleElementReferenceException

时间:2017-01-22 14:50:12

标签: java selenium web-crawler

您好我是Selenium

的新手

我正在使用Java library,已经尝试了ChromeFirefox驱动程序。

我正在运行一个循环。有趣的是,循环有时会工作3次,2次,并不总是在同一次迭代中失败。我认为它与某种竞争条件有关(比如等待页面加载)。如果我在调试模式下运行它似乎完美。

我已经尝试了其他答案的建议,例如wait explicitlyimplicitly,但仍然没有帮助。也许如果你看到代码,你可以帮我一把。

这是一个循环。

WebDriverWait wait = new WebDriverWait(driver,20);
WebElement searchResults = driver.findElement(new By.ById("searchresults"));
searchResults = searchResults.findElement(new By.ByClassName("table"));
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.tagName("a")));
List<WebElement> list=searchResults.findElements(By.tagName("a"));
for(WebElement w: list) {
  result.add(w.getAttribute("href")); //EXCEPTION HAPPENS ALWAYS HERE
}

解决方案是完全破解。我仍然不明白,但它完成了这项工作。如果有人明白为什么请告诉我。

我只是等待所有等待,它表现更好。如果在某些数据检查中抛出异常以确保我得到了我想要的全部内容,我还接受了@Cyril的建议来重新运行迭代。

WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(new By.ById("searchresults")));
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(new By.ByClassName("table"))); 
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.tagName("a")));

2 个答案:

答案 0 :(得分:2)

StaleElementReferenceException表示您正在访问的DOM元素已更改或从DOM中删除。所以等到元素可见或存在没有帮助(之后它们仍然可以更新)。

您可以通过在查找任何DOM元素之前通过Thread.sleep显式等待5秒来修复异常。

另一个选择是look up the element again if the exception is thrown。但它只适用于单个元素。

答案 1 :(得分:2)

为了避免StaleElementReferenceException,你可以在find元素中获取属性。这是一个片段(nth-child第一个索引是1):

List<WebElement> list=searchResults.findElements(By.tagName("a"));
for(int i = 1; i < list.length; i++) {
   result.add(searchResults.findElement(By.cssSelector("a:nth-child(" + i + ")")).getAttribute("href"));
}

这样,异常的唯一机会是元素在findElementgetAttribute之间变化,这是不太可能的(或表元素更改 - searchResults)。 当然,有更好的方法来实现这个,就像findElement周围的包装函数或使用页面对象模式一样,但对于你的情况,它应该足够了。

编辑:你的解决方案可能有效,因为它使脚本等到页面完全加载,然后元素不再改变。