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

如何在Python Selenium中分页并保存页面HTML?遇循环及元素过期异常

解决分页遍历HTML保存的Selenium问题

我来帮你搞定这两个分页循环的问题,先拆解下每个方案的问题根源,再给你修复后的可用代码:

问题根源分析

第一种方案的问题

  • 漏掉了第一页的HTML保存:直接进入循环点击下一页,初始页面的内容根本没存入列表
  • 循环内未重新定位元素:页面刷新后,之前定位的search元素已经和DOM脱离,你判断的其实是旧元素的状态,导致末页时无法正确触发退出条件
  • 判断逻辑不准确:前端是通过disabled属性+自定义class控制禁用状态,单纯用is_enabled()不一定能准确识别禁用状态

第二种方案的问题

  • 仅在循环前定位一次元素:点击下一页后页面DOM重新渲染,原来的search元素就变成了“过时引用”,自然抛出StaleElementReferenceException

修复后的解决方案

核心思路是:每次循环重新定位元素、先存第一页、用更准确的末页判断逻辑,具体代码如下:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import time

# 存储HTML页面的列表
news_list = []

# 第一步:先保存第一页的HTML
wait = WebDriverWait(driver, 10)
# 等待当前页码元素加载完成,确保页面已就绪
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "li[data-testid='current-page-item']")))
first_html = driver.page_source
soup_first = BeautifulSoup(first_html, "html.parser")
news_list.append(soup_first)

# 第二步:循环处理后续页面
while True:
    try:
        # 每次循环都重新定位下一页箭头(最后一个li元素)
        next_page_btn = wait.until(EC.presence_of_element_located((By.XPATH, '/html/body/div/div/div[2]/div[2]/div/ol/li[5]')))
        
        # 精准判断是否为末页:同时检查disabled属性和专属禁用class
        is_last_page = next_page_btn.get_attribute("disabled") is not None and "fDeSdf" in next_page_btn.get_attribute("class")
        
        if is_last_page:
            # 到达末页,退出循环
            break
        
        # 点击下一页
        next_page_btn.click()
        # 推荐用显式等待替代固定sleep,这里先保留sleep方便理解
        time.sleep(5)
        
        # 保存当前页面HTML
        current_html = driver.page_source
        soup_current = BeautifulSoup(current_html, "html.parser")
        news_list.append(soup_current)
        
    except Exception as e:
        print(f"分页处理出错: {str(e)}")
        break

关键优化点

  1. 先存第一页:避免漏掉初始页面的内容
  2. 循环内重新定位元素:彻底解决StaleElementReferenceException,因为每次页面刷新后都重新获取最新的元素引用
  3. 精准末页判断:结合disabled属性和前端自定义的禁用class,比单纯用is_enabled()更适配页面的实际逻辑
  4. 异常捕获:防止循环中出现意外错误导致程序直接崩溃

另外,建议把固定的time.sleep(5)替换成显式等待,比如等待当前页码更新,这样更高效稳定:

# 替换time.sleep(5)的代码
# 等待旧的当前页码元素失效(说明页面开始刷新)
old_current_page = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "li[data-testid='current-page-item']")))
wait.until(EC.staleness_of(old_current_page))
# 等待新的当前页码元素出现(说明页面加载完成)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "li[data-testid='current-page-item']")))

这样可以确保页面完全加载后再获取HTML,避免捕获到未渲染完成的内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:01:41