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

滚动Web Telegram时Selenium获取innerText触发StaleElementReferenceException异常

问题成因
  • StaleElementReferenceException 本质原因:向上滚动加载新聊天时,Telegram网页会动态更新DOM——旧消息元素可能被移除、重新渲染,或页面结构发生变化。你之前通过document.querySelectorAll获取的WebElement对象,对应的DOM节点已不存在于当前页面文档中,此时调用get_attribute就会抛出该异常。
  • 代码逻辑缺陷:
    • 一次性获取所有元素后遍历,但滚动操作导致DOM更新,旧元素引用直接失效。
    • 异常捕获仅处理NoSuchElementException,未覆盖StaleElementReferenceException,导致程序直接崩溃。
    • 每次循环都打开文件写入,IO操作频繁且低效。
修复方案

方案1:通过JS脚本直接提取文本(避免持有WebElement)

把元素查询和文本提取逻辑都放在JS脚本中,直接返回文本集合,从根源避免stale引用问题:

from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException

def find_message_container(driver):
    unique_texts = set()
    try:
        # 用JS一次性获取所有匹配元素的innerText并返回
        texts = driver.execute_script("""
            const elements = document.querySelectorAll('.message.spoilers-container');
            return Array.from(elements).map(el => el.innerText.trim());
        """)
        unique_texts.update(texts)
        
        # 统一写入文件,减少IO操作
        with open("unique_texts.txt", "w", encoding="utf-8") as file:
            file.write("\n".join(unique_texts))
            
    except (NoSuchElementException, StaleElementReferenceException) as e:
        print('处理元素时出错:', e)
    
    return unique_texts

方案2:滚动后重新查询元素+异常重试

若需保留WebElement操作,每次滚动后重新查询元素,并在遍历中捕获stale异常:

from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

def find_message_container(driver):
    unique_texts = set()
    try:
        # 等待新元素加载完成(滚动后调用时触发)
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, '.message.spoilers-container'))
        )
        # 每次都重新查询元素,不复用旧引用
        elements = driver.find_elements(By.CSS_SELECTOR, '.message.spoilers-container')
        
        for element in elements:
            try:
                text = element.get_attribute("innerText").trim()
                if text:
                    unique_texts.add(text)
            except StaleElementReferenceException:
                # 遇到失效元素直接跳过
                continue
        
        with open("unique_texts.txt", "w", encoding="utf-8") as file:
            file.write("\n".join(unique_texts))
            
    except NoSuchElementException as e:
        print('未找到目标元素容器:', e)
    
    return unique_texts

滚动加载的配合逻辑

调用上述函数时,每次滚动后都重新执行元素查询,不要复用之前的结果:

def scroll_and_load(driver):
    chat_container = driver.find_element(By.CSS_SELECTOR, '.messages-container')
    last_scroll_top = chat_container.get_attribute('scrollTop')
    
    while True:
        # 向上滚动聊天区域
        driver.execute_script("arguments[0].scrollTop -= 500", chat_container)
        
        # 等待新内容加载
        WebDriverWait(driver, 5).until(
            lambda d: d.find_element(By.CSS_SELECTOR, '.messages-container').get_attribute('scrollTop') != last_scroll_top
        )
        last_scroll_top = chat_container.get_attribute('scrollTop')
        
        # 重新获取并保存文本
        find_message_container(driver)
        
        # 滚动到顶部时停止
        if last_scroll_top == '0':
            break
关键注意事项
  • 页面更新(如滚动加载)后,永远重新查询元素,不要复用旧WebElement引用。
  • 必须捕获StaleElementReferenceException,动态页面中此类异常属于正常情况。
  • 写入文件时统一操作,避免循环内频繁打开关闭文件,提升效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:46:04