Selenium - 陈旧元素引用:元素未附加到页面

时间:2017-07-09 23:31:36

标签: c# html selenium selenium-webdriver selenium-chromedriver

我试图理解为什么在我尝试显示从网站上获取的项目时出现错误。 我也在使用谷歌浏览器浏览器。

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“))时,点击();”,就会出错。我无法显示我提取的数据。

在错误消息中,它显示“ OpenQA.Selenium.StaleElementReferenceException:'陈旧元素引用:元素未附加到页面文档”。我检查了其他帖子,但我没弄清楚。我该如何解决?

正如我所读到的,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();
}

如何转换为文字

4 个答案:

答案 0 :(得分:6)

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

一般来说,如果在启动webelement之后更改了元素属性或某些内容,我们将获得Stale Exception。例如,在某些情况下,如果用户尝试在同一页面上单击同一元素但在页面刷新后,则会获取staleelement异常。

为了解决这个问题,我们可以创建新的webelement,以防页面被更改或刷新。下面的代码可以给你一些想法。(它在java中,但概念将是相同的)

示例:

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

为了解决这个问题,我们可以将xpath存储在某个字符串中,然后使用它创建一个新的webelement。

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

在这种情况下,我们正在收集一组webelements并迭代以获取文本。但是在收集了webelements和gettext抛出陈旧之后,似乎有一些变化。我们可以使用循环并在旅途中创建元素并获取文本。

for(int i = 0; i<5; i++)
{
   String value = driver.findElement(by.xpath("//.....["+i+"]")).getText);
   System.out.println(value);
}

希望这会对你有所帮助。感谢。

答案 1 :(得分:2)

此类错误通常是由更新的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--;
        }
    }

答案 2 :(得分:1)

我也遇到过类似的情况。这里的主要问题是页面需要时间,所以我添加了time.sleep(sec)并可以正常工作。

答案 3 :(得分:0)

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

  • 等待某个父元素在页面中可见(可能是父容器div)
  • 等待任何ajax(xhr)请求在您尝试使用的元素周围完成
  • (这是诀窍)不要将任何元素存储为实例属性值,总是按请求获取(这将帮助您从staleelement)。尝试在c#6中表达,例如 private IWebElement _parentContainer =&gt; _driver.FindElement(...)

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