我有一个遍历网站表的代码。表是动态的,并在用户滚动中将项加载到表中。
我有参数:
public class UserTableRow
{
private readonly IWebElement row;
public string Username => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l0 r0')]")).Text;
public string Firstname => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l1 r1')]")).Text;
public string Lastname => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l2 r2')]")).Text;
public string Type => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l3 r3')]")).Text;
public string Crew => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l4 r4')]")).Text;
public string JobTitle => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l5 r5')]")).Text;
public string DefaultPrice => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l6 r6')]")).Text;
public string Future => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l7 r7')]")).Text;
public string Language => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l8 r8')]")).Text;
public override string ToString()
{
return "SharePrice: " + Username.ToString() + ": " + Firstname.ToString();
}
public UserTableRow(IWebElement row)
{
try
{
this.row = row;
}
catch (Exception)
{
throw;
}
}
}下面是将数据添加到列表中的方法本身。
public static IEnumerable<UserTableRow> AddItemsToList(IWebDriver driver)
{
IReadOnlyCollection<IWebElement> rows = new List<IWebElement>();
List<UserTableRow> DataHere = new List<UserTableRow>();
driver.FindElement(By.XPath("//*[@id=\"disabled_users_show_label\"]")).Click();
Thread.Sleep(7000);
driver.FindElement(By.XPath("//*[@id=\"users_table\"]/div[5]/div/div[1]")).Click();
for (int i = 0; i < 11; i++)
{
rows = driver.FindElements(By.CssSelector("#users_table .slick-viewport .slick-row"));
// Now we will iterate through cells in table and compare to what we already have in the list
foreach (IWebElement cell in rows)
{
rows = driver.FindElements(By.CssSelector("#users_table .slick-viewport .slick-row"));
// Add data to our object
DataHere.Add(new UserTableRow(cell));
//We need to select table first to be able to scroll down. We do it directly here
Actions actions = new Actions(driver);
actions.SendKeys(Keys.ArrowDown).Build().Perform();
}
}
List<UserTableRow> noDupes = DataHere.Distinct().ToList();
return noDupes;
}它运行得很好,但是在某个时候(我不知道为什么)它捕捉到一个错误,上面写着:
OpenQA.Selenium.StaleElementReferenceException:‘
元素引用:元素未附加到页面文档(会话信息: chrome=84.0.4147.105)’
指向row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l0 r0')]")).Text;
有什么想法吗?如何在参数中添加try catch,这样代码就会继续执行,直到添加到列表完成为止?
我打电话的原因
rows = driver.FindElements(By.CssSelector("#users_table .slick-viewport .slick-row"));在循环中,我正在尝试更新表值,以便在向下滚动后迭代。这是一个棘手的表,它卸载项并从卷轴上的数据库加载其他项。因此,我试图模仿用户滚动与键盘和捕捉表项目的列表。
与航班上的物品进行比较将是非常完美的。然而,我正在考虑将所有的内容都列到列表中(甚至是重复的),然后再列出其他列表,其中我将删除重复的内容,比如:
List<UserTableRow> noDupes = DataHere.Distinct().ToList();HTML:
<div id="users_table" class="security_slick_container slickgrid_300610 ui-widget" style="overflow: hidden; outline: 0px; position: relative;">
<div tabindex="0" hidefocus="" style="position:fixed;width:0;height:0;top:0;left:0;outline:0;"></div>
<div class="slick-header ui-state-default" style="overflow:hidden;position:relative;">
<div class="slick-header-columns" style="left: -1000px; width: 2132px;" unselectable="on">
<div class="ui-state-default slick-header-column slick-header-sortable slick-header-column-sorted" id="slickgrid_300610userName" title="" style="width: 94px;"><span class="slick-column-name"><strong>Username:</strong></span><span class="slick-sort-indicator slick-sort-indicator-asc"></span>
<div class="slick-resizable-handle"></div>
</div>
<div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610firstName" title="" style="width: 89px;"><span class="slick-column-name"><strong>Firstname:</strong></span><span class="slick-sort-indicator"></span>
<div class="slick-resizable-handle"></div>
</div>
<div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610lastName" title="" style="width: 109px;"><span class="slick-column-name"><strong>Lastname:</strong></span><span class="slick-sort-indicator"></span>
<div class="slick-resizable-handle"></div>
</div>
<div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610type" title="" style="width: 124px;"><span class="slick-column-name"><strong>Type:</strong></span><span class="slick-sort-indicator"></span>
<div class="slick-resizable-handle"></div>
</div>
<div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610crew" title="" style="width: 109px;"><span class="slick-column-name"><strong>Crew:</strong></span><span class="slick-sort-indicator"></span>
<div class="slick-resizable-handle"></div>
</div>
<div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610jobTitle" title="" style="width: 109px;"><span class="slick-column-name"><strong>Job title:</strong></span><span class="slick-sort-indicator"></span>
<div class="slick-resizable-handle"></div>
</div>
<div class="ui-state-default slick-header-column slick-header-sortable" id="slickgrid_300610defaultPriceClass" title="" style="width: 124px;"><span class="slick-column-name"><strong>Defaultprice class:</strong></span><span class="slick-sort-indicator"></span>
<div class="slick-resizable-handle"></div>
</div>
<div class="ui-state-default slick-header-column" id="slickgrid_300610description" title="" style="width: 129px;"><span class="slick-column-name"><strong>Description:</strong></span>
<div class="slick-resizable-handle"></div>
</div>
<div class="ui-state-default slick-header-column" id="slickgrid_300610language" title="" style="width: 39px;"><span class="slick-column-name"><strong>Language:</strong></span>
<div class="slick-resizable-handle"></div>
</div>
</div>
</div>
<div class="slick-headerrow ui-state-default" style="overflow: hidden; position: relative; display: none;">
<div class="slick-headerrow-columns" style="width: 1115px;"></div>
<div style="display: block; height: 1px; position: absolute; top: 0px; left: 0px; width: 1132px;"></div>
</div>
<div class="slick-top-panel-scroller ui-state-default" style="overflow: hidden; position: relative; display: none;">
<div class="slick-top-panel" style="width:10000px"></div>
</div>
<div class="slick-viewport" style="width: 100%; overflow: auto; outline: 0px; position: relative; height: 567px;">
<div class="grid-canvas" style="height: 16550px; width: 1115px;">
<div class="ui-widget-content slick-row even" style="top:0px">
<div class="slick-cell l0 r0">john.smith</div>
<div class="slick-cell l1 r1">John</div>
<div class="slick-cell l2 r2">Smith</div>
<div class="slick-cell l3 r3">Contractor</div>
<div class="slick-cell l4 r4">Microsoft</div>
<div class="slick-cell l5 r5">Sales manager</div>
<div class="slick-cell l6 r6">A</div>
<div class="slick-cell l7 r7"></div>
<div class="slick-cell l8 r8">en</div>
</div>
<div class="ui-widget-content slick-row odd" style="top:25px">
<div class="slick-cell l0 r0">robert.geits</div>
<div class="slick-cell l1 r1">Robert</div>
<div class="slick-cell l2 r2">Geits</div>
<div class="slick-cell l3 r3">Staff</div>
<div class="slick-cell l4 r4">Google</div>
<div class="slick-cell l5 r5">Project manager</div>
<div class="slick-cell l6 r6">B</div>
<div class="slick-cell l7 r7"></div>
<div class="slick-cell l8 r8">de</div>
</div>
<div class="ui-widget-content slick-row even" style="top:50px">
<div class="slick-cell l0 r0">amir.rooney</div>
<div class="slick-cell l1 r1">Amir</div>
<div class="slick-cell l2 r2">Rooney</div>
<div class="slick-cell l3 r3">Staff</div>
<div class="slick-cell l4 r4">Microsoft</div>
<div class="slick-cell l5 r5">Sales manager</div>
<div class="slick-cell l6 r6">A</div>
<div class="slick-cell l7 r7"></div>
<div class="slick-cell l8 r8">en</div>
</div>
# ETC # ETC # ETC # ETC # ETC # ETC # ETC # ETC # ETC # ETC
</div>
</div>
<div tabindex="0" hidefocus="" style="position:fixed;width:0;height:0;top:0;left:0;outline:0;"></div>
</div>发布于 2020-08-04 18:23:57
您正在刷新foreach中的行,但是行是foreach的可迭代对象。我想这并不是违法的(毕竟,它编译了),但似乎是自找麻烦。我的观点是,陈旧的元素引用在某种程度上与在它自己的foreach循环中重新分配的行有关。
但是,在第二次分配行之后,您永远不会在foreach中使用它。这似乎是一个无意的声明,你可以删除。毕竟,为什么要费心在foreach内分配行,然后再不要在foreach中使用它呢?
如果您第二次分配行,因为您正在比较已经处理的行,我将给第二行赋值一个不同的变量名(例如,rows_B)。但就像我说的,我不认为它发生在这里。您只需在foreach内分配行,而不使用它。
或者,如果第二行分配的原因是因为表在处理表时动态变化的话?如果是这样的话,我认为你能做的最好的就是抓住错误,并试图从你的中流改变中恢复过来。我知道这听起来很模糊,但实际上,如果你的输入数据在你试图处理输入的过程中发生了变化,那么你所能期望的最好的输入是一种最大的努力。
例如,您可以在foreach循环中创建第二个行变量(例如,rows_b)来刷新。然后将rows_b与原始行进行比较。如果它们是一样的-太棒了,就继续处理。
如果它们不同,我将跟踪您处理过的行,从循环中分离出来,重新开始。在执行过程中,您将检查一行以前是否已经处理过,如果是这样,请跳到下一次迭代。
如果这就是你想要做的--并且想看到一个代码示例--请告诉我。如果代码不是你想要完成的,我也不想写它;-)
https://stackoverflow.com/questions/63250383
复制相似问题