Selenium Python点击翻页报StaleElementReferenceException如何解决
问题根因
出现StaleElementReferenceException的核心原因是你提前定位好的DOM元素,在页面刷新/局部更新后,原引用已经被浏览器销毁,后续再调用该元素的属性/方法就会触发该报错。
你的代码存在两个明确的问题点:
- 提前捕获下一页按钮
pag后,先遍历了当前页列表,这个过程如果页面触发异步渲染更新,会导致pag的引用失效,点击时直接报错 - 点击翻页后直接调用
info(),但list_ed还是上一页的元素引用,哪怕设置了35秒等待,后续遍历也会触发同类报错
修复建议
- 调整操作顺序:优先处理完当前页所有数据,再定位下一页按钮并点击,避免捕获按钮后等待过久导致元素失效
- 不要复用跨页的元素引用:每次翻页后重新定位列表元素,不要沿用之前捕获的
list_ed变量 - 替换固定sleep为显式等待:通过判断页面元素是否更新来确认翻页完成,比固定时长等待兼容性更强
- 增加重试机制:对下一页点击操作增加异常捕获重试逻辑,避免偶发的元素失效问题
修复后可运行代码
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 from selenium.common.exceptions import StaleElementReferenceException, TimeoutException def get_current_page_info(driver, wait): # 每次拉取数据前重新定位当前页的列表元素 list_ed = wait.until(EC.presence_of_all_elements_located((By.XPATH, '//*[@id="jornal"]/li[@class="lista"]'))) for idx, ed in enumerate(list_ed): # 遍历过程中增加异常重试,避免偶发元素失效 for _ in range(3): try: el_text = ed.text el = ed.find_element(By.XPATH, 'a').get_attribute('href') print(el_text) print(el) break except StaleElementReferenceException: list_ed = wait.until(EC.presence_of_all_elements_located((By.XPATH, '//*[@id="jornal"]/li[@class="lista"]'))) ed = list_ed[idx] def click_next_page(driver, wait) -> bool: # 点击前才定位下一页按钮,避免提前捕获失效 try: next_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="Pagination"]/a[@class="next"]'))) # 记录当前页第一条数据的文本,用来校验翻页是否完成 first_item_text = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="jornal"]/li[@class="lista"][1]'))).text next_btn.click() # 等待页面更新:要么第一条数据变化,要么下一页按钮消失(到最后一页) wait.until(lambda d: d.find_element(By.XPATH, '//*[@id="jornal"]/li[@class="lista"][1]').text != first_item_text \ or len(d.find_elements(By.XPATH, '//*[@id="Pagination"]/a[@class="next"]')) == 0) return True except TimeoutException: # 没有下一页,终止循环 return False except StaleElementReferenceException: # 按钮偶发失效自动重试 return click_next_page(driver, wait) def main(): driver = webdriver.Firefox() driver.implicitly_wait(10) wait = WebDriverWait(driver, 20) driver.get("https://www.imprensaoficialmunicipal.com.br/sao_joaquim_da_barra") while True: # 先拉取当前页所有数据 get_current_page_info(driver, wait) # 再尝试翻页 has_next = click_next_page(driver, wait) if not has_next: break driver.quit() if __name__ == '__main__': main()
内容的提问来源于stack exchange,提问作者Rafael
相关产品推荐
相关产品推荐

