Selenium WebDriveR语言 StaleElementReferenceException 那不应该发生



我正在尝试在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)引起的,通常是一个算法问题。

最新更新