2012-09-02 101 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