You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Selenide翻页采集商品名时出现StaleElementReferenceException报错如何解决

错误原因

StaleElementReferenceException 触发的核心原因是操作的DOM元素已经被页面销毁,缓存的旧引用失效,你的代码具体存在三个问题:

  • 点击下一页按钮后没有等待页面跳转、新内容渲染完成,就立即执行元素采集逻辑,此时读取到的还是上一页已经失效的元素引用。
  • 采集商品名称时没有先校验元素是否已完成加载、挂载到DOM树,直接遍历调用getText(),遍历过程中如果页面DOM发生变更就会报错。
  • 下一页按钮点击逻辑没有做可用性校验,也没有等待跳转完成的判断,页面还在加载中就进入下一轮采集逻辑。
修复代码

你可以按照如下逻辑修改代码即可解决报错:

import com.codeborne.selenide.CollectionCondition;
import com.codeborne.selenide.ElementsCollection;
import com.codeborne.selenide.Selenide;
import com.codeborne.selenide.WebDriverRunner;
import org.junit.jupiter.api.Assertions;
import org.openqa.selenium.By;
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;

public class AfterPhonesCategory {

    // 商品标题选择器统一管理,避免重复编写
    private static final By GOODS_TITLE_SELECTOR = By.xpath("//article//h3[@data-zone-name = 'title']//span");

    public List<String> collectResultsFromPage() {
        // 滚动到底部触发懒加载,确保本页所有商品都加载完成
        Selenide.executeJavaScript("window.scrollTo(0, document.body.scrollHeight)");
        // 最长等待10秒,直到商品标题元素全部加载完成、可正常显示
        ElementsCollection resultsNameWebElement = Selenide.$$(GOODS_TITLE_SELECTOR)
                .shouldBe(CollectionCondition.sizeGreaterThan(0), Duration.ofSeconds(10))
                .shouldBe(CollectionCondition.allMatch("所有元素都可见", elem -> elem.isDisplayed()));

        Assertions.assertTrue(resultsNameWebElement.stream().anyMatch(x->x.getText().contains("Apple")),
                "the snippet does not contain the name of the apple");

        // 立即提取所有文本,避免后续元素引用失效
        return resultsNameWebElement.stream()
                .map(elem -> elem.exists() && elem.isDisplayed() ? elem.getText() : "")
                .filter(text -> !text.isBlank())
                .collect(Collectors.toList());
    }

    private boolean initNextPageButton() {
        ElementsCollection goNextPageButton = Selenide.$$x("//a[contains(@class, '_3OFYT')]");
        // 先判断下一页按钮存在且可点击
        if(goNextPageButton.size() > 0 
                && goNextPageButton.get(0).isEnabled() 
                && goNextPageButton.get(0).isDisplayed()){
            // 记录点击前的URL,用来判断是否跳转完成
            String beforePageUrl = WebDriverRunner.getWebDriver().getCurrentUrl();
            goNextPageButton.get(0).click();
            // 等待页面跳转完成
            Selenide.Wait().until(driver -> !driver.getCurrentUrl().equals(beforePageUrl));
            // 等待新页面的商品元素加载完成
            Selenide.$$(GOODS_TITLE_SELECTOR).shouldBe(CollectionCondition.sizeGreaterThan(0), Duration.ofSeconds(10));
            return true;
        }
        return false;
    }


    private List<String> findResults;

    public AfterPhonesCategory collectResults() {
        findResults = collectResultsFromPage();
        while (initNextPageButton()) {
            findResults.addAll(collectResultsFromPage());
        }
        return this;
    }
}

内容的提问来源于stack exchange,提问作者Otto Rahn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 04:57:04