让Web为AI重写:从HTML噪音到语义结构的工程实践
2026/9/11 20:20:50 网站建设 项目流程

如果你做过基于大模型的 RAG 知识库,或者用过 AI 搜索类 Agent,大概率会遇到一个很别扭的场景:模型从网页里拿到的内容,不是正文,而是导航菜单、Cookie 弹窗、广告位、猜你喜欢和评论区。明明是高质量的文章,喂给模型之后,答案却像在“噪音堆里翻线索”。

这件事的本质,不是模型不够聪明,而是 Web 本身就不是为 AI 设计的。浏览器里的 HTML 是给人眼看、给人手点开发的,AI 读到的是未经整理的结构碎片。今天,一群工具开始尝试改变这个局面,Scrunch 就是其中一个非常典型的代表。它的核心问题很直接:把人读的网页,重写成 AI 能直接消化和操作的内容。

这篇文章不打算复述某一个项目的手册,而是围绕“Rewriting the Web for AI”这个判断,讲清楚三条事:为什么 Web 对 AI 不友好;重塑 Web 具体有哪几个技术层次;以及我们能上手怎么做。如果你在做 RAG、AI Agent、爬虫工程化,或者只是想让自己的网站更容易被 AI 引用,这篇文章值得读完并收藏。

先说一个明确的判断:让 Web 重新适配 AI,不是把网页改成纯文本,而是做一次系统性的“结构重写”。下面展开讲。

1. 这篇文章真正要解决的问题

先说痛点。我见过不少团队做 AI 产品时,第一步不是调模型,而是“清洗网页数据”。他们写大量正则表达式,删标签、去广告、去导航、拼正文,最后得到的还是一份不太干净的 Markdown。

问题出在哪?出在我们默认了“Web 内容 = 一段可抓取的 HTML”。但现实是,现代网页的 HTML 是浏览器渲染的结果,其中混杂了大量视觉布局和交互逻辑。AI 不关心视觉,它关心的是信息实体:这篇文档讲什么、关键结论是什么、有哪些结构可引用。HTML 本身提供的信息密度太低。

Scrunch 这类工具背后代表的方向,就是要在 Web 和 AI 之间加一层“重写层”。它要做的事,不是简单地把 HTML 转成文本,而是把网页里的噪音过滤掉,把信息重新组织和表达,让大模型能以更低的成本读取、理解和调用。

谁最该读这篇文章:

  • 正在做 RAG 知识库,但被网页内容清洗折磨的开发者;
  • 做 AI Agent,希望 Agent 能直接“读懂网页”而不仅是搜索链接的人;
  • 做垂直搜索、内容聚合、网页正文抽取服务的后端工程师;
  • 以及那些希望自己的网站内容可以被 AI 引用、被 Agent 推荐给用户的前端或站长。

读完这篇文章,你至少能回答三个问题:Web for AI 到底要改造什么;改造分哪几个层次;如何用最小代码跑通一个“网页转 AI 友好内容”的服务。

2. “Rewriting the Web for AI”到底是什么意思

Scrunch 这个标题有一个关键动作:Rewriting,重写。它不只是抽取,也是重写。要理解这个动作,先要理解两个对象——人和 AI 读取网页的差异。

人看网页,看的是视觉层级。标题大不大、排在哪个位置、颜色是否突出、导航是否有下拉,都会影响人对信息的判断。AI 看网页,看到的通常是一段 DOM 结构、一堆标签、文本和属性。它没有“视觉注意力”的概念,只会按标签结构推断语义。所以在传统 Web 里,AI 天然处于劣势。

所谓“Rewriting the Web for AI”,本质是做三件事:

  1. 把“面向渲染”的 HTML 重写成“面向理解”的结构化文本;
  2. 把“人眼识别”的页面信息重写成“模型可直接引用”的语义单元;
  3. 把“页面浏览”的交互方式重写成“Agent 可调用”的服务接口。

这里有一个很容易误会的点:很多人以为重写网页就是把 HTML 标签全部剥掉。实际上,真正的重写是“重新组织语义单元”。比如剥掉标签之后,你仍然要能识别出一篇文章的标题、作者、发布时间、正文、要点和小结。这些信息是人读网页时会自动获取的,AI 缺的就是这套自动识别能力。

Scrunch 这类工具的立意,恰好就是在这个语义化组织上做文章。说得直白一点:Web 原有的信息,是以“视觉页面”为单位的;AI 时代需要的信息,是以“语义文档”和“可操作接口”为单位的。从页面到文档、从读取浏览到调用交互,这是一次信息组织的范式变化。

所以,不要觉得“Rewriting the Web for AI”是前端视觉重构。它更像是给 Web 内容建立了一套面向 AI 的“数据协议”,决定哪些信息被保留、哪些被丢弃、按什么结构组织、暴露哪些调用能力。

3. 为什么大量 Web 内容对 AI 不友好

只看概念不够,必须落到真实场景。我用三类最常见的问题来说明。

第一类是噪音型页面。一个普通的文章页,里面往往有页头导航、面包屑、侧边栏推荐、文章标签、作者介绍、评论列表,还有一堆跟踪脚本产生的元素。如果把这些内容全部交给 AI,模型的上下文窗口很快就占满了,而且重要信息可能被淹没。做过 RAG 的人都知道,检索召回时如果抓进大量无用文本,回答质量会明显下降。

第二类是动态渲染型页面。很多现代网站用前端框架,页面内容是 JavaScript 动态渲染出来的。常规爬虫拿到的是空壳 HTML,正文根本不在里面。要让 AI 拿到有效内容,必须在爬取阶段做浏览器渲染,或者要求后端提供预渲染版本。这已经不是“清洗”问题,而是“渲染链路”问题。

第三类是低语义型页面。大量老系统用 div 堆出整个页面,所有元素都是<div><span>,没有<article><main><aside>这些语义化标签。AI 想通过标签推断内容层级时,一无所获。

下面用一小段 HTML 对比说明。

<!-- 低语义结构:AI 很难判断什么是正文 --> <div class="wrap"> <div class="header"> <div class="nav">首页</div> <div class="nav">关于</div> </div> <div class="main"> <div class="title">为什么 Web 需要为 AI 重写</div> <div class="desc">本文讨论 Web 语义化对 AI 的影响。</div> <div class="content"> 第一段正文内容…… </div> </div> <div class="side">热门推荐</div> <div class="footer">版权信息</div> </div>
<!-- 语义化结构:AI 更容易理解 --> <header> <nav>首页 / 关于</nav> </header> <main> <article> <h1>为什么 Web 需要为 AI 重写</h1> <p class="summary">本文讨论 Web 语义化对 AI 的影响。</p> <p>第一段正文内容……</p> </article> </main> <aside>热门推荐</aside> <footer>版权信息</footer>

人眼能通过位置和样式判断哪个是正文,但原始 HTML 给 AI 的信号太弱。如果页面再叠加样式、脚本和跟踪代码,AI 能获取的有效信号就更少了。理解这个现状,你就能明白为什么“重写 Web”不是小题大做。

4. 重塑 Web 的三个具体层次

说清楚了现状,接下来拆解解决方案。我认为“为 AI 重写 Web”需要覆盖三个层次,缺一不可。

4.1 内容抽取层:从 HTML 到干净正文

这一层解决“噪音太多”的问题。思路是从 HTML 里识别出主要内容块,剔除导航、页脚、侧边栏等无关模块。经典实现思路类似浏览器的阅读模式:遍历 DOM,通过标签、类名、文本密度和标点符号密度,判断哪些节点更像正文。近些年的规则引擎普遍采用可读性算法和机器学习模型的混合方案。

这一层是基础。没有干净的正文,后面所有工作都无从谈起。实际工程中,内容抽取不只是简单去掉标签,还要处理编码、残缺 HTML、弹窗遮罩、懒加载图片等边界情况。

4.2 语义化与结构化层:让内容自带逻辑

这一层解决“信息层级不明”的问题。目标是把网页内容组织成 AI 更容易读取的结构化格式。

常见做法包括:

  • 使用语义化 HTML 标签,强化主区域划分;
  • 使用 JSON-LD 和 Schema.org 标记文章、作者、发布时间等实体信息;
  • 提供面向 AI 的文本摘要版本,或者标准化的 Markdown 输出;
  • 参考 llms.txt 这类社区倡议思路,为站点建立对 LLM 友好的说明文件;
  • 为 Agent 提供纯文本入口,去掉 JS 和视觉效果影响。

这一层的关键判断是:AI 时代,语义不再只服务 SEO,还要服务模型的召回和引用。如果你的页面有清晰的<article>、JSON-LD 和摘要,AI Agent 在回答用户时,会更容易准确引用你的内容。

4.3 协议与服务层:从浏览变成调用

第三层解决“只能看不能操作”的问题。过去的 Web 是以链接导航为核心的,AI Agent 要完成一个任务,往往要模拟人一样多次点击、跳转。这种方式不仅慢,而且容易失败。更高效的方式是,把网页能力暴露成语义化接口,让 Agent 通过工具调用完成操作。

这里要提一下 MCP(Model Context Protocol),它本质上就是一套让 AI Agent 调用外部工具和数据的标准化协议。当网站暴露 MCP 接口后,Agent 不需要解析 HTML,而是直接调用服务获取结构化结果。可以这么理解:传统网页是“给人操作的表单”,MCP 是“给 Agent 调用的 API”。

这三层不是互相替代,而是组合演进:

层次解决的核心问题典型输出核心角色
内容抽取层页面噪音太重干净正文 / Markdown后端、数据工程师
语义化结构化层信息结构不明显语义标签 / JSON-LD / 摘要前端、站长、后端
协议服务层无法程序化操作MCP / API / 可调用工具平台方、Agent 开发者

5. 可落地的实践:做一个网页转 AI 友好内容的最小服务

理论讲完,现在动手。我们用 Python 实现一个最小的“网页转 AI 友好内容”服务。它接收一个 URL,抓取网页,去噪抽取正文,转成结构化 Markdown 和摘要,再通过 HTTP 接口返回。这个服务可以作为 RAG 采集链路或者 Agent 网页读取模块的最小原型。

说明一下:以下代码依赖运行时会自动安装,本文不写死版本号。如果你用的 Python 环境比较新,请以实际安装结果为准。整体思路比具体版本更重要。

5.1 环境准备

建议使用 Python 3.10 以上版本。创建虚拟环境:

mkdir web-for-ai cd web-for-ai python -m venv venv source venv/bin/activate

安装依赖:

pip install fastapi uvicorn requests beautifulsoup4 lxml

四个依赖的分工:

  • fastapiuvicorn提供 HTTP 服务和接口;
  • requests负责抓取网页;
  • beautifulsoup4lxml负责解析 HTML、清洗标签。

5.2 实现内容抽取和重写逻辑

在项目目录下创建processor.py,实现一个简单的正文抽取类。

# 文件路径:web-for-ai/processor.py import re import html from urllib.parse import urljoin import requests from bs4 import BeautifulSoup class AIWebProcessor: """把网页抽取为 AI 友好的 Markdown 结构。""" def __init__(self, timeout=10): self.timeout = timeout self.headers = { "User-Agent": "Mozilla/5.0 (compatible; AIWebProcessor/1.0; educational)" } def fetch(self, url: str) -> str: """抓取网页 HTML,返回文本。""" resp = requests.get(url, headers=self.headers, timeout=self.timeout) resp.raise_for_status() return resp.text def extract_title(self, soup: BeautifulSoup) -> str: """优先取 h1,再取 title 标签。""" h1 = soup.find("h1") if h1 and h1.get_text(strip=True): return h1.get_text(strip=True) title_tag = soup.find("title") return title_tag.get_text(strip=True) if title_tag else "" def extract_main_text(self, soup: BeautifulSoup) -> str: """ 简单策略:优先取 article/main 标签,其次取 body。 """ container = soup.find("article") or soup.find("main") or soup.body or soup # 去掉脚本、样式、导航、页脚、评论等噪音节点 for tag in container.find_all( ["script", "style", "nav", "footer", "aside", "form", "noscript"] ): tag.decompose() lines = [] for element in container.find_all(["h1", "h2", "h3", "h4", "p", "li"]): text = element.get_text(strip=True) if not text: continue lines.append(text) if lines: return "\n\n".join(lines) # 兜底方案:取纯文本并压缩空白 raw_text = container.get_text(separator="\n") cleaned_lines = [line.strip() for line in raw_text.splitlines() if line.strip()] return "\n\n".join(cleaned_lines) def process(self, url: str) -> dict: """完整流程:抓取 -> 解析 -> 结构化。""" page_html = self.fetch(url) soup = BeautifulSoup(page_html, "lxml") title = self.extract_title(soup) content = self.extract_main_text(soup) # 生成行数有限的摘要,便于 Agent 快速判断内容价值 summary_lines = content.split("\n")[:5] summary = "\n".join(summary_lines) # 输出一个简单的、AI 友好的 Markdown 结构 markdown = f"# {title}\n\n{content}\n" return { "url": url, "title": title, "summary": summary, "content": content, "markdown": markdown, "char_count": len(content), }

这个类做的事情不复杂,但已经覆盖了三个关键操作:

  1. 抓取网页并设置合理的 User-Agent;
  2. 优先定位<article><main>,剔除常见噪音节点;
  3. 提取标题和正文,输出 Markdown。

对生产环境来说,你可能还要加入阅读时长估算、关键词提取、章节大纲生成等能力,但最小原型这样已经够了。

5.3 暴露 HTTP 接口

在项目目录下创建main.py

# 文件路径:web-for-ai/main.py from fastapi import FastAPI, HTTPException from pydantic import BaseModel from processor import AIWebProcessor app = FastAPI(title="Web for AI 转换服务") processor = AIWebProcessor() class WebRequest(BaseModel): url: str @app.get("/health") def health(): return {"status": "ok"} @app.post("/ai/article") def to_ai_friendly(req: WebRequest): """输入网页 URL,输出 AI 友好的结构化内容。""" if not req.url.startswith(("http://", "https://")): raise HTTPException(status_code=400, detail="URL 格式不正确") try: result = processor.process(req.url) except Exception as exc: raise HTTPException(status_code=502, detail=str(exc)) return result

这里有一个很重要的安全点:这个服务接收任意 URL,存在 SSRF 风险。实际部署时,不要把服务直接暴露到公网;如果要暴露,必须限制目标域名范围、配置内网地址拦截、增加鉴权和配额控制。下面的最佳实践部分还会展开。

5.4 启动与调用

先启动服务:

uvicorn main:app --reload --port 8000

然后打开新终端调用:

curl -X POST http://127.0.0.1:8000/ai/article \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com/article"}'

返回结果大概是这样的结构(字段按处理器里的定义):

{ "url": "https://example.com/article", "title": "网页标题", "summary": "第一行内容\n第二行内容", "content": "正文全文", "markdown": "# 网页标题\n\n正文全文", "char_count": 1200 }

6. 运行验证与效果观察

拿到上面的返回结果后,先判断三步:

  1. 字段title是否正确提取,如果提取的是站点名而不是文章标题,说明页面没有h1<title>不够准确;
  2. 字段char_count是否合理,如果只有几十个字,大概率是页面是纯 JS 渲染,requests抓不到正文;
  3. 字段markdown的正文是否完整,如果混入大量导航文字,需要调整extract_main_text的噪音标签列表。

如果第二步失败,说明这个页面是动态渲染的,需要换成无头浏览器方案。比如 Playwright 或 Puppeteer,先把页面渲染完成再交给BeautifulSoup做语义清洗。这是工程上最常见的升级路径,尤其是目标站点是大量用 Vue、React 搭建的内容平台时。

如果你接入 RAG 流水线,建议把这个接口当作“文档加载器”,进一步把正文内容按标题层级拆成 chunk,再交给 embedding 模型。拆分的粗细要根据模型上下文窗口和检索粒度来调整,一般控制在 300 到 800 字之间比较稳妥。

7. 常见问题与排查思路

在实践过程中,你大概率会遇到下面这些问题:

问题现象可能原因排查方式解决方案
返回 403 或请求被拦截目标站点有反爬策略,User-Agent 或访问频率被识别查看响应头和状态码信息,确认是否是反爬返回降低请求频率,使用真实浏览器 UA,遵守 robots.txt 和站点条款
char_count很小目标站点是前端 JS 动态渲染,静态请求拿不到正文用 curl 直接看下载的 HTML 里是否有正文改用 Playwright 渲染后抽取
正文混入导航和评论噪音标签列表不完整,页面没有标准 article/main 标签打印抽取后的纯文本,定位噪音来源扩展噪音标签和容器类名,或使用可读性算法库
中文乱码页面编码声明与实际编码不一致检查响应头里的 charset 和 meta 标签使用requestsresp.encoding根据内容指定编码
请求超时目标站点响应慢查看服务日志中的超时时间调大超时时间,或加入重试和熔断机制
服务被内网地址攻击接口接收任意 URL,存在 SSRF 风险检查访问日志中是否出现异常域名增加域名白名单,禁止私网 IP,增加鉴权与限流

这里面最常见的坑有两个。第一个是“抓到了内容但抓错了位置”,等你把 Markdown 喂给模型后才发现答案很偏。第二个是“动态页面问题”,静态请求只能拿到空壳,这在现代前端项目里非常普遍。

8. 最佳实践与工程建议

最后讲几点生产环境里真正重要的工程建议。

8.1 对网站侧:从语义 HTML 开始

如果你的网站是面向内容消费的,改造顺序建议是:

  • <main><article><aside><nav>等语义化标签重构页面结构;
  • 在关键内容区域使用 JSON-LD 标记文章标题、作者、发布时间、摘要和主图;
  • 对 SPA 页面做服务端渲染或预渲染,至少保证基础内容不经 JS 也能读到;
  • 在站点根目录维护一份对 LLM 友好的站点说明文本,让搜索型 Agent 能快速了解站点主题和内容边界。

这些改动的直接收益是:你的内容更容易被 AI 搜索正确引用,被 Agent 推荐给用户。对内容类平台来说,这已经不只是 SEO,而是“AEO”——答案引擎优化。

8.2 对采集侧:合法、限速、去重

写爬虫时,首先检查目标站的 robots.txt 和服务条款,只采集你被允许访问的内容。控制抓取频率,设置合理的重试退避。对采集到的内容做 URL 去重和内容指纹去重,避免重复入库。抓取在线内容用于商业项目前,务必评估版权风险。

8.3 对 AI 侧:清洗、分块、验证

在用大模型处理网页内容时,别把清洗工作全交给模型。前端清洗能去掉的噪音,就不要浪费模型上下文。内容进入知识库前,做好分块和元数据标注,例如来源 URL、发布时间、标题、章节路径。后续检索环节可以根据这些元数据做过滤,提高召回准确率。同时,建议保留原文和清洗后文本的对应关系,出了问题可以回溯。

8.4 安全边界必须落地

凡是接收 URL 的服务,都要当作高权限服务来设计。具体来说:

  • 限制可访问的域名白名单;
  • 过滤私网 IP、环回地址、云元数据地址;
  • 对抓取结果做大小限制,防止超大页面拖垮服务;
  • 增加接口鉴权、调用频率限制、请求超时和熔断;
  • 不要在日志里记录正文内容,只记录 URL、状态和耗时。

8.5 质量监控

生产系统要对抽取质量做人工抽查和自动评估。可以设置每周抽样一批 URL,做一个“正文是否完整、有无残留导航、标题是否正确”的小评测集。模型迭代过程中,这些评测集能帮你判断哪些改动是正向的。

9. 总结与后续学习方向

回到开头的问题。Scrunch 代表的“Rewriting the Web for AI”方向,真正要解决的是信息组织方式的代际切换。Web 以前是给眼睛看的,未来要同时给机器和模型读。这不只是前端工程师的事,也不只是 AI 工程师的事,而是内容生产、前端渲染、后端接口和数据工程共同的改造任务。

对个人开发者来说,最好的切入方式是从一个小页面开始。选一个你常用的内容网站,把它接入上文这个最小服务,看看抽取效果如何;然后给自家网站加上语义化标签和 JSON-LD;最后再考虑把你的网站能力暴露成 Agent 可以调用的接口。每一步都不难,但组合起来,就是一次让 Web 重新适配 AI 的实际落地。

后续值得继续深入的方向包括:MCP 协议如何让 Agent 直接操作网站的某个业务功能;如何用可读性算法提升复杂页面的抽取精度;以及如何把结构化后的内容更好地接入 RAG 和 Agent 工作流。建议你把这篇文章收藏起来,按里面的步骤先把最小服务跑通,再逐步往生产级推进。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询