Selenium(Java) 无法识别只有 div 元素的 table 中的某些元素

Selenium(Java) not identifying some elements in a table that has only div elements

我正在尝试从只有 div 元素的网页中的 table 获取值。没有tr td。下面是一个示例(不是真实的)HTML 的样子。

<div class="table" style="style="transform: translate3d(0px, 0px, 0px); opacity: 1;">
<div class="row heading">
<div class="row" style="opacity: 1;">
 <div class="cell">
  <div class="row1">value1</div>
  <span class="Tooltip" style="style="position: relative;">...</span>
 </div>
 <div class="cell1">
  <div class="classname"></div>
  <div class="row1">value2</div>
 </div>
 <div class="cell1">
  <div class="classname"></div>
  <div class="row1">value3</div>
 </div>
 <div class="cell1">
  <div class="classname"></div>
  <div class="row1">value4</div>
 </div>
 <div class="cell1">
  <div class="classname"></div>
  <div class="row1">value5</div>
 </div>

table 有 50 行,每行 5 列。我尝试了 2 种方法来从 table.

中获取所有值
  1. 使用 CSSSelector

     for(int i=2;i<=38;i++) {
             WebDriverWait wait = new WebDriverWait(driver, 60);
             wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#root > div > div.Home > div.home-left > div.table > div:nth-child("+i+") > div:nth-child(1) > div")));            
             String valueone = driver.findElement(By.cssSelector("#root > div > div.Home > div.home-left > div.table > div:nth-child("+i+") > div:nth-child(1) > div")).getText();
             clist.add(valueone);
             for(int j=2;j<=5;j++) {
                 val = driver.findElement(By.cssSelector("#root > div > div.Home > div.home-left > div.table > div:nth-child("+i+") > div:nth-child("+j+") > div.total")).getText();
                 clist.add(val);
             }   
         }
    
  2. 使用 Xpath:

     for(int i=2;i<=38;i++) {
     String c;
         WebDriverWait wait = new WebDriverWait(driver, 30);
         wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"root\"]/div/div[3]/div[1]/div[5]/div["+i+"]/div[1]/div")));
         valueone = driver.findElement(By.xpath("//*[@id=\"root\"]/div/div[3]/div[1]/div[5]/div["+i+"]/div[1]/div")).getText();
             clist.add(valueone);
     }
     for(int j=2;j<=38;j++) {
         c = driver.findElement(By.xpath("//*[@id=\"root\"]/div/div[3]/div[1]/div[5]/div["+j+"]/div[2]/div[2]")).getText();
         clist.add(c);
     }   
     for(int k=2;k<=38;k++) {
         c = driver.findElement(By.xpath("//*[@id=\"root\"]/div/div[3]/div[1]/div[5]/div["+k+"]/div[3]/div")).getText();
         clist.add(c);
     }
     for(int l=2;l<=38;l++) {
         c = driver.findElement(By.xpath("//*[@id=\"root\"]/div/div[3]/div[1]/div[5]/div["+l+"]/div[4]/div[2]")).getText();
         clist.add(c);
     }
    

问题:当我尝试使用 css 选择器进行迭代时,出现此异常(找不到第 12 行)-

    Exception in thread "main" org.openqa.selenium.TimeoutException: Expected condition failed: waiting for visibility of element located by By.cssSelector: #root > div > div.Home > div.home-left > div.table > div:nth-child(12) > div:nth-child(1) > div (tried for 30 second(s) with 500 milliseconds interval)
at org.openqa.selenium.support.ui.WebDriverWait.timeoutException(WebDriverWait.java:95)
at org.openqa.selenium.support.ui.FluentWait.until(FluentWait.java:272)
at App.GetData.main(GetData.java:46)
    Caused by: org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#root > div > div.Home > div.home-left > div.table > div:nth-child(12) > div:nth-child(1) > div"}

当我尝试使用 X 路径进行迭代时,出现此异常(找不到第 13 行)-

    Exception in thread "main" org.openqa.selenium.TimeoutException: Expected condition failed: waiting for visibility of element located by By.xpath: //*[@id="root"]/div/div[3]/div[1]/div[5]/div[13]/div[1]/div (tried for 30 second(s) with 500 milliseconds interval)
at org.openqa.selenium.support.ui.WebDriverWait.timeoutException(WebDriverWait.java:95)
at org.openqa.selenium.support.ui.FluentWait.until(FluentWait.java:272)
at App.GetData.main(GetData.java:72)
    Caused by: org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//*[@id="root"]/div/div[3]/div[1]/div[5]/div[13]/div[1]/div"}

我尝试了 ImplicitWaitExplicitWait 甚至 Thread.sleep(我知道不推荐这样做)。似乎没有任何效果。 讽刺的是,如果我尝试 20 次,Selenium 会在 1 次尝试中毫无问题地识别所有元素。

  1. 为什么 css 选择器很难找到一个元素,而 xpath 找到该元素却很难找到另一个元素?

  2. 我在 Selenium 中经常遇到这个问题,当它能够在一个 运行 上毫无问题地找到相同的元素而在其他 运行 上很难找到它时?这个问题有永久性的solution/approach吗?

要获取所有值而不是使用 visibilityOfElementLocated(),您需要引入 for the visibilityOfAllElementsLocatedBy() and you can use the following based :

  • 代码块:

    List<WebElement> values = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//div[@class='table']//div[@class='cell' or @class='cell1']/div[@class='row1']")));
    for(WebElement value:values) { System.out.println(value.getText()); }
    

替代使用 Java 8 stream()map()

作为替代方案,您可以使用 Java8 stream() and map(),如下所示:

  • 代码块:

    System.out.println(new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//div[@class='table']//div[@class='cell' or @class='cell1']/div[@class='row1']"))).stream().map(element->element.getAttribute("innerHTML")).collect(Collectors.toList()));
    

终于找到问题的原因了!我在玩 HTML 并发现,在初始加载时,只有最初的 12 行被加载(即使显示所有行)并且只有在进一步滚动时,其余行才会被加载。在遍历行之前执行以下操作,现在所有行现在都由 cssSelectorXpath.

标识
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight)");