Key Takeaways
一套面向生产的中文 RAG 爬虫实现方案:先定义来源授权和成功条件,再处理增量采集、代理路由、原始证据、结构化切分、索引版本与检索评估。
代理只是网络路由的一层。它可以用于地域采集、出口隔离或会话保持,但不能替代访问授权、内容质量判断、权限控制,也不应被当作绕过明确拒绝访问的手段。
先定义搜索与数据意图
在写爬虫之前,先回答三个问题:
- 为什么采集:问答知识库、产品文档检索、市场情报,还是内部搜索?
- 允许采什么:哪些域名、路径、语言、地区和内容类型在授权范围内?
- 什么才算成功:不是 HTTP 200,而是得到正确版本、正确语言、可解析、可引用且允许进入索引的内容。
如果这些条件没有写进策略层,后面的代理、浏览器和向量库只会放大错误。
总体架构
来源策略库:把授权和抓取规则放在代码之外
robots.txt 是站点向爬虫表达抓取规则的标准机制之一,但 RFC 9309 明确指出它不是访问授权机制。因此,robots、服务条款、隐私要求、合同授权和应用层权限必须分别评估。
URL Frontier 与短租约
任务记录至少保存调度和幂等信息:
Worker 领取任务时写入短租约;只有租约持有者能够提交本轮采集结果。超时任务可重新入队,但写入文档版本时仍需使用 URL + 内容哈希或版本 ID 做幂等保护。
用 HTTP 条件请求减少无效下载
HTTP 条件请求适合文档类来源。ETag 可配合 If-None-Match,Last-Modified 可配合 If-Modified-Since;服务器确认表示未变化时可返回 304 Not Modified。按 HTTP Semantics,若同时发送两种条件,If-None-Match 的判断优先于 If-Modified-Since。
下面的示例保留 TLS 验证,并对重定向、超时、响应类型和响应体大小设置边界:
这里的 5 MiB、连接数和超时都是示例值,应根据来源和运行环境测量后调整,而不是当作通用最佳值。
即使存在 ETag 或 Last-Modified,关键来源仍应定期做完整内容哈希校验,因为缓存验证器是否准确取决于源站实现。
HTTP 优先,浏览器只做有理由的回退
优先使用普通 HTTP 抓取;只有在以下情况才考虑浏览器:
- 授权页面的业务正文依赖 JavaScript 渲染;
- 需要完成已授权的交互才能得到数据;
- 静态 HTML 缺失关键内容;
- 需要保存视觉状态或截图证据。
浏览器回退必须继承同一个 sourceId、授权策略、语言/地域要求和证据 Schema,不能成为绕过 401/403 的隐式备用通道。
代理路由:按任务需求选择,不按失败码盲目换 IP
可把路由策略拆成几类:
direct-first:直接访问能获得正确且允许的数据时,不增加代理层;fixed-market:需要验证某一国家/语言版本时固定地域;sticky-browser-task:同一个多步骤浏览器任务保持会话路由;rotating-independent:相互独立的任务之间轮换出口,用于容量和隔离,而不是规避明确访问限制。
404、Schema 错误、权限不足或来源明确拒绝访问,都不应通过不断换 IP 重试。代理也不会改变所有浏览器指纹或保证通过反自动化系统。
原始证据库:向量库不能成为唯一事实来源
建议保存:
- 原始响应或经过批准的快照;
- HTTP 状态、最终 URL、内容类型;
- 采集时间与 Collector 版本;
- 路由地域和会话模式,但移除账号密码;
- 内容 SHA-256;
- 必要时的截图或渲染证据;
- 来源策略版本和授权标签。
这样可以回答“这个答案来自哪一版页面”,也能在提取器或 Embedding 发生回归时重新处理原始证据,而不必重新访问源站。
URL 规范化:不要过度合并
同时保留:
- 请求 URL;
- 最终 URL;
- 规范 URL。
可以移除明确的追踪参数,但不要把语言、版本、地区、筛选条件或分页参数不同的页面错误合并。Canonical 标签可以作为信号,但不应无条件覆盖你的数据模型。
先提取结构,再切分
直接按原始 HTML 切块通常会把导航、页脚、重复菜单和隐藏 UI 一并送入 Embedding。更稳妥的做法是先提取正文结构,再以标题、段落、代码块和表格等语义边界切分。
Chunk 元数据决定是否可追溯
每个 Chunk 至少保存:
- Chunk ID;
- 文档版本;
- 标题路径;
- 来源 URL;
- 原文偏移或可定位锚点;
- 内容哈希;
- Embedding 模型与版本;
- 权限标签;
- 生效与失效时间。
不要预设一个适用于所有内容的固定 Token 大小。实际 Chunk 尺寸需要根据文档结构、Embedding 模型限制和检索评估结果确定。
索引版本化与灰度发布
上面的数量只是 Schema 示例,不代表 BytesFlows 的生产数据。
新索引应先生成候选版本,完成检索评估后再切换别名或版本指针,并保留至少一个可回滚版本。不要直接覆盖唯一的生产索引。
检索评估:验证答案,而不只是验证“向量写进去了”
准备来自真实用户任务的问题集,至少检查:
- 目标文档/证据是否被召回;
- 引用是否真正支持答案;
- 过期内容是否进入答案;
- 无充分证据时系统能否拒答;
- 是否发生权限泄漏;
- 是否被重复来源占满 Top-K;
- 中文、英文、代码等不同内容类型的效果;
- 检索与生成链路的延迟和成本。
评价指标应根据业务定义。不要在没有标注集和实验数据时宣称固定“准确率”或“召回率”。
Freshness 调度:从变化率推导,而不是写死频率
可把来源分为高变化、中变化和低变化,并记录历史变更间隔。一个可操作的起点是:
- 高频变化内容:从较短周期开始,并设置抓取频率上限;
- 稳定文档:延长周期,优先使用条件请求;
- 政策、权限和关键配置页:可以使用定期哈希检查或事件触发,但仍遵守来源策略。
最终频率应根据实际变化率、业务时效需求、来源限制和成本动态调整,而不是因为内容类型叫“价格”或“Release Notes”就固定成某个小时数。
失败分类与停止条件
| 现象 | 默认动作 | 进入重试前要确认什么 |
|---|---|---|
| 404 | 记录并降低优先级 | 是否为临时发布、错误 URL 或重定向变化 |
| 410 | 作为明确移除信号处理 | 是否需要删除索引版本或保留历史证据 |
| 401/403 | 停止自动重试并复核授权 | 凭证、权限、来源策略是否仍有效 |
| 429 | 降低速率 | Retry-After 或来源提供的速率指导 |
| 5xx | 有限指数退避 | 总重试预算和熔断条件 |
| 异常 MIME | 隔离 | 是否被重定向到登录页、错误页或下载文件 |
| 提取失败 | 保留证据,阻止索引发布 | 正文提取器是否发生回归 |
| 错语言/错地区 | 不入索引 | 路由、Accept-Language、Cookie 与页面实际输出 |
安全与隐私检查清单
相关内容
- 英文版:RAG Crawler with Proxies
- AI Data Collection from the Web
- Web Scraping Architecture Design
- Web Scraping Proxy Architecture
- AI 数据采集解决方案
参考标准与文档
FAQ
RAG 爬虫一定需要代理吗?
不需要。能直接、稳定并获授权访问的数据源,通常应优先减少不必要的网络层。代理更适合有明确地域、出口隔离或会话路由需求的场景。
HTTP 200 就代表可以写入向量库吗?
不代表。还需要验证最终 URL、内容类型、语言/地区、正文提取结果、权限标签和内容质量。挑战页、登录页和错误模板也可能返回 200。
为什么要保存原始证据,而不是只保存 Chunk?
因为提取器、切分策略和 Embedding 模型都会变化。保留原始证据才能复现某一版索引,并在处理逻辑升级后重新生成派生数据。
404 和 410 应该一样处理吗?
不建议。404 可能来自错误 URL、临时状态或路由变化;410 更明确表示资源已经被移除。两者都应保存状态和历史证据,但自动删除策略不应完全相同。
Alex Vance
核心基础设施架构团队
本文由 BytesFlows 工程团队审查。代码示例适用于合规的公开网页数据采集、QA 自动化、SEO 监测与市场研究工作流。实际基准表现可能因目标站点防爬策略、地理位置、客户端运行环境及请求频率而异。