我有一个代码可以遍历网站表。表是动态的,项目在用户滚动时加载到其中。
我有参数:
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;
}
}
}
这是将数据添加到List中的方法本身。
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。硒。陈旧元素引用异常:"陈旧元素引用:元素未附加到页面文档(会话信息:chrome=84.0.4147.105('
指向row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l0 r0')]")).Text;
有什么想法可以将try-catch添加到Parameters中,这样代码就可以继续执行,直到添加到列表中为止?
我打电话给的原因
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>
您正在刷新foreach内部的行,但行是foreach的可迭代对象。我想这并不违法(毕竟是汇编的(,但似乎是在找麻烦。我的观点是,过时的元素引用在某种程度上与在它自己的foreach循环中重新分配的行有关。
但是,在第二次指定行之后,就再也不会在foreach中使用它了。这似乎是一个无意的声明,你可以删除。毕竟,为什么要麻烦在foreach内部分配行,然后永远不要在foreach中使用?
如果你第二次分配行是因为你正在与已经处理的行进行比较,我会给第二次的行分配一个不同的变量名(比如rows_B(。但正如我所说,我不认为这会在这里发生。你只需在foreach内部分配行,而从不使用它。
或者,如果第二行分配的原因是因为在处理表时表正在动态更改?如果是这样的话,我认为你能做的最好的事情就是抓住错误,试着从中途发生的任何变化中恢复过来。我知道这听起来很模糊,但实际上,如果你的输入数据在你试图处理输入时发生了变化,你所希望的最好的结果就是尽最大努力。
例如,您可以创建第二行变量(比如rows_b(以在foreach循环中刷新。然后将rows_b与原始行进行比较。如果它们完全一样——太棒了,就继续处理吧。
如果它们不同,我会记录到目前为止您处理过的行,跳出循环,重新开始。在foreach过程中,您将检查一行之前是否已经处理过,如果是,请跳到下一个迭代。
如果这是您想要做的事情,并且希望看到一个代码示例,请告诉我。如果代码不是你想要完成的,我不想写;-(