共计 2850 个字符,预计需要花费 8 分钟才能阅读完成。
背景与痛点
在日常开发中,我们经常需要从 ChatGPT 网页版提取数据用于分析、训练或集成到其他系统中。但直接抽取数据面临几个主要挑战:

- 动态内容加载:ChatGPT 使用 JavaScript 动态渲染内容,传统爬虫无法获取完整数据
- 反爬机制:包括验证码、请求频率限制、用户行为检测等
- 数据结构复杂:对话内容嵌套在多层 DOM 结构中,需要精准定位
常见应用场景包括:
- 构建自定义知识库
- 对话历史分析
- 训练专用领域的语言模型
- 开发第三方 ChatGPT 客户端
技术选型对比
处理动态网页主要有三种方案:
- requests + BeautifulSoup
- 优点:轻量、简单
-
缺点:无法执行 JS,不适用于动态内容
-
Selenium
- 优点:可模拟真实浏览器行为
-
缺点:资源占用高,速度慢
-
Playwright
- 优点:支持多浏览器,速度快,API 简洁
- 缺点:较新,社区资源相对较少
对于 ChatGPT 这种重度依赖 JS 的网站,Playwright 是最佳选择。
核心实现
1. 环境准备
首先安装必要依赖:
pip install playwright
playwright install
2. 处理动态加载
Playwright 可以等待特定元素加载完成:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto('https://chat.openai.com/')
# 等待对话框加载
page.wait_for_selector('.chat-container')
3. 绕过基础反爬
几个实用技巧:
- 使用真实 User-Agent
- 添加合理的等待时间
- 模拟人类操作模式
# 设置真实 User-Agent
page.set_extra_http_headers({'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
})
# 模拟人类输入速度
page.type('#prompt-textarea', 'Hello', delay=100)
4. 数据解析
ChatGPT 的对话内容通常包含在特定 class 的元素中:
dialogs = page.query_selector_all('.chat-message')
for dialog in dialogs:
role = dialog.query_selector('.role').inner_text()
content = dialog.query_selector('.content').inner_text()
print(f'{role}: {content}')
完整代码示例
from playwright.sync_api import sync_playwright
import time
def scrape_chatgpt(username, password):
with sync_playwright() as p:
# 启动浏览器
browser = p.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
# 访问登录页面
page.goto('https://chat.openai.com/auth/login')
# 登录流程
page.click('button:has-text("Log in")')
page.fill('input[name="username"]', username)
page.click('button:has-text("Continue")')
page.fill('input[name="password"]', password)
page.click('button:has-text("Continue")')
# 等待登录完成
page.wait_for_selector('.chat-container', timeout=10000)
# 模拟对话
page.type('.prompt-textarea', '请介绍一下你自己', delay=100)
page.click('button:has-text("Send")')
# 等待回复
page.wait_for_selector('.chat-message:last-child .content')
# 提取对话内容
messages = page.query_selector_all('.chat-message')
for msg in messages:
role = msg.query_selector('.role').inner_text()
content = msg.query_selector('.content').inner_text()
print(f'{role}: {content}')
# 关闭浏览器
browser.close()
if __name__ == '__main__':
scrape_chatgpt('your_username', 'your_password')
性能与安全考量
1. 请求频率控制
避免短时间内发送大量请求,建议:
- 每个请求间隔 2 - 5 秒
- 使用随机间隔时间
import random
time.sleep(2 + random.random() * 3) # 2- 5 秒随机等待
2. 代理 IP 使用
当需要大规模采集时,使用代理池:
browser = p.chromium.launch(
headless=True,
proxy={
'server': 'http://proxy.example.com:8080',
'username': 'user',
'password': 'pass'
}
)
3. 异常处理
健壮的异常处理机制必不可少:
try:
page.wait_for_selector('.chat-message', timeout=5000)
except:
print('元素加载超时')
# 重试或记录日志
生产环境避坑指南
常见错误
- 元素定位失败
- 原因:DOM 结构变化
-
解决:定期检查选择器,使用更稳定的定位方式
-
账号被封禁
- 原因:行为模式异常
-
解决:模拟人类操作,降低请求频率
-
数据不完整
- 原因:未等待动态加载
- 解决:合理使用 wait_for_selector
最佳实践
- 使用独立的测试账号
- 定期维护选择器
- 实现断点续爬功能
- 添加详细日志记录
扩展思考
本文介绍的技术同样适用于其他动态网站的数据抽取,如:
- 社交媒体平台(Twitter、Facebook)
- 电商网站(Amazon、淘宝)
- 单页应用(SPA)
关键是要理解网站的技术架构,选择合适的工具,并尊重网站的 robots.txt 规定。
结语
通过 Playwright 实现 ChatGPT 数据抽取是一个高效可靠的方案。在实际应用中,建议根据具体需求调整代码,并始终遵守相关法律法规和网站使用条款。希望本文能为你的数据采集项目提供有价值的参考。
正文完
发表至: 未分类
近三天内
