如何在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
相关产品推荐
相关产品推荐

