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

如何在Selenium Python中返回并选择商品列表中的其他商品

解决Selenium返回列表页后无法选择商品的问题

问题根源

你提前缓存了商品元素的引用列表,当通过window.history.go(-1)返回列表页时,页面DOM会重新加载,之前保存的元素引用已经失效(触发StaleElementReferenceException),导致后续点击操作失败,循环无法继续执行。

另外你的代码存在一个XPATH逻辑错误://div[@class='description-wrapper']是全局路径,会匹配页面中所有符合条件的元素,而非当前商品卡片下的按钮,可能导致误选商品。

解决方案

核心思路:不要提前缓存元素对象,每次回到列表页后重新查询DOM获取元素,同时修正XPATH为相对路径。

1. 修改商品列表页封装类(CatPage.py)

添加获取符合条件商品数量、按索引重新查询商品的方法:

# CatPage.py
from selenium.webdriver.common.by import By

class CatPage:
    def __init__(self, driver):
        self.driver = driver    
    allProducts = (By.XPATH, "//div[@class='category-products'] // li[contains(@class,'item')]/div/div")
    # 改用相对路径,确保只查找当前商品卡片下的按钮
    notifyBtnLocator = (By.XPATH, ".//div[@class='description-wrapper']/div[@class='btn-border btn-border-product-list']")
    
    def getNotifyProductCount(self):
        """获取需要订阅的商品总数"""
        products = self.driver.find_elements(*CatPage.allProducts)
        valid_count = 0
        for product in products:
            try:
                product.find_element(*CatPage.notifyBtnLocator)
                valid_count +=1
            except:
                continue
        return valid_count
    
    def getNotifyProductByIndex(self, index):
        """按索引重新查询对应商品元素(每次调用都会刷新DOM)"""
        products = self.driver.find_elements(*CatPage.allProducts)
        current_index = 0
        for product in products:
            try:
                product.find_element(*CatPage.notifyBtnLocator)
                if current_index == index:
                    return product
                current_index +=1
            except:
                continue
        return None

2. 修改测试代码

每次循环回到列表页后,重新获取对应索引的商品元素,并用显式等待替代time.sleep提升稳定性:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def test_e2e(self, setup):
    # 滚动加载完整商品列表
    self.driver.execute_script("window.scrollTo(0,document.body.scrollHeight)")
    category = CatPage(self.driver)
    # 取前5个符合条件的商品(或所有商品,取最小值)
    max_operate_count = min(category.getNotifyProductCount(), 5)
    counter = 0
    
    while counter < max_operate_count:
        # 每次循环重新获取当前索引的商品元素
        target_product = category.getNotifyProductByIndex(counter)
        if target_product:
            target_product.click()
            
            # 执行邮箱订阅操作
            self.driver.find_element(By.XPATH, "//input[@id='email-notification']").send_keys("test@seart.pl")
            self.driver.find_element(By.XPATH, "//input[@value='Powiadom o dostępności']").click()
            
            # 返回列表页
            self.driver.execute_script("window.history.go(-1)")
            
            # 显式等待列表页加载完成(替代time.sleep,更可靠)
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located(CatPage.allProducts)
            )
        counter +=1

关键注意点

  • 相对路径XPATH:.//开头的路径会限定在当前元素的子节点中查找,避免全局匹配错误
  • 避免缓存元素:页面跳转后DOM重构,旧元素引用必然失效,必须每次重新查询
  • 显式等待:优先使用WebDriverWait等待元素加载,比固定时长的time.sleep更适配不同加载速度的页面

内容的提问来源于stack exchange,提问作者Wiktor Wiktorowicz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 11:01:13