foreach循环内的Selenium导航

时间:2012-09-02 15:01:47

标签: .net selenium foreach webdriver

我遇到导航问题。我从html表中获取了一个行列表。我遍历行并从中抓取信息。但是我在该行上还有一个链接,用于获取与要刮取的行相关的更多信息。然后我导航回原始表格的页面。这适用于第一行,但对于后续行,它会引发异常。

我在第一次点击一行内的链接后查看我的行集合,并且没有一个像我们点击链接之前那样具有正确的值。我相信当我导航到另一个我没有得到的URL时会发生一些事情。

我的代码如下。我如何使这个工作,所以我可以迭代父表,单击每行中的链接,导航到子表,但仍然继续迭代父表中的行?

    private List<Document> getResults()
    {
        var documents = new List<Document>();

        //Results
        IWebElement docsTable = this.webDriver.FindElements(By.TagName("table"))
            .Where(table => table.Text.Contains("Document List"))
            .FirstOrDefault();

        var validDocRowRegex = new Regex(@"^(\d{3}\s+)");

        var docRows = docsTable.FindElements(By.TagName("tr"))
            .Where(row =>
                //It throws an exception with .FindElement() when there isn't one.
                row.FindElements(By.TagName("td")).FirstOrDefault() != null &&
                    //Yeah, I don't get this one either. I negate the match and so it works??
                !validDocRowRegex.IsMatch(
                    row.FindElement(By.TagName("td")).Text))
            .ToList();

        foreach (var docRow in docRows)
        {
            //Todo: find out why this is crashing on some documents.
            var cells = docRow.FindElements(By.TagName("td"));

            var document = new Document
            {
                DocID = Convert.ToInt32(cells.First().Text),
                PNum = Convert.ToInt32(cells[1].Text),
                AuthNum = Convert.ToInt32(cells[2].Text)
            };

            //Go to history for the current document.
            cells.Where(cell =>
                cell.FindElements(By.TagName("a")).FirstOrDefault() != null)
                .FirstOrDefault().Click();

            //Todo: scrape child table.

            this.webDriver.Navigate().Back();
        }

        return documents;
    }

更新:(回应Jim Evans的回答)

这看起来工作正常。

private List<Document> getResults()
    {
        var documents = new List<Document>();
        IWebElement docRow = null;
        int rowIndex = 0;

        while((docRow = this.getDocumentRow(rowIndex)) != null)
        {
            var cells = docRow.FindElements(By.TagName("td"));

            var document = new Document
        {
            DocID = Convert.ToInt32(cells.First().Text),
            PNum = Convert.ToInt32(cells[1].Text),
            AuthNum = Convert.ToInt32(cells[2].Text)
        };

            //Go to history for the current document.
            cells.Where(cell =>
                cell.FindElements(By.TagName("a")).FirstOrDefault() != null)
                .FirstOrDefault().Click();

            //Todo: scrape child table.

            this.webDriver.Navigate().Back();

            documents.Add(well);

            rowIndex++;
        }

        return documents;
    }

    private IWebElement getDocumentRow(int rowIndex)
    {
        try
        {
            IWebElement docsTable = this.webDriver.FindElements(By.TagName("table"))
                .Where(table => table.Text.Contains("Document List"))
                .FirstOrDefault();

            var validDocRowRegex = new Regex(@"^(\d{3}\s+)");

            var docRow = docsTable.FindElements(By.TagName("tr"))
                .Where(row =>
                    //It throws an exception with .FindElement() when there isn't one.
                    row.FindElements(By.TagName("td")).FirstOrDefault() != null &&
                        //Yeah, I don't get this one either. I negate the match and so it works??
                    !validDocRowRegex.IsMatch(
                        row.FindElement(By.TagName("td")).Text))
                .ElementAt(rowIndex);

            return docRow;
        }
        catch
        {
            return null;
        }
    }

1 个答案:

答案 0 :(得分:1)

您的问题是,一旦您导航到新页面(通过您的案例中的.Click()),您的缓存元素将不再有效。 DOM会在每次页面加载时重建,包括在浏览器历史记录中导航时。因此,即使您正在加载已经导航到的页面,您也会获得一个新构造的DOM,因此对先前构造的DOM的所有引用都是无效的。解决方案是在导航回上一页后重新找到您要查找的元素。