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

Selenium爬虫调用函数后报StaleElementReferenceException错误如何解决

报错原因

StaleElementReferenceException 报错的核心是你先通过find_elements_by_xpath获取了所有<a>元素的引用存在elems列表中,后续遍历该列表时,原页面的DOM发生了变更(切换窗口回退、页面自动刷新、动态渲染更新都会导致原有DOM元素的引用失效),此时再对之前保存的元素对象调用get_attribute方法就会触发该异常。

解决方案

方案1:先提取所有链接存为字符串列表再遍历(最稳妥)

无需保留元素对象的引用,第一步先把所有符合规则的链接全部提取成纯字符串列表,后续直接遍历这个字符串列表处理即可,完全规避元素引用失效的问题。修改后的fetch_productlinks代码如下:

def fetch_productlinks(self, url):
    self.driver.get(url)
    # 先一次性提取所有符合条件的链接,存为普通字符串列表,不保留元素引用
    elems = self.driver.find_elements_by_xpath("//a[@href]")
    valid_urls = []
    for elem in elems:
        try:
            elem_url = elem.get_attribute("href")
            if re.match(".*/code/.*", elem_url):
                valid_urls.append(elem_url)
        except StaleElementReferenceException:
            # 提取链接阶段遇到失效的元素直接跳过即可
            continue
    # 遍历纯字符串的链接列表,完全不会有元素引用问题
    counter = 0
    for elem_url in valid_urls:
        if counter <= 1: 
            self.extract_imagesandmetadata(elem_url, self.driver)          
            counter += 1

方案2:优化多窗口操作逻辑

你当前的extract_imagesandmetadata方法里新开标签页的逻辑也有优化空间,切换窗口后不需要操作原页面的元素,同时处理完后直接关闭新打开的标签页,减少不必要的窗口占用,也能降低原页面DOM变更的概率:

def extract_imagesandmetadata(self, url, driver):
    before_window = driver.current_window_handle
    # 用js新开标签页访问目标链接,避免触发原页面操作
    driver.execute_script("window.open(arguments[0]);", url)
    # 切换到新标签页
    new_window = [window for window in driver.window_handles if window != before_window][0]
    driver.switch_to.window(new_window)
    print("Crawling ..." + url)
    html = driver.page_source
    # 每次新建临时字典,避免全局变量覆盖之前的存储数据
    tempdict = {}
    if html:
        self.soup = BeautifulSoup(html, 'html.parser')
        pimg = self.soup.find('img', {'class': 'img-responsive'})
        
        if pimg:
            print(pimg["src"])
            tempdict["pimg"] = self.img_base_path + pimg["src"]
        else:
            tempdict["pimg"] = ""

        ptitle = self.soup.find('h1', {'class': 'eprc-title'})

        if ptitle:
            print(self.sanitize_text(ptitle.text))
            tempdict["ptitle"] = self.sanitize_text(ptitle.text)
        else:
            tempdict["ptitle"] = ""

        tempdict["purl"] = url
    self.outdict.append(tempdict)
    # 处理完直接关闭当前新标签页,切回原窗口
    driver.close()
    driver.switch_to.window(before_window)

额外注意

不要使用全局的self.tempdict存储单条产品数据,否则每次遍历都会覆盖之前的内容,最终所有存储的条目都会是最后一条产品的信息,每次处理新链接时新建临时字典即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 08:06:03