2012-09-02 63 views
0

我遇到导航问题。我从html表中获取行的列表。我遍历行并从中获取信息。但是,我也点击了一行链接以获取更多与该行相关的信息。然后我回到带有原始表的页面。这适用于第一行,但对于后续行,它会引发异常。Foreach循环内部的Selenium导航

第一次单击行内的链接后,我查看了我的行集合,并且他们没有像我们单击链接之前那样的正确值。我相信当我导航到一个我没有收到的网址时会发生一些事情。

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

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; 
    } 

UPDATE:(针对吉姆·埃文斯的回答)

这看起来像它的正常工作。

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; 
     } 
    } 

回答

2

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

+0

对不起,花了我很长的时间才回到你身边。我明白你在说什么,并相应地更改我的代码。我会在一秒内发布更新后的代码。我希望他们能够添加另一个抽象层次,即使它们不在当前的DOM中,Web元素也可以保留。所以这会更容易做我尝试在我的原始代码中... – lintmouse