Selenium – 陈旧元素引用:元素未附加到C#中的页面文档

我使用selenium将网站表格中的数据转化为分析。 我必须扫描并获得约1000行的表格。

我知道该页面有Javascript,它会自动更新DOM。 但表中的行数太多,所以当我扫描我的代码时总会抛出exception。

我尝试使用此代码:

Boolean breakIt = true; List result = new List(); while (true) { breakIt = true; try { IWebElement baseTable = browser.FindElementById("column2"); ReadOnlyCollection rowsTable = baseTable.FindElements(By.XPath("id('oTable')/table/tbody/tr")); foreach (IWebElement rows in rowsTable) { if (rows.FindElements(By.XPath("td")).Count == 10) result.Add(rows); } if (breakIt) { break; } } catch (StaleElementReferenceException ser) { if (ser.Message.Contains("element is not attached")) { browser.Refresh(); browser.WaitForPageToLoad(); browser.GoToFrame(browser.FindElementByXPath("//*[@id='form1']/div[3]/iframe")); breakIt = false; } } } 

它会抛出一个例外:

陈旧元素引用:元素未附加到页面文档。

有什么想法解决我的问题吗? 我认为使用多个Thread是最好的方法。

但我尝试使用多个Thread它也返回exception。

我想在获得rowsTable.Count 。 除此/ 2。 并创建两个线程运行这个?

我处于类似的情况。 我的清单并不是那么大,所以我提出的一些想法不适用于我的情况,因此我没有对它们进行测试。

多次扫描表格。

假设表定期更新,那么如果第一个表扫描在StaleElementReferenceExceptionStaleElementReferenceException ,则第二个表扫描会在下一个静默期开始时启动,并且在下次更新发生之前很有可能成功。 前提是您可以比更新周期更快地完成扫描。

waitForAngular()是来自https://stackoverflow.com/a/30540634/6081394或来自https://stackoverflow.com/a/38657507/6081394的方法,或者一个接一个地使用它们以确保;)

 var finished = false; for (var i = 0; i < 10; i++) { try { waitForAngular() // scan table here finished = true; break; } catch (StaleElementReferenceException e) { continue; } } if (!finished) { // test flaked out } 

我自己这样做。

在本地运行Selenium。

本地selen比Remote更快,因此使用以前的方法,在页面更新之前完成表扫描的可能性要高得多。 我知道,这不太现实,但仍然是一个选择。

多次扫描每个小范围的行。

如果表只是刷新但数据(和行数)相同,您可以先计算表中的行,然后一次检查10行,如果出现StaleElementReferenceException ,则重试。

您可以使用CSS查询行范围,请参阅https://stackoverflow.com/a/28061560/6081394

 tr:nth-child(n+2):nth-child(-n+4) 

注入JavaScript代码段并在那里进行检查。

JavaScript执行是事件驱动和单线程的。 这可以保证当您注入的JavaScript运行时,更新页面的脚本不会。 但是,可能会发生的情况是,当表处于更新过程中时脚本会被执行。 你必须检测到,拯救,再次运行脚本,希望下次会更好。 有关示例,请参阅https://stackoverflow.com/a/6285793/6081394 。

如果我面对一张大桌子和快速更新,这就是我追求的方式。

边注

AFAIK,selenium驱动程序最终在页面中执行JavaScript来完成工作,并且执行是单线程的,因为单个浏览器选项卡中的所有JavaScript执行都是单线程的。 因此,您编写的任何multithreadingC#测试都将以序列化顺序依次执行Selenium操作。 因此multithreading不是解决方案。