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。 并创建两个线程运行这个?
我处于类似的情况。 我的清单并不是那么大,所以我提出的一些想法不适用于我的情况,因此我没有对它们进行测试。
多次扫描表格。
假设表定期更新,那么如果第一个表扫描在StaleElementReferenceException
上StaleElementReferenceException
,则第二个表扫描会在下一个静默期开始时启动,并且在下次更新发生之前很有可能成功。 前提是您可以比更新周期更快地完成扫描。
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不是解决方案。