使用Selenium Java自动化亚马逊时解决两类元素定位异常
解决Selenium操作亚马逊时的StaleElementReferenceException和NoSuchElementException问题
问题根源
- StaleElementReferenceException:你在第一页就获取了商品元素列表
requiredItem,但点击分页进入新页面后,原页面的DOM已被销毁,之前保存的元素引用全部失效,再调用旧引用的方法必然报错。 - NoSuchElementException:循环逻辑错误,翻页后未重新获取当前页的商品列表,仍在遍历旧列表;同时XPath定位不稳定,加上等待逻辑混乱,导致元素未加载完成就尝试定位。
解决方案
- 每进入一页就重新获取当前页的商品元素,不提前缓存跨页面的元素引用
- 使用
while循环持续查找,直到找到目标商品或确认无更多页面 - 仅使用显式等待,避免隐式等待与显式等待混用(两者混用会导致等待时间不可控)
- 优化定位器,使用更稳定的属性定位分页按钮和商品元素
修改后的代码
package Daszio.AmazonPurchase; import java.time.Duration; import java.util.List; import org.openqa.selenium.WebDriver; import org.openqa.selenium.By; import org.openqa.selenium.Keys; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.annotations.Test; public class Practice { @Test public void addCart() { WebDriver driver = new ChromeDriver(); WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); driver.manage().window().maximize(); driver.get("https://www.amazon.in/"); // 搜索商品 wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("twotabsearchtextbox"))) .sendKeys("shoes for men", Keys.ENTER); boolean itemFound = false; String targetItemText = "Mens Solid Lace Up Genuine Leather Formal Brogue Shoes (201826FW)"; while (!itemFound) { // 等待当前页商品加载完成,重新获取当前页的商品列表 wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@data-cy='title-recipe']/h2/a/span"))); List<WebElement> currentPageItems = driver.findElements(By.xpath("//div[@data-cy='title-recipe']/h2/a/span")); // 遍历当前页的商品 for (WebElement item : currentPageItems) { if (item.getText().contains(targetItemText)) { item.click(); itemFound = true; break; } } // 如果没找到,尝试点击下一页 if (!itemFound) { try { // 定位下一页按钮,使用更稳定的定位器 WebElement nextPageBtn = wait.until(ExpectedConditions.elementToBeClickable( By.xpath("//a[contains(@aria-label,'Next page')]") )); nextPageBtn.click(); // 等待页面切换完成,旧页面元素失效 wait.until(ExpectedConditions.stalenessOf(currentPageItems.get(0))); } catch (Exception e) { // 没有下一页了,退出循环 System.out.println("已到最后一页,未找到目标商品"); break; } } } // 最后关闭驱动(可选,根据你的测试需求) // driver.quit(); } }
关键优化点
- 每次进入新页面后重新获取当前页的商品列表,避免引用失效
- 使用
while循环持续查找,直到找到目标或无更多页面 - 统一使用显式等待,确保元素加载完成后再操作
- 优化分页按钮的定位器,使用
aria-label属性更稳定 - 添加异常捕获处理无下一页的情况
内容的提问来源于stack exchange,提问作者Sandeep Sudevan
相关产品推荐
相关产品推荐

