为了账号安全,请及时绑定邮箱和手机立即绑定

Selenium:陈旧元素参考(调试时工作正常)

Selenium:陈旧元素参考(调试时工作正常)

C#
森林海 2021-04-30 15:08:49
我正在尝试使用C#中的Selenium刮取一个页面,通过单击页面上的“下一步”按钮可以浏览多个页面。我通常会得到一个错误的消息,即有一个过时的元素引用,只有当我在没有断点的情况下运行它时,该引用才会发生。如果我逐步执行该程序,则效果很好。我假设Selenium无需等待就跳过了重要的内容(即使我实现了wait方法)。对于代码,这是问题的主要逻辑:foundVacancies.AddRange(FindVacanciesOnPage());const string nextBtnXPath = "//*[@id=\"ContainerResultList\"]/div/div[3]/nav/ul/li[8]/a";if (Driver.FindElements(By.XPath(nextBtnXPath)).Count != 0){    while (TryClickingNextButton(nextBtnXPath))    {        foundVacancies.AddRange(FindVacanciesOnPage());    }}此方法首先获取首页上的所有项目,并将它们添加到foundVacancies列表中。之后,它将尝试寻找“下一步”按钮,如果没有足够的项目,该按钮将不会一直存在。如果是这样,它将尝试单击它,刮取页面,然后再次单击它,直到没有剩余的页面。这在调试时效果很好,但是正常运行时有一些错误。获取页面上所有项目以及发生错误的位置的方法:private IEnumerable<string> FindVacanciesOnPage(){    var vacancies = new List<string>();    var tableContainingAllVacancies = Driver.FindElement(By.XPath("//*[@id=\"ContainerResultList\"]/div/div[2]/div/ul"));    var listOfVacancies = tableContainingAllVacancies.FindElements(By.XPath(".//li/article/div[1]/a"));    foreach (var vacancy in listOfVacancies)    {        vacancies.Add(vacancy.FindElement(By.XPath(".//h2")).Text);    }    return vacancies;}这些项目在<ul>HTML标记中,并且有一个<li>孩子,我将逐个检查这些孩子,并获取其内部文本。过时的元素错误发生在foreach循环中。我假设Web驱动程序没有时间重新加载DOM,因为它在断点时可以正常工作。但是,我确实有一种方法可以等待页面完全加载,这就是我进入下一页时所使用的方法。private bool TryClickingNextButton(string nextButtonXPath){    var nextButton = Driver.FindElement(By.XPath(nextButtonXPath));    var currentUrl = Driver.Url;    ScrollElementIntoView(nextButton);    nextButton.Click();    WaitUntilLoaded();    var newUrl = Driver.Url;    return !currentUrl.Equals(newUrl);}我正在比较新旧URL,以确定这是否是最后一页。该WaitUntilLoaded方法如下所示:var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(30));wait.Until(x => ((IJavaScriptExecutor) Driver).ExecuteScript("return document.readyState").Equals("complete"));奇怪的是,有时Web驱动程序仅在加载第一页后立即关闭,而没有任何错误或任何结果。我花了很多时间在SO上进行调试和搜索,但似乎找不到任何信息,因为在进行断点处理时,代码工作得很好。我仅在有无无头模式的情况下尝试使用Chrome,但我认为这可能不是Chrome的问题。我不知道data-jn-click是什么。我试图只执行JavaScript nextPage();,但是什么也没做。
查看完整描述

3 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

我没有使用C#的经验,所以如果有错,请不要介意。您正在使用findElements并将其存储到var listOfVacancies。我已经介绍了一些网站。你为什么不使用ReadOnlyCollection<IWebElement>。最好将所有元素存储为List并对其进行遍历。所以代码变成了

ReadOnlyCollection<IWebElement> listOfVacancies = tableContainingAllVacancies.FindElements(By.XPath(".//li/article/div[1]/a"));


查看完整回答
反对 回复 2021-05-08
  • 3 回答
  • 0 关注
  • 171 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信