猿问

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

我正在尝试使用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();,但是什么也没做。


森林海
浏览 176回答 3
3回答

杨魅力

我没有使用C#的经验,所以如果有错,请不要介意。您正在使用findElements并将其存储到var listOfVacancies。我已经介绍了一些网站。你为什么不使用ReadOnlyCollection<IWebElement>。最好将所有元素存储为List并对其进行遍历。所以代码变成了ReadOnlyCollection<IWebElement>&nbsp;listOfVacancies&nbsp;=&nbsp;tableContainingAllVacancies.FindElements(By.XPath(".//li/article/div[1]/a"));
随时随地看视频慕课网APP
我要回答