【问题标题】:Clicking all elements found in List<WebElement>单击 List<WebElement> 中的所有元素
【发布时间】:2021-05-11 16:34:01
【问题描述】:

我正在尝试单击动态表行中锚标记内的 i 标记中的类属性找到的元素的所有实例。具体来说,它的一行有几个单元格,在最后一个单元格中,有一系列 4 个链接,其中一个和 X 或一个 O。如果正方形是 X,则可以单击它,稍等片刻后,它会变为 O。链接写如下:

<a class="foobar"><i class="dontNeedToClick"><i></a>
<a class="foobar"><i class="dontNeedToClick"><i></a>
<a class="foobar"><i class="needToClick"><i></a>
<a class="foobar"><i class="dontNeedToClick"><i></a>

当点击 needToClick 元素时,该类将变为 dontNeedToClick 元素 在包含数千个 O 的数据库中只有不到一百个 X 可以滚动,因此自动点击它们会节省大量时间。我可以成功计算元素出现在表中的实例,但是当我使用 .findElements() 将元素放入 List 对象并尝试遍历它时,我得到 ElementNotVisibleException。

到目前为止,这是我的示例代码:

// get the count of thumbs down accounts
    int elementsCount= driver.findElements(By.className("needToClick")).size();
    System.out.println("Amount of elements: " + elementsCount);

// loop and click through all elements found

    for (int x = 0; x < elementCount; x++) {
        List<WebElement> elements = driver.findElements(By.className("needToClick"));
        WebElement client = elements.get(x);
        client.click();
        Thread.sleep(5000);
    }

我尝试使用 Iterator 并得到相同的异常。

        Iterator<WebElement> clickElement = elements.iterator();
        while (clickElement.hasNext()) {
            clickElement.next().click();
        }

我也尝试过使用 foreach 循环。

    List<WebElement> thumbsDown = driver.findElements(By.className(expectedClass));

    for(WebElement element : thumbsDown) {
        element.click();
    }

我会使用 xpath,但我对动态表不是很有经验,并且无法找到一种方法来获取包含我正在寻找的元素的行以及与之相关的其他元素并计算出小于优雅的方法,例如仅通过类名查找所有元素就足够了。将不胜感激。

【问题讨论】:

  • 您是否错过了这一行List&lt;WebElement&gt; elements = driver.findElements(By.className("needToClick)); 的双引号?我添加了一条评论,因为我认为这不是您的问题的原因,因为您无法使用缺少的双引号进行编译。
  • 这是一个拼写错误,将代码概括为非特定于我的用途。感谢您指出,但是是的,代码符合并运行,直到向我抛出异常。
  • 您应该尝试运行调试器以查看异常发生的时间,(例如:循环第一次执行时或稍后的某个时间)。有可能是 click 事件修改了元素列表,所以 findElements 找不到它。
  • 这是 chrome/firefox 功能还是 Eclipse?感谢您的建议。
  • 我的意思是调试你的java代码,因为ElementNotVisibleException是由findElements函数抛出的。如果稍后在for循环中抛出,可能是第一次点击修改列表,所以在后面的迭代中找不到类needToClick

标签: java selenium selenium-webdriver


【解决方案1】:

确保您尝试点击的元素可见。如果您不关心可见性,请点击 javascipt:

JavascriptExecutor js = (JavascriptExecutor) driver;
WebDriverWait wait = new WebDriverWait(driver, 5);

List<WebElement> elements = driver.findElements(By.className("needToClick"));
elements.forEach(e -> {
    js.executeScript("arguments[0].click();", e);
    wait.until(ExpectedConditions.attributeToBe(e,"class", "dontNeedToClick"));
    //if element have not only dontNeedToClick class use attributeContains
    //wait.until(ExpectedConditions.attributeContains(e,"class", "dontNeedToClick"));
});

检查是否可以单击一个元素并更改类:

driver.findElement(By.className("needToClick")).click();

如果不试试 xpath:

driver.findElement(By.xpath("//a[i[@class='needToClick']]"));
//or
driver.findElement(By.xpath("//a[i[contains(@class,'needToClick')]]"));

【讨论】:

  • 这个解决方案正是我所需要的。 wait.until 引发了一个异常,但对于我的需求并不是必需的,因此我将其注释掉。 forEach 循环正确地点击了所有标记为needToClick 的链接。谢谢您的帮助!如果您能解释一下arguments[0] 的来源,那就太好了,因为我或多或少地理解了其余代码。
【解决方案2】:

是在遍历列表时抛出异常,还是在尝试生成列表时抛出异常?

如果是前者,您需要在每次点击后重新生成列表 - 即使您加载一个完全相同的新页面,selenium 也会将新页面上的元素视为“不同”,而您将无法使用您在旧页面上找到的任何元素。 (编辑:我再次查看了您的循环,看来您在做这部分是正确的。我猜您需要等待页面完全加载)

如果是后者,那么您可能需要等待页面加载,并确保您要查找的元素全部存在。在 selenium 中,您可以设置显式或隐式超时,但我个人更喜欢 time.sleep(however many seconds),因为 selenium 可能会在完全加载所有 javascript 之前“说”它已加载。

希望这会有所帮助!

【讨论】:

  • 当我注释掉client.click(); 代码时,循环“成功”迭代,也没有抛出异常,当我手动单击其中一个元素时,我的控制台中的元素计数会更新。真的被这个难住了。
【解决方案3】:

如果你想选择列表中的每个元素,只需使用 foreach 循环:

for(WebElement e : List<WebElement>){
   e.doThings();
}

【讨论】:

    【解决方案4】:

    我认为你必须使用 xpath,因为我在 &lt;i&gt; 标签中看到了你的元素

    喜欢这个

    //a[@class='foobar']//i[contains(@class,'Click')]
    

    代码

     List<WebElement> elements = driver.findElements(By.xpath("//a[@class='foobar']//i[contains(@class,'Click')]"));
     for (WebElement tempEle : elements) {
      tempEle.click();
    }
    

    您还可以在 For each 循环中使用 ifbreak 来查找特定元素

    【讨论】:

    • 使用 IDE 记录器,我可以使用以下 xpath 成功单击我想要的内容://tr[262]/td[12]/axpath=(.//*[normalize-space(text()) and normalize-space(.)='random date and time'])[1]/following::a[3]xpath=(.//*[normalize-space(text()) and normalize-space(.)='uniqueemail@domain.com'])[1]/following::a[3]//div[@id='accountsGrid']/div[2]/div/table/tbody/tr[262]/td[12]/atr 数字对应于我需要点击的链接之一。如果我能以某种方式从 List[WebElement] 中刮取行号,那真的会有所帮助,但我也无法弄清楚。
    • 很遗憾没有。我尝试了以下 xpath int elementsCount = driver.findElements(By.xpath(".//*a[@class='foobar']//i[contains(@class,'needToClick')]")).size();,但它无法计算我的初始代码能够计算的元素。
    • 好的,现在尝试每个
    【解决方案5】:
       int elementsCount= driver.findElements(By.className("needToClick")).size();
    System.out.println("Amount of elements: " + elementsCount);
    
        List<WebElement> elements = driver.findElements(By.className("needToClick"));
    
    for (int x = 0; x < elementCount; x++) {
        WebElement client = elements.get(x);
        Thread.sleep(5000);
    

    client.click(); }

    【讨论】:

      【解决方案6】:

      列表元素 = driver.findElements(By.className("needToClick")); 元素.get(0).click(); 它适用于网络列表元素上的点击事件

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-12-11
        • 2011-12-21
        • 2018-04-28
        • 2014-02-27
        • 2017-12-02
        • 2016-11-14
        • 2017-05-27
        • 1970-01-01
        相关资源
        最近更新 更多