Selenium - 过时的元素参考:元素未附加到页面

Posted

技术标签:

【中文标题】Selenium - 过时的元素参考:元素未附加到页面【英文标题】:Selenium - stale element reference: element is not attached to the page 【发布时间】:2017-12-13 14:17:29 【问题描述】:

我试图了解为什么在我尝试显示从网站获取的项目时它会出错。 我也在使用 google chrome 作为浏览器。

chromeDriver.Navigate().GoToUrl("somewebsites");

chromeDriver.FindElement(By.Id("something.link.text")).Click();
chromeDriver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5));

还有我的代码的其他部分

var item = chromeDriver.FindElementsByXPath("//*[starts-with(@id,\"g_1_\")]/td[3]/span");
foreach (var value in item)

    Console.WriteLine(value.Text); 

每当我使用 "chromeDriver.FindElement(By.Id("something.link.text")).Click();" 时,它都会出错。我无法显示我提取的数据。

在错误消息中,它显示“OpenQA.Selenium.StaleElementReferenceException: 'stale element reference: element is not attach to the page document”。我检查了其他帖子,但我没有弄清楚。我该如何解决?

正如我所读到的,selenium 的响应速度比网站打开时间快得多,因此会出现错误。此外,它很少给出硒无法定位的元素。有什么建议吗?

编辑:如果我从显示功能中删除“.text”,它会显示“OpenQA.Selenium.Remote.RemoteWebElement”。字符串有问题吗?

EDIT2:我可以像这样保存从网站获取的数据:

[i]="System.Collections.ObjectModel.ReadOnlyCollection`1[OpenQA.Selenium.IWebElement]" 为此,我写了这样的东西:

string[] test= new string[100];

for (int i = 0; i < 100; i++)

     kaan[i] = driver.FindElements(By.XPath("//*[starts-with(@id,\"g_1_\")]/td[3]/span")).ToString();

如何转换成文字

【问题讨论】:

StaleElementReference Exception in PageFactory的可能重复 请添加html 【参考方案1】:

我没有在 c# 中工作过,但在 java/selenium 上工作过。但是,我可以给你一个克服陈旧的想法。

通常,如果在启动 web 元素后元素属性或某些内容发生更改,我们将收到 Stale Exception。例如,在某些情况下,如果用户尝试单击同一页面上的同一元素,但在页面刷新后,会出现 staleelement 异常。

为了克服这个问题,我们可以创建新的 web 元素,以防页面发生更改或刷新。下面的代码可以给你一些想法。(它在java中,但概念是一样的)

例子:

 webElement element = driver.findElement(by.xpath("//*[@id='***']"));
 element.click();
 //page is refreshed
 element.click();//This will obviously throw stale exception

为了克服这个问题,我们可以将 xpath 存储在一些字符串中,并使用它创建一个新的 web 元素。

String xpath = "//*[@id='***']";
driver.findElement(by.xpath(xpath)).click();
//page has been refreshed. Now create a new element and work on it
driver.findElement(by.xpath(xpath)).click();   //This works

在这种情况下,我们正在收集一组 web 元素并迭代以获取文本。但是在收集 webelements 和 gettext 后,webelement 似乎有一些变化。我们可以使用循环并随时随地创建元素并获取文本。

for(int i = 0; i<5; i++)

   String value = driver.findElement(by.xpath("//.....["+i+"]")).getText);
   System.out.println(value);

希望这对您有所帮助。谢谢。

【讨论】:

它给出了一个想法,我会试试的。谢谢 这不起作用,因为 Selenium 缓存了选择器的结果。使用相同的选择器将给出相同的结果,因此返回初始的陈旧对象。 基本硒永远不会捕获。如果我们使用页面工厂,那么可能是。 @tocqueville 有没有办法处理选择器结果的缓存? Selenium 返回元素在 html 中已经改变(我插入 time.sleep(10) 足以完成元素更改)。而且我没有将此元素分配给某个变量,而是在 python 中使用driver.find_element_by_xpath()【参考方案2】:

我最初遇到了这个问题,但我通过一些技巧解决了它

等待某些父元素在页面中可见(可能是父容器 div) 等待任何 ajax (xhr) 请求围绕您尝试使用的元素完成 (这是诀窍)不要将任何元素存储为实例属性值,始终根据请求获取(这将帮助您摆脱陈旧的元素)。在 c# 6 中尝试表达式,示例 私有 IWebElement _parentContainer => _driver.FindElement(...)

另外,您可以为 IWebElement 创建抽象的基本控件和一些扩展方法,并在查找元素时进行一些基本的检查操作

【讨论】:

【参考方案3】:

这种类型的错误通常是由更新的 DOM 引起的。我建议您在所有包含 javascript/ajax 调用的页面上实际等待这些调用完成,然后再与站点交互。我通常在页面加载后立即执行此等待,并且在执行某种触发 javascript/ajax 调用和/或更新 DOM 的操作时。实际上,这意味着在页面加载(或与之交互)之后运行以下函数,然后找到您要与之交互的元素。

public void WaitForJqueryAjax() 
        int delay = MaxdelaySeconds;
        while(delay > 0) 
            Thread.Sleep(1000);
            var jquery = (bool)(this.driver as IJavaScriptExecutor)
                .ExecuteScript("return window.jQuery == undefined");
            if(jquery) 
                break;
            
            var ajaxIsComplete = (bool)(this.driver as IJavaScriptExecutor)
                .ExecuteScript("return window.jQuery.active == 0");
            if(ajaxIsComplete) 
                break;
            
            delay--;
        
    

【讨论】:

我也使用这个技巧。不过,如果 Ajax 调用不通过 jQuery,不知道该怎么做。【参考方案4】:

我遇到过类似的情况。这里的主要问题是页面需要时间,所以我添加了 time.sleep(sec) 并且效果很好。

【讨论】:

一般来说,以这种方式依赖sleep() 最多只能为核心问题提供一种低效的解决方法。最好的情况是,它可能会等待太久,从而不必要地降低性能。最坏的情况是,它触发得太快,导致同样的问题。理想情况下,我们会绑定到一个特定的事件,以便在可用时触发它。您是否了解这里可能适合哪些事件,而不是简单地使用sleep() 来延迟处理?

以上是关于Selenium - 过时的元素参考:元素未附加到页面的主要内容,如果未能解决你的问题,请参考以下文章

Python,Selenium:'元素不再附加到 DOM'

Selenium 如何解决滚动条问题,未显示元素不可操作问题

动态创建的 p 元素未附加到动态创建的 div

使用robot framework + selenium2 出现异常解决方法

Selenium报错:StaleElementReferenceException异常

selenium浏览器元素定位