【问题标题】:Selenium(Java) not identifying some elements in a table that has only div elementsSelenium(Java)没有识别只有div元素的表中的某些元素
【发布时间】:2020-10-09 23:49:17
【问题描述】:

我正在尝试从网页中只有 divelements 的表格中获取值。没有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>

该表有 50 行,每行 5 列。我尝试了 2 种方法来获取表中的所有值。

  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 Path 进行迭代时,我得到了这个异常(找不到第 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 中经常遇到这个问题,当它能够在一次运行中毫无问题地找到相同的元素并且在其他运行中难以找到它时?是否有针对此问题的永久解决方案/方法?

【问题讨论】:

    标签: selenium selenium-webdriver xpath css-selectors nosuchelementexception


    【解决方案1】:

    要获取所有值而不是使用visibilityOfElementLocated(),您需要为visibilityOfAllElementsLocatedBy() 诱导WebDriverWait,您可以使用以下基于Locator Strategy

    • 代码块:

      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()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()));
      

    【讨论】:

    • 您好,感谢您的回答。我使用 css 和 xpath 尝试了您建议的两种方法。仍然没有运气。同样的错误。
    • 线程“主”org.openqa.selenium.TimeoutException 中的异常:预期条件失败:等待 By.cssSelector 定位的所有元素的可见性:#root > div > div.Home > div.home -left > div.table > div:nth-child(12) > div:nth-child(1) > div(尝试 30 秒,间隔 500 毫秒)
    • 线程“main”中的异常 org.openqa.selenium.TimeoutException:预期条件失败:等待 By.xpath 定位的所有元素的可见性://*[@id="root"]/ div/div[3]/div[1]/div[5]/div[13]/div[1]/div(尝试 30 秒,间隔 500 毫秒)
    • @justcurious 那些 cssSelector 和 xpath 从来都不是我回答的一部分。你能复制粘贴我的代码并告诉我状态吗?
    • 您的 cssSelector 和 xpath 用于我提到的 HTML,我相信。正如我在问题中提到的那样,这不是真正的 HTML。我只是复制粘贴了您的代码并添加了真正的 xpath 和 cssSelector
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2021-01-21
      • 2020-09-05
      • 2017-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多