ChatGPT网页内容抽取实战:基于Python的高效爬取方案与避坑指南

1次阅读
没有评论

共计 2943 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

背景痛点

从 ChatGPT 网页端抽取数据时,开发者常遇到三个主要难点:

ChatGPT 网页内容抽取实战:基于 Python 的高效爬取方案与避坑指南

  1. 动态渲染:对话内容通过 JavaScript 动态加载,传统 HTTP 请求无法获取完整 DOM 树
  2. 速率限制:频繁请求会触发 429 错误,甚至导致临时封禁
  3. 会话保持:需要维持登录状态才能访问历史对话记录

这些特性使得常规的 Requests+BeautifulSoup 组合难以奏效,必须采用能够执行 JavaScript 的浏览器自动化工具。

技术选型对比

目前主流方案主要有三种技术路线:

  • Requests+BeautifulSoup
  • 优点:轻量级、速度快
  • 局限:无法处理动态内容
  • 适用场景:静态页面抓取

  • Selenium

  • 优点:完整浏览器环境、支持所有 JS 渲染
  • 缺点:资源消耗大
  • 适用场景:需要交互操作的复杂页面

  • Playwright

  • 优点:多浏览器支持、自动等待机制
  • 缺点:较新生态
  • 适用场景:需要跨浏览器测试的项目

对于 ChatGPT 这种 SPA 应用,Selenium 目前仍是平衡功能和稳定性的最佳选择。

核心实现方案

1. Selenium 环境配置

需要先安装浏览器驱动(以 Chrome 为例):

  1. 安装 Selenium 包:pip install selenium
  2. 下载对应版本的 ChromeDriver
  3. 配置无头模式减少资源占用

2. 登录状态保持

关键技巧:

  • 使用 get_cookies() 保存登录凭据
  • 通过 add_cookie() 恢复会话
  • 设置合理的 session 过期处理逻辑

3. 动态加载处理

ChatGPT 采用无限滚动加载,需要模拟滚动操作:

driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
time.sleep(2)  # 等待新内容加载

4. 内容解析最佳实践

推荐使用 XPath 定位对话气泡:

# 定位 AI 回复
ais = driver.find_elements(By.XPATH, '//div[contains(@class,"ai-message")]')
# 定位用户提问
users = driver.find_elements(By.XPATH, '//div[contains(@class,"user-message")]')

完整代码示例

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import json

# 初始化浏览器
def init_browser():
    options = webdriver.ChromeOptions()
    options.add_argument("--headless")  # 无头模式
    driver = webdriver.Chrome(options=options)
    return driver

# 登录并保存 cookies
def login(driver, email, password):
    driver.get("https://chat.openai.com/auth/login")
    time.sleep(3)

    # 执行登录操作(示例伪代码)driver.find_element(By.ID, "username").send_keys(email)
    driver.find_element(By.ID, "password").send_keys(password)
    driver.find_element(By.XPATH, "//button[contains(text(),' 登录 ')]").click()

    time.sleep(5)  # 等待登录完成
    return driver.get_cookies()

# 加载完整对话历史
def load_full_conversation(driver, url):
    driver.get(url)
    last_height = driver.execute_script("return document.body.scrollHeight")

    while True:
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
        time.sleep(2)
        new_height = driver.execute_script("return document.body.scrollHeight")
        if new_height == last_height:
            break
        last_height = new_height

    return driver.page_source

if __name__ == "__main__":
    driver = init_browser()
    cookies = login(driver, "your_email", "your_password")

    # 保存 cookies 供下次使用
    with open("cookies.json", "w") as f:
        json.dump(cookies, f)

    html = load_full_conversation(driver, "https://chat.openai.com/c/conv-id")
    driver.quit()

风险控制策略

1. 请求频率控制

推荐使用指数退避算法:

import random

def exponential_backoff(retries):
    base_delay = 5  # 基础延迟秒数
    max_delay = 60  # 最大延迟
    delay = min(base_delay * (2 ** retries) + random.uniform(0, 1), max_delay)
    time.sleep(delay)

2. 反检测措施

  • 轮换 User-Agent
  • 随机化操作间隔
  • 禁用自动化特征:
    options.add_argument("--disable-blink-features=AutomationControlled")

3. 验证码处理预案

建议设置验证码触发阈值报警,当出现以下情况时暂停采集:

  • 连续 3 次请求返回 403
  • 页面出现验证码元素
  • 响应时间异常延长

避坑指南

1. 避免 429 错误

关键 header 配置:

headers = {
    "Accept-Language": "en-US,en;q=0.9",
    "Referer": "https://chat.openai.com/",
    "DNT": "1"
}

2. 指纹检测规避

无头模式下的额外配置:

options.add_argument("--disable-gpu")
options.add_argument("--window-size=1920,1080")

3. 数据去重设计

建议使用对话 ID+ 时间戳作为唯一键:

import hashlib

def generate_msg_id(msg):
    return hashlib.md5(f"{msg['timestamp']}-{msg['content'][:50]}".encode()).hexdigest()

开放性问题

当需要大规模采集时,如何设计分布式爬取架构?考虑以下方面:

  1. 任务调度:如何分配 URL 给不同节点
  2. 状态同步:确保所有节点共享最新的反爬策略
  3. 数据一致性:避免重复采集和冲突
  4. 监控系统:实时掌握各节点状态

期待大家在评论区分享自己的分布式爬虫设计思路!

正文完
 0
评论(没有评论)