最近在搭一个 AI Agent 的时候,我遇到一个特别常见的烦恼:网页内容拿过来了,但模型读不懂。文档页面里塞满了导航菜单、推荐阅读、Cookie 弹窗和图片懒加载代码,真正有用的正文只占网页源代码的一小段。Scrunch 这个项目标题很有意思,直接写着“Rewriting the Web for AI”,也就是把整个 Web 改写成 AI 能读的样子。它背后的问题,远不止“抓取正文并转成 Markdown”那么简单。
如果你做过 RAG、AI 搜索或者自动化 Agent,大概率也踩过同一个坑:模型能处理的上下文是有限的,而一个 HTML 页面里超过七成的内容,对理解正文毫无帮助。传统爬虫给的是“网页解剖后的残骸”,而这类工具想给的,是一种按 AI 阅读习惯重新组织过的内容结构。今天我想聊的,不是某个工具的安装命令,而是这一类方案到底在解决什么问题、典型处理链路是怎样的、落地时最容易在哪里翻车。
1. Scrunch 的切入点:网页语义和 AI 语义并不在同一层
先说一个基本判断:网页是给人眼设计的,不是给模型设计的。这个错位,才是 Scrunch 这类项目存在的根本原因。
1.1 人类阅读网页靠的是视觉,不是语义
我们看一个网页时,会不自觉地用视觉秩序判断信息层级。标题字号大,正文行距松,侧边栏颜色浅,按钮位置固定,这些视觉线索帮助我们快速决定“哪里要看,哪里可以跳过”。但把同样的页面转换成 HTML 源码后,视觉线索几乎全部丢失。
浏览器渲染出来的页面,在 DOM 里是一堆嵌套节点;交给模型之后,它看到的是一串没有轻重缓急的 token。HTML 里虽然有<article>、<nav>、<header>这类语义标签,但很多网站并不规范,甚至从头到尾都是<div>。模型没法像人一样“看一眼就知道这是导航”,它只能靠上下文去猜。
1.2 模型需要的不是“内容”,而是“关系”
很多人在做网页转文本时,第一个想法是:把正文提取出来,剩下的删掉。这个思路没有错,但不够。模型真正需要的,不只是“内容”,还包括内容之间的结构关系。
比如一个软件文档页面,可能有这样一个结构:标题是“安装指南”,下面分成“环境要求”“下载地址”“验证安装”三个小节,每小节里还有代码块和注意事项。如果只是把文字抽出来拼接成一大段,模型虽然能看到这些字,却很难判断哪条命令对应哪个步骤,也很难意识到“注意事项”是对前面内容的限制。Scrunch 这类工具的深层价值,就是把这种层级关系保留下来,用 Markdown 的标题、列表、引用和代码块重新表达。
1.3 把“提取内容”升级成“重写内容”
项目名里的 Rewriting 很关键。它不是 Extraction,不是 Cleaning,而是 Rewriting。这意味着它的目标不是从页面里拿走无用的部分,而是把一个面向视觉的页面,重新组织成面向语言模型的逻辑文本。
这个过程可以类比成翻译:同样是表达“安装前需要检查 Python 版本”,网页会用排版、图标、颜色来强调,AI 可读文本则需要用清晰的主语、条件和步骤顺序来表达。翻译不等于逐字替换,它需要理解意图,再重新输出。Scrunch 这类工具真正想做的,就是网页结构和模型理解之间的翻译层。
2. 从 URL 到 AI 可读文本:一条典型处理链路
不管底层实现多复杂,这类工具的核心流程通常可以拆成四层:输入获取、内容清理、语义结构化、输出封装。理解这条链路,比记住某个函数签名更重要。
| 阶段 | 主要任务 | 常见产物 |
|---|---|---|
| 输入获取 | 根据 URL 获取页面,或接收调用方传入的 HTML | 原始 HTML、渲染后的 DOM |
| 内容清理 | 去掉脚本、样式、广告、导航、页脚、弹窗、追踪参数 | 干净的正文片段 |
| 语义结构化 | 识别标题层级、列表、表格、代码块,压缩长段落 | Markdown、JSON 结构 |
| 输出封装 | 控制 token 长度,保留必要链接和元信息 | 精简文本、带元数据的结构化内容 |
2.1 输入层:先确认页面是静态可读,还是动态渲染
最常见的误判,是以为所有网页都能通过一次 HTTP 请求拿到完整内容。实际上,大量现代网站使用前端框架渲染,HTML 里只有空壳和脚本,真正的内容要等浏览器执行 JS 之后才会出现。
Scrunch 这类工具如果定位是“重写整个 Web”,就必须处理动态渲染,但这会带来成本和复杂度的显著上升。作为使用者,你要先想清楚自己的真实输入是什么:
- 如果只是处理文档站、博客、帮助中心,通常静态 HTML 或轻量渲染就够。
- 如果要处理大量 SPA 应用、登录后页面、需要交互才能加载的内容,就不能只用 URL 抓取,还要考虑无头浏览器、Cookie 会话、权限校验等环节。
- 无论哪种方式,都要尊重目标站点的访问协议和内容版权。合规采集是一个前提条件,不能因为工具方便就忽略。
2.2 清理层:去噪不是删文本,而是识别信息块
清理层最容易被理解成“删标签”。实际上,需要删除的不是某个标签,而是某些信息块。导航、页脚、侧边栏推荐、Cookie 弹窗、悬浮客服、图片懒加载占位符,这些块在 DOM 里可能结构完全不一样,不能靠一个正则表达式解决。
比较稳妥的做法,是综合几种策略:
- 优先使用页面里的语义标签,比如
<main>、<article>、<nav>、<footer>。 - 再通过阅读类算法判断段落密度、链接密度和文本长度。
- 最后用选择器规则处理已知站点特例。
这里有个权衡:清理太激进,会误删正文里的提示信息或者表格;清理太保守,又会留下大量噪声。所以好的清理层应该输出“清理了什么”,而不是只输出“剩下什么”,这样便于事后检查。
2.3 语义层:把文档切成模型能使用的结构
清理之后,剩下的是正文,但正文本身还不够。一个长文档页面可能有几十个小节,每个小节又有自己的层级关系。如果直接塞给模型,后面的内容很容易被截断,或者模型无法精准引用某一步骤。
语义结构化阶段,通常要做这几件事:
- 把页面按标题层级切块,让每个块拥有独立上下文。
- 保留列表、表格、代码块的结构,不要简单拍平成纯文本。
- 标记重要链接,比如文档里的“下一步阅读”“相关 API”和源码下载地址。
- 对超长段落做压缩或摘要,但前提是不能破坏原意。
这些操作的目的,是让模型拿到的不只是“一段文字”,而是一个可以定位、可以引用、可以继续追问的知识单元。
2.4 输出层:在 Markdown、JSON 和 token 预算之间做选择
输出格式直接影响下游任务。常见的选择有两种:
- Markdown 格式:适合直接作为 LLM 的上下文,因为标题、列表和代码块会被模型比较自然地理解,而且 token 开销相对小。
- JSON 格式:适合还需要二次加工的调用方,可以保留文章标题、作者、发布时间、原文链接、正文分段等结构化字段。
| 输出格式 | 优点 | 适合场景 |
|---|---|---|
| Markdown | 可读性好、token 效率高、模型理解成本低 | RAG 切片、问答、Agent 阅读 |
| JSON | 元数据完整、机器可解析 | 需要过滤、排序、二次筛选的流程 |
| 纯文本 | 最简单、兼容性最好 | 只关注正文内容的轻量场景 |
输出阶段还要考虑 token 预算。在没有明显版本说明的情况下,不要假设一个页面经过转换后一定很短。有些页面正文本身就是几万字的长篇报告,转换得再干净,也还是要按策略切块。切块策略不是“每 500 个 token 一刀切”,而是尽量按章节边界切,这样语义才完整。
3. 为什么不能直接把 HTML 喂给模型
有人可能会问:既然模型能力越来越强,为什么不直接把整个 HTML 丢给它,让它自己判断哪些内容有用?这个思路听起来简单,实际用起来问题很多。
3.1 token 预算被大量浪费
一个普通的企业官网页面,HTML 源码可能就有 100KB 到 200KB,其中大部分是 CSS 类名、脚本配置、埋点代码和构建工具生成的注释。如果换算成 token,一次请求可能就消耗几万甚至十几万 token。模型的上下文窗口再大,也不应该浪费在这些内容上。
更重要的是,token 开销直接影响成本和响应速度。做 Agent 场景时,一个任务往往要读好几个页面,如果每个页面都这样消耗,任务很快就达到上下文上限,后面的关键内容反而没位置了。
3.2 标签本身不是语义
HTML 里有大量类名是为样式服务的,比如class="sc-7b3f9a1d"、>