Python Selenium使用for循环遍历餐厅链接出现StaleElementReferenceException问题
错误原因
StaleElementReferenceException报错的核心原因是:你在进入列表页后提前抓取了所有餐厅条目元素存储在titles列表中,当你点击进入详情页再调用driver.back()返回列表页时,页面DOM已经重新渲染,之前存储在titles里的元素引用全部失效,第二次循环调用元素时就会触发该错误。
解决思路
不要提前一次性抓取所有餐厅元素,改为先统计餐厅总数量,通过索引循环,每次返回列表页后重新定位当前索引对应的餐厅元素即可。
修正后代码
import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Chrome(executable_path='../chromedriver.exe') driver.get("https://www.zomato.com/kolkata/dine-out?dishv2_id=76487754bd59c594cd5218d3427e68e0_2&rating_range=4.0-5.0") screen_height = driver.execute_script("return window.screen.height;") # 获取页面屏幕高度 i = 1 count = 0 scroll_pause_time = 1 while True: # 每次滚动一屏高度 driver.execute_script("window.scrollTo(0, {screen_height}*{i});".format(screen_height=screen_height, i=i)) i += 1 time.sleep(scroll_pause_time) # 每次滚动后更新滚动高度,因为页面滚动后高度可能变化 scroll_height = driver.execute_script("return document.body.scrollHeight;") # 当需要滚动的高度超过总滚动高度时退出循环 if (screen_height) * i > scroll_height: break driver.execute_script("window.scrollTo(0, 0);") res_list = [] # 先获取餐厅总数量 total_rest = len(driver.find_elements_by_xpath('//a[@class="sc-dBAPYN kcrxQo"]')) # 按索引循环处理每个餐厅 for index in range(total_rest): time.sleep(2) driver.execute_script("window.scrollTo(0, 0);") # 每次重新获取餐厅列表,取当前索引对应的元素 titles = driver.find_elements_by_xpath('//a[@class="sc-dBAPYN kcrxQo"]') element = titles[index].find_element_by_xpath('./div/h4') driver.execute_script("arguments[0].click();", element) # 等待详情页标题加载完成再取值,比固定sleep更稳定 name_of_rests = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, '#root > div > main > div > section.sc-kxynE.jzTfFZ > section > section > div > div > div > h1')) ).text res_list.append(name_of_rests) # 返回列表页 driver.back() # 等待列表页加载完成 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, '//a[@class="sc-dBAPYN kcrxQo"]')) ) print(res_list) driver.close()
优化说明
- 新增了显式等待
WebDriverWait替代固定time.sleep,代码运行效率和稳定性更高 - 每次返回列表页后重新抓取元素,完全规避过期元素引用问题
内容的提问来源于stack exchange,提问作者Iswar Chand
相关产品推荐
相关产品推荐

