我正在尝试在Internet Explorer中使用一些针对Chrome开发的脚本(并且在那里工作很棒),并且发现StaleElementReferenceExceptions似乎是常态。显然这是因为IE太慢了?
我理解,这些例外是在您找到Webelement时发生的,然后DOM更改,然后您尝试对该Webelement做点事,这使Selenium感到困惑,因为页面现在已更改,网络中的引用没有更长的有效。如果这就是为什么发生StaleelementReference Exceptions,那么我不知道为什么要看到这个。
我有一个带有闪光灯播放器的新窗口,在Flash Player播放视频之后,我尝试从对象中获取一些参数。页面源看起来有点像这样:
<object id="flashContent" width="100%" height="100%" type="application/x-shockwave-flash" name="flashContent" data="[redacted]" style="visibility: visible;">
<param name="scale" value="noscale">
<param name="wmode" value="opaque">
<param name="allowfullscreen" value="true">
<param name="allowscriptaccess" value="always">
<param name="bgcolor" value="">
<param name="SeamlessTabbing" value="false">
<param name="flashvars" value="[redacted]">
</object>
我有兴趣阅读flashvars param的值,所以我有以下代码:
text = driver.findElement(By.cssSelector("object#flashContent param[name='flashvars']")).getAttribute("value");
因此,我不能减少找到param webelement和获得其属性的时间,而且似乎每次都在扔staleelementReferenceException。我已经打开了页面源并观看了窗口 - 据我所知,什么都没有改变。我尝试在一段时间内捕获例外,只是重试希望我能达到dom安静且网络元素稳定的时间,但以下代码完全帮助我:
timer.start();
while (true) {
try {
text = getDriver().findElement(By.cssSelector("object#flashContent param[name='flashvars']"))
.getAttribute("value");
break;
} catch (StaleElementReferenceException e) {
if (timer.getElapsedSeconds() >= 20) {
debug("getAttribute is borked, throwing up...");
throw e;
} else {
debug("getAttribute failed again but we're still trying after " + timer.getElapsedMilliseconds() + " milliseconds.");
}
}
}
上面的设计是为了继续尝试查找/getAttribute组合,即使抛出了staleelementReferenceException,直到通常会超时到达Findelement Call的时间(隐含的超时时间为20秒)。运行它的结果是,Findelement Call成功了,然后GetAttribute呼叫将整个20秒钟左右的staleelementReferenceException扔了一次staleelementReferenceException。然后它倾倒了。在此期间,页面上什么都没发生,至少我无法看到。
关于这种情况在这种情况下为什么或如何陈旧的想法?
编辑:我找到了一个仅适用于您仅从页面中获取数据的情况(即,从页面中获取属性或文本而不是单击或发送键盘,)。我的代码已经使用了一个名为JSOUP的库来将DOM读入内存,如果您需要导航DOM并找到信息,这非常方便,但希望避免在DOM本身上找到一系列低表现的Selenium查找操作。使用JSOUP我能够在DOM的静态版本中阅读并提取我寻求的信息。但是,如果我发现自己要单击或发送钥匙,那么这种解决方法将是没有用的,所以我仍然想知道是否还有其他选择。
StaleElementReferenceException是由您的代码试图找到不再存在DOM中的内容而引起的。如果您使用JSOUP访问DOM的旧版本,则闪存视频末端后DOM的内容不再包含flashvars param和/或其值属性。您的初始方法是使用最快的代码选项正确的:
String text = driver.findElement(By.cssSelector("object#flashContentparam[name='flashvars']")).getAttribute("value");
在视频末端表示视频已经完成,然后尝试查找flashvars param及其值属性之后,等待元素存在于DOM中。P.S。:StaleElementReferenceException很少是由快速或部分(AJAX)页面刷新(&lt; 500 ms)引起的,通常是一个算法问题。