共计 1655 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点
ChatGPT 网页端通过多种技术手段防止内容被轻易复制,这给开发者带来了不小的挑战。具体来说,它的防复制机制主要包括:

- DOM 保护 :关键内容被包裹在复杂的影子 DOM 中,常规的 DOM 查询方法无法直接获取
- 事件拦截 :复制、右键菜单等操作被 JavaScript 事件监听器拦截
- 动态渲染 :部分内容通过 Canvas 或 WebGL 渲染,无法通过 HTML 解析获取
这些机制使得开发者无法直接通过简单的爬虫技术获取 ChatGPT 的输出内容,影响了数据收集、知识库构建等二次开发需求。
方案对比
针对这些限制,我们研究了三种解决方案,各有其适用场景:
- Puppeteer/Playwright 实现 DOM 树重建
- 优点:能获取精确的 DOM 结构,保持原始格式
- 缺点:资源消耗较大,执行速度较慢
-
适用场景:需要精确复制内容和格式的情况
-
搭建 Node.js 代理层转发 API 响应
- 优点:效率高,直接获取原始数据
- 缺点:需要处理授权令牌刷新,可能违反服务条款
-
适用场景:已有 API 访问权限,需要高效获取数据
-
Tesseract.js OCR 识别兜底方案
- 优点:能处理 Canvas 渲染内容
- 缺点:识别精度有限,处理速度慢
- 适用场景:其他方法失效时的最后手段
核心实现:Puppeteer 方案
以下是使用 Puppeteer 实现 DOM 树重建的完整 TypeScript 代码示例:
/**
* 使用 Puppeteer 获取 ChatGPT 页面内容
* @param url 目标页面 URL
* @returns 解析后的内容
*/
async function getChatGPTContent(url: string): Promise<string> {
// 初始化 Puppeteer
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
try {const page = await browser.newPage();
// 使用 stealth 插件避免被检测
await stealthPlugin.enable(page);
// 设置合理的等待策略
await page.goto(url, {
waitUntil: 'networkidle2',
timeout: 30000
});
// 等待主要内容区域加载
await page.waitForSelector('#main-content', { timeout: 10000});
// 穿透影子 DOM 获取内容
const content = await page.evaluate(() => {const shadowRoot = document.querySelector('chatgpt-content')?.shadowRoot;
return shadowRoot?.textContent || '';
});
return content;
} finally {await browser.close();
}
}
生产考量
在将方案投入生产环境前,需要考虑以下因素:
- 性能指标
- Puppeteer 方案:约 5 -10 QPS,平均延迟 500ms
- API 代理方案:50+ QPS,平均延迟 100ms
-
OCR 方案:1-2 QPS,平均延迟 2000ms
-
风险等级
- Puppeteer:中等风险,可能触发反爬机制
- API 代理:高风险,可能违反服务条款
-
OCR:低风险,但效果有限
-
合规性边界
- 避免大规模爬取
- 尊重版权和 DMCA 规定
- 仅用于合法用途
避坑指南
在实施过程中,需要注意以下常见问题:
- 内存泄漏
- 确保正确关闭浏览器实例
-
避免同步操作阻塞事件循环
-
反爬对抗
- 动态调整请求频率
- 使用代理 IP 轮换
-
模拟人类操作模式
-
Cloudflare 防护
- 可能需要处理验证码
- 考虑使用第三方验证码解决服务
延伸思考
如何设计自适应防护强度的爬取策略?可以考虑以下方向:
- 根据响应时间和错误率动态调整请求频率
- 实现多种方案的自动切换机制
- 建立黑名单 IP 的自动规避系统
希望这些方案能帮助开发者解决 ChatGPT 内容复制的难题。在实际应用中,请务必遵守相关法律法规和服务条款。
正文完
发表至: 未分类
近两天内
