线程“主”中的异常 org.openqa.selenium.NoSuchElementException:没有这样的元素:无法找到元素:

问题描述 投票:0回答:1

我的任务

网址:https://www.homedepot.com/

步骤:

  1. 首先将鼠标悬停在所有部门
  2. 加热和冷却是第二次鼠标悬停
  3. 空调是第三次鼠标悬停
  4. 点击便携式空调

我可以执行第 1 步和第 2 步,但找不到第 3 步和第 4 步的 WebElements。

我的代码

ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*");
options.addArguments("--disable-notifications");
WebDriver driver = new ChromeDriver(options);
driver.get("https://www.homedepot.com/");
WebElement First = driver.findElement(By.xpath("(//a[@data-id='departmentsFlyout'])[1]"));
WebElement Second = driver.findElement(By.xpath("(//a[@data-level='Heating & Cooling'])[1]"));
// cannot able to find the below Third and Fourth WebElements//
WebElement Third = driver.findElement(By.xpath("//a[@title='Air Conditioners']"));
WebElement Fourth = driver.findElement(By.xpath("//a[@href='//www.homedepot.com/b/Heating-Venting-Cooling-Air-Conditioners-Coolers-Air-Conditioners-Portable-Air-Conditioners/N-5yc1vZc4m4']"));

Actions act = new Actions(driver);
act.moveToElement(First).build().perform();
act.moveToElement(Second).build().perform();
act.moveToElement(Third).build().perform();
act.moveToElement(Fourth).click().build().perform();
selenium-webdriver css-selectors selenium-chromedriver selenium-grid
1个回答
0
投票

主要问题是元素 3 和 4 在您打开创建它们的导航面板之前不存在。这就是为什么你一开始就找不到 3 和 4 的原因。

另一个问题是最后的点击被另一个元素拦截,直到导航菜单完全打开。这需要一些特殊处理过去只是等待可点击。

改进建议:

  1. 你的定位器过于复杂了。

    (//a[@data-id='departmentsFlyout'])[1]
    可以很容易地成为
    //a[@data-id='departmentsFlyout']
    并且仍然有效。或者更好的是,让它成为一个 CSS 选择器
    a[data-id='departmentsFlyout']
    。 CSS 选择器语法更短且更易于阅读,执行速度更快,并且得到了广泛浏览器的更好支持。 XPath 有它的位置,但根据我的经验,我的定位器优先顺序是 1. ID,2. CSS 选择器,然后是 3. XPath,如果需要的话。

  2. 你不需要

    .build()
    动作,你可以
    .perform()
    它们,例如

    act.moveToElement(First).perform();
    
  3. 您的定位器不一致。它们仍然有效,但注意并使用一致性可以使您的工作变得容易得多。最后三个定位器都可以有形式,

    //a[@title='<Category>']
    或 CSS 选择器
    a[title='<Category>']
    .

  4. 最后的点击不需要是Action,做成常规点击即可。根据我的经验,Actions 的行为并不一致,所以除非绝对必要,否则我会避免使用它们。

我添加了一个

click()
支持方法,它负责等待可点击并处理
ElementClickInterceptedException
StaleElementReferenceException

为了确保每个步骤都有效,我们将

.findElement()
链接起来,然后为每个元素链接
.moveToElement()
,例如

WebElement First = wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("a[data-id='departmentsFlyout']")));
act.moveToElement(First).perform();

你会注意到第一个、第二个和第三个元素的处理方式完全相同,除了定位器。它们是重构为处理等待可见然后悬停动作的方法的主要候选对象。

最终的工作代码看起来像

import java.time.Duration;
import java.time.LocalDateTime;
import org.openqa.selenium.By;
import org.openqa.selenium.ElementClickInterceptedException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class Ques11 {
    static WebDriver driver;

    public static void main(String[] args) {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--remote-allow-origins=*");
        options.addArguments("--disable-notifications");
        driver = new ChromeDriver(options);
        driver.manage().window().maximize();
        driver.get("https://www.homedepot.com/");

        hover(By.cssSelector("a[data-id='departmentsFlyout']"), 10);
        hover(By.cssSelector("a[title='Heating & Cooling']"), 10);
        hover(By.cssSelector("a[title='Air Conditioners']"), 10);
        click(By.cssSelector("a[title='Portable Air Conditioners']"), 10);
    }

    public static void click(By locator, int timeOutInSeconds) {
        LocalDateTime now = LocalDateTime.now();
        while (LocalDateTime.now().isBefore(now.plusSeconds(timeOutInSeconds))) {
            try {
                new WebDriverWait(driver, Duration.ofSeconds(timeOutInSeconds)).until(ExpectedConditions.elementToBeClickable(locator)).click();

                return;
            } catch (ElementClickInterceptedException | StaleElementReferenceException e) {
                // do nothing, loop again
            }
        }
    }

    public static void hover(By locator, int timeOutInSeconds) {
        WebElement e = new WebDriverWait(driver, Duration.ofSeconds(timeOutInSeconds)).until(ExpectedConditions.visibilityOfElementLocated(locator));
        new Actions(driver).moveToElement(e).perform();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.