Python Selenium scrollIntoView触发StaleElementReferenceException问题
问题解决:NBA赛程爬取中页面重载导致的StaleElementReferenceException
问题场景
爬取NBA赛程页面中data-id='nba:schedule:main:team:link'的球队名称,通过scrollIntoView定位元素后提取内容到列表和文本文件。但页面中途重载后屏幕冻结,滚动操作停止,添加time.sleep(3)也无效,抛出StaleElementReferenceException错误。
错误原因
StaleElementReferenceException的本质是:你最初获取的元素引用,在页面DOM被重新渲染(比如页面重载、动态刷新)后,已经和当前页面的元素失去关联。你一开始一次性获取了所有elements_to_save,但页面中途重载后,这些元素对象已经失效,再操作就会报错。
解决方案
核心思路是避免复用失效的元素引用,每次操作前重新定位元素,同时处理页面动态加载的情况:
修改后的代码
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 from selenium.common.exceptions import StaleElementReferenceException from datetime import datetime driver = webdriver.Chrome(r"C:\Users\Admin\Downloads\chromedriver_win32 (1)\chromedriver.exe") driver.get("https://www.nba.com/schedule?pd=false®ion=1") wait = WebDriverWait(driver, 10) # 处理同意cookie弹窗 wait.until(EC.element_to_be_clickable((By.ID, "onetrust-accept-btn-handler"))).click() # 初始化文件和列表 myList = [] with open('new_result_file00.txt', 'w', encoding='utf-8') as f: # 写入初始标题和时间 header_element = wait.until(EC.presence_of_element_located((By.XPATH, "//div/div/div/div/h4"))) f.write(header_element.text + "\n") f.write(str(datetime.today()) + "\n") myList.append(1) # 循环处理元素,每次重新获取避免stale引用 processed_count = 0 while True: try: # 每次循环重新获取所有当前页面的目标元素 elements_to_save = wait.until(EC.presence_of_all_elements_located((By.XPATH, "//*[@data-id='nba:schedule:main:team:link']"))) # 只处理未处理过的元素 for element in elements_to_save[processed_count:]: try: # 滚动到元素位置 driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", element) # 等待元素文本可获取 wait.until(EC.visibility_of(element)) team_name = element.text # 写入文件和列表 f.write(team_name + "\n") f.write(str(datetime.today()) + "\n") myList.append(team_name) processed_count += 1 # 短暂等待避免滚动过快触发页面重载 time.sleep(1) except StaleElementReferenceException: # 遇到stale引用,跳过当前元素,下次循环重新获取 continue # 尝试滚动到底部加载更多内容 driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") time.sleep(2) # 检查是否还有新元素加载 new_elements = wait.until(EC.presence_of_all_elements_located((By.XPATH, "//*[@data-id='nba:schedule:main:team:link']"))) if len(new_elements) == processed_count: # 没有新元素,结束循环 break except Exception as e: print(f"处理出错: {e}") break driver.quit()
关键改动说明
- 每次循环重新获取元素:不再一次性获取所有元素,而是每次循环重新定位,避免页面重载后引用失效
- 使用显式等待:用
WebDriverWait替代implicitly_wait,更精准地等待元素可交互/可见,提升稳定性 - 处理动态加载:滚动到底部后等待新元素加载,直到没有新内容为止
- 捕获StaleElementReferenceException:遇到失效引用时跳过当前元素,下次循环重新获取
- 用with语句管理文件:自动处理文件关闭,避免资源泄漏
- 优化滚动方式:使用平滑滚动并居中元素,减少页面重载触发概率
内容的提问来源于stack exchange,提问作者xlmaster
相关产品推荐
相关产品推荐

