有谷大脑
返回博客

收藏一篇网页进知识库,不只是「抓 HTML」

很多工具抓到的 Markdown 里混着导流语、相关阅读和 TOC。有谷用浏览器真渲染、站点规则抽取和块级清洗,把干净正文送进 RAG。

用 Chrome 插件把一篇技术博客收进知识库,问:「作者对 Redis 持久化的结论是什么?」

如果入库时只是把页面 HTML 转成一大段文本,常见结果是:检索命中了文末「相关阅读」里另一篇 Redis 文章的摘要,模型据此答了一个和原文无关的结论——正文其实在,但被噪声淹没了

网页收藏是知识库最高频的入口之一,却长期被当成「curl 一下就行」的二等公民。有谷大脑的处理分三层:真渲染拿到完整 DOM → 规则引擎抽正文 → Markdown 块级清洗,再进入和其他格式共用的 chunk 与向量索引链路。

网页收藏入库:浏览器渲染、规则抽取、块级清洗、语义 chunk。

为什么「只抓 HTML」不够

静态 HTTP 请求拿不到 JavaScript 渲染后的内容。现代博客、文档站、Notion 导出页大量依赖客户端渲染——你 curl 到的往往是一个空壳 <div id="root"> 和几行 script。

即使用无头浏览器拿到了完整 DOM,正文抽取也只完成一半。Readability、defuddle、trafilatura 这类抽取器工作在 DOM 层:靠 <article>、文本密度、class 命名把正文容器从导航、侧栏、页脚里剥出来。它们对容器外的噪声很有效,对容器内夹带的噪声几乎无能为力:

  • WordPress 主题把 TOC、中部广告、Related Posts、Newsletter 卡片渲染在 <article> 里面;
  • 公众号文章开头的「点击上方蓝字关注」、结尾的「在看 / 点赞 / 转发」——在 DOM 上就是普通段落,启发式无法区分;
  • CSDN、掘金文末的版权块和导流语,和正文段落结构一模一样。

转成 Markdown 之后,这些残留如果直接 chunk、embedding,会污染向量空间,还会在问答里被当成有效证据。

有谷网页抓取链路

一条 URL 进入有谷,大致经过这些阶段:

  1. 规范化 URL — 去掉 utm_* 等追踪参数,合并重复收藏
  2. 浏览器渲染 — 独立 URL-fetch Worker 里用 Playwright 打开页面,必要时走代理;等网络空闲后再取 DOM 和最终 URL
  3. 站点规则抽取 — Mercury 风格的 per-domain 规则优先:部分站点有专用 extractor,直接给出 content HTML 和元数据
  4. 通用正文提取 — 规则未命中时,trafilatura 从 HTML 抽主文本,转成 Markdown
  5. 代码块归一化 — 修复 gutter 表格、pre 结构等常见站点 markup,避免代码块在 Markdown 层碎裂
  6. 块级清洗 — 在 Markdown AST 层逐块判定:保留正文,去掉广告、相关阅读、TOC、订阅引导、版权声明
  7. chunk + 索引 — 干净 Markdown 进入语义切块和向量库,metadata 保留 canonical URL、标题、站点名、题图

输出契约是结构化的:标题、Markdown 正文、展示用 HTML、作者、描述、HTTP 状态——下游阅读器和 RAG 共用同一份清洗结果。

两层清洗各管什么

**DOM 层(抽取)**适合删页面骨架:导航、侧栏、页脚、评论区容器。有 mature 工具可用,不必重造。

Markdown 层(清洗)适合删正文内夹带:转成块序列后,不管原站是 WordPress、公众号还是 Medium,输入形态统一——段落、标题、列表、代码块边界由 AST 保证。代价是 class/id 线索丢失,只能靠块的文本语义判断去留。

典型要删的块:

标签典型内容
头部导流「点击上方蓝字关注我们」
文内 TOC纯锚点链接列表
中部推广「〔推广〕XX 训练营限时 5 折」
相关阅读「相关阅读」+ 站内链接列表
尾部版权「本文首发于 xxx,转载请注明出处」

清洗后的 Markdown 才适合 TTS 朗读和 RAG 检索——和PDF 入库「先理解结构再 downstream」是同一思路。

和插件收藏的配合

有谷 Chrome 插件在用户当前 Tab 一键收藏:把 URL 交给后端异步抓取,而不是把浏览器里已渲染的 DOM 直接 POST 上来。好处是:

  • 收藏动作快,不阻塞用户浏览
  • 抓取在专用 Worker 里跑,浏览器池、代理、重试策略和 API 进程隔离
  • 同一 URL 重复收藏可走去重,抓取结果可复现

用户看到的是「已保存」,后台可能是十秒到一分钟的抓取 + 清洗 + 入库;入库进度通过 SSE 推阶段文案,不用盲等。

什么时候网页 RAG 最容易出问题

强 JS 站点且渲染超时 — 页面需要登录、或无限滚动才加载正文,需要在抓取策略里单独处理。

正文极短但评论区很长 — DOM 抽取若误把评论当正文,清洗层也救不回来,需要抽取阶段就限定 content root。

双语混排页面 — 块级清洗不解决语言检测;问答侧需要用户明确问的是哪一段。

频繁改版的站点 — Mercury 规则需要维护;通用 trafilatura 兜底精度会下降,但总比把整页 HTML 硬切强。

在整条产品链里的位置

网页收藏连接「采集」和「知识」:

  • 采集侧:URL-fetch Worker、DOM/Markdown 两层清洗(本篇)
  • 存储侧:与 PDF、Excel代码 共用知识库与权限模型
  • 消费侧:阅读器展示、Agent 问答检索、MCP对外暴露

网页是入口最轻的一种格式,入库质量却直接决定用户愿不愿意持续收藏——把干净正文送进索引,和把 PDF 版面框准一样,都是 RAG 的地基