trafilatura 在相同测试样本上漏掉的标注性模板内容,比 Readability 更少

最后更新于 August 17, 2026
trafilatura 在相同测试样本上漏掉的标注性模板内容,比 Readability 更少
AI 摘要
trafilatura 是一个无需浏览器的 Python 内容提取工具。在本文使用的标注样本上,它唯一的同 HTML 抽取质量对手是 Mozilla Readability:trafilatura 在 17 个标注为模板内容的单元里漏出了 1 个,而 Readability 漏出了 5 个。带浏览器的工具这里只在部署占用的语境中出现,并没有在这些页面上做质量测试。它的核心工作是提取正文内容:输入 HTML,输出面向文章的文本和元数据,同时通过启发式规则过滤掉页面装饰元素。它可以把结果序列化为 JSON 以及其他格式,但不会生成你自定义的行结构,也不会输出重复的、带类型的目录记录。

trafilatura 是一款不依赖浏览器的 Python 内容提取器。在本文标注的测试样本里,它唯一能在同类 HTML 提取质量上正面硬刚的对手是 Mozilla Readability:trafilatura 在 17 个已标注样式噪音单元里漏掉了 1 个,而 Readability 漏掉了 5 个。基于浏览器的工具只在部署体积对比里出现,本文并没有在这些页面上对它们做质量测试。

trafilatura title and 3/3 paragraphs retained

它的核心工作就是提取正文:输入 HTML,输出面向文章的文本和元数据,并通过启发式规则过滤页面外围内容。它可以把结果序列化为 JSON 和其他格式,但不会生成你自定义的表格字段结构,也不会输出重复的、带类型的目录记录。本文测试的是 2.1.0 版本。它不会执行 JavaScript,而和 Readability 的对比也说明,清理力度和内容保留之间本来就有取舍,并不是某一方全面碾压另一方。

trafilatura 的定位,以及它明确不做什么

trafilatura 自称是一个用于在网页上采集文本和元数据的 Python 与命令行工具——涵盖爬取、抓取、提取——并支持输出 CSV、JSON、HTML、Markdown、TXT 或 XML。这个说法范围很大,但真正发挥作用的部分其实更窄、更直接:它接收一个 HTML 文档,然后返回正文内容,把页面边角的杂项信息剥离掉。

System diagram: Where trafilatura fits, and what it refuses to do

先建立一个心智模型,因为它能解释它的优势,也能解释它的边界。大多数你拿去抓网页的爬虫都依赖选择器——你会告诉它“抓取 class 为 product-price 的元素”,它就把那个位置上的内容返回给你。trafilatura 的工作方式正好相反。它会通读整份文档,然后通过内容启发式规则判断哪些区块是真正的文章,哪些只是页面噪音,而不是依赖你写好的选择器。这也是它不需要为每个站点单独配置清洗规则的原因。与此同时,这也正是它无法直接给你结构化目录的原因:它没有 schema,没有类型化行数据,只有“这里是有意义的文本”。它是提取器,不是你按字段点选的解析器。

它也不需要单独下载浏览器运行时。依赖树里包含像 lxml 这样的跨平台 wheel,因此“无需浏览器下载”不应被误解为只用源码安装,或者完全不含本地二进制组件。

安装体验:依赖体积小,不需要浏览器安装

在 Python 3.14 的全新虚拟环境里执行 pip install trafilatura 时,共安装了 17 个包;根据 pip-install-trafilatura.log,记录到的最大 wheel 是 lxml,大小 8.6 MB。整个过程不需要额外安装浏览器,也不需要安装后再跑浏览器初始化命令。

横向比较一下规模:同一研究基线里的 Scrapling 套件为了让抓取器正常工作,前后执行了四次单独的 pip 安装命令,最后装了 26 个包,其中有两个是 42.2 MB 的 Playwright driver wheel(tools/scrapling/artifacts/logs/pip-install-scrapling.log)——这还没算浏览器二进制文件的下载。Crawlee 套件中,单独下载 Chromium 的体积约为 81.7 MiB(tools/crawlee/research-materials.md)。这些工具承担的任务更重,所以这不是能力上的公平较量;这里只是反映你的磁盘和 CI 缓存会看到什么。另一个好消息是,我拿到的 pip 版本就是 2.1.0,也等于当前发布版,因此下面的数据没有“你测的是旧版本”的时间偏差问题。

实测:提取器实际返回了什么

trafilatura boilerplate cleanup

我用两类样本去测它:一类是它擅长的场景,一类是它的边界场景,原始输出都保存在benchmark 仓库里。文章测试样本最让我信服。

我取了一个本地文章样本,在真实正文外面包了一层噪音:登录提示、“Subscribe” 弹窗、导航链接、版权页脚——这些都是朴素爬虫很容易一并抓下来的典型页面杂项。trafilatura 返回了标题 + 3/3 段正文,而且所有这些噪音标记——Login、Subscribe、Copyright——都没有出现在结果里。除了正文文本,它还正确提取了页面元数据里的作者和日期。完整结果分别保存在 .txt.md.json 中,路径是 results/local_article.json

同一份 HTML 保存成了纯文本、Markdown 和 JSON。文章并没有证明这三种格式是一次调用同时产出的;它们只是同一条提取路径的不同序列化方式。这里的 JSON 包装的是提取出的文本和元数据,不是你自定义的重复记录集合。

下面把第一次运行的结果放在一起,方便你直接核对,而不是只听我说:

测试样本返回内容耗时证据
本地文章,外层包有导航 / 登录 / 订阅 / 版权内容标题 + 3/3 段正文,零噪音区块泄漏,作者为 Thunderbit Research Lab,日期为 2026-07-090.007 秒local_article.json
本地产品目录12 个商品名称及其 12 个价格,以扁平文本形式返回,0 条结构化记录,478 个字符0.064 秒local_catalog_extraction.txt
返回 HTTP 500 的页面fetch_url 返回 None,没有抛出异常30.012 秒local_failure_500.json
Books to Scrape 商品页(公开页面)1,324 个字符的干净文本,以及对应的 Markdown 版本0.753 秒public_books_product.txt / .md

以上每一行都来自 trafilatura 套件里的 artifacts/raw/trafilatura-test-summary.json——trafilatura 2.1.0、Python 3.14、macOS arm64、单机单次运行。请把这些时间看作观测值,而不是正式基准测试成绩。

在那个 500 错误样本上,fetch_url 大约在 30 秒后返回了 None,而附近的本地接口却很快就返回了。这个运行结果只能说明它有延迟,不能说明内部到底是重试/退避、固定超时,还是走了别的内部路径。本文没有验证 fetch_url 是否支持逐次调用的超时参数;已有证据表明,更可控的做法是使用你自己掌控的客户端先把页面拿下来,再把 HTML 传给 trafilatura。

trafilatura catalog text-only boundary

同一组测试也暴露出三个边界。

首先,也是最关键的:trafilatura 是内容提取器,不是结构化爬虫。 我把它用在一个产品目录样本上。它返回了全部 12 个商品名称——以文本形式——以及恰好 0 条结构化记录(按 results/local_catalog_extraction.txt 统计,共 478 个字符的扁平文本)。价格也都回来了,从 $18.00$51.00,每个价格都单独放在对应商品名下方的独立行里。你想要的内容都在输出里,但没有任何一项是字段。如果你需要 [{name, price, rating}, …] 这种结构,那它就是错的工具,怎么配都不会变——这是设计选择,不是 bug。

trafilatura no JavaScript render boundary

第二:它不会渲染 JavaScript。 它只处理静态 HTML。把它丢到客户端渲染页面上,你拿到的只是 JS 执行前服务器已经发出来的内容,而那通常并不是什么有用的信息。如果你的目标站点大量依赖 JS,就得配一个渲染器;trafilatura 不负责那一半。

第三,关于我自己的证据还有一个说明:第一次公开页面的提取测试用的是产品描述块,而不是真正的新闻文章,因为公开沙盒里没有新闻页面。上面的文章清理结果来自一个受控的本地样本。我相信它——因为噪音剥离得非常明确——但我不愿意把产品页包装成“新闻级提取”的证据,所以研究包里把这部分标成了一个开放缺口。2026-07-14 的后续运行把这个缺口补上了,结果就在下一节。

真实页面的噪音清理核验

trafilatura boilerplate labels removed

两张真实页面只抓取一次,保存为离线样本,并附上 SHA-256 哈希,然后在断网状态下重新运行。没有记录耗时,也没有人工标注的真值。这是一次真实页面的噪音清理核验,不是准确度评分。

真实文章样本原始 HTML提取正文正文/原文页面杂项标记移除数标题日期主机名作者站点名
Wikipedia,“Web scraping”230,049 字节26,673 字节0.1164/42005-09-17wikipedia.orgnullnull
Wikinews,“7th Heaven”(归档页)79,716 字节2,200 字节0.0285/52005-11-29wikinews.orgnullnull

这两行都来自 artifacts/results/trafilatura-fidelity-summary.json。检查的标记包括 “Jump to content”、“Privacy policy”、“Powered by MediaWiki”、“This page was last edited”,以及 Wikinews 页面上的 “free news source”——这些都被成功剔除,在两页上都没有漏出来。

正文/原文比值衡量的是压缩程度,不是准确率;被遗漏的文章内容没有单独评分。这两张 MediaWiki 模板上的 authorsitename 都是 null,而上面的本地受控样本则提供了作者信息。这是测试中观察到的 MediaWiki 特定缺失,不代表它整体的署名提取能力差。提取到的日期按返回值如实记录,未与真值再做比对。

两个提取器、同一份 HTML 字节、一个评分脚本

System diagram: Two extractors, the same HTML bytes, one scoring script

在这个研究基线里,只有一份针对 trafilatura 的同测试床对比,而这份对比并不是 trafilatura 自己构建的。真正构建它的是 mozilla-readability 套件,把它作为对照组:22 个手工标注样本中,每个文本块都被标记为 ARTICLE 或 BOILERPLATE,而且每个词都有唯一的标记 token,因此提取出的词能精确映射回唯一一个标注区块。两个工具拿到的 HTML 字节完全相同。Readability 运行在 jsdom 29.1.1 和 Node v22.22.3 上;trafilatura 则使用自己的解析器。

指标(微平均,内容保真集)trafilatura 2.1.0@mozilla/readability 0.6.0证据
文章单元恢复数40/4040/40comparison.json
泄漏的噪音单元数1/175/17comparison.json
污染输出的噪音 token 数341comparison.json
Token 精度0.9390.902comparison.json
Token F10.9690.948comparison.json
非散文召回率,f6_nonprose 样本7/88/8comparison.json
超短文章,f3_short_120 的 F10.5710.800comparison.json

来源是这个研究基线里的 tools/mozilla-readability/artifacts/raw/comparison.json——内容保真集共 11 个样本,40 个文章单元,17 个噪音单元。这些都是故意偏向对抗性场景的合成样本,所以应该把它们看作机制展示,而不是对真实语料库的排名。

两个工具都不是万能的,差异才是最值得关注的部分。trafilatura 更“干净”——只泄漏了 1 个区块,而 Readability 泄漏了 5 个;污染 token 也只有 3 个,而 Readability 有 41 个。这就是“干净文章文本”的精确率那一半,它决定了你的 LLM 上下文窗口会不会被侧栏链接塞满。但 Readability 也保留了 trafilatura 丢掉的内容:在非散文样本上,trafilatura 丢掉了一个 <figcaption>,而 Readability 保留了它;在一篇非常短的文章上,trafilatura 只有 0.571,而 Readability 达到了 0.800。激进清理是有代价的,不是白赚的。如果你的语料里有很多短文、图注和表格密集页面,这个取舍可能反而对你不利。

如何把这个对比变成你的选型测试

先明确你的流水线里,哪类错误代价更高。如果页面杂项会吃掉下游 token,或者污染搜索结果,那么噪音单元泄漏数和污染 token 数就应该赋予更高权重。如果不能接受图注、短文或非散文块被删掉,那么就该更重视按页面形态衡量的内容召回率。共享样本集能把这种取舍显性化,但它不会替你决定新闻档案库、文档语料库或检索流水线该怎么加权。

更广泛的压力测试背景可以看十个库的内存与畸形 HTML 对比

做对比实验时,最好从保存好的 HTML 开始,而不是直接抓线上 URL,这样两个提取器拿到的字节才完全一致。样本应包含普通长文、短通知、图注密集页面、表格或代码密集文档,以及你实际要接入的每个发布源模板。在运行工具之前,先标注少量必须保留的内容单元和已知的页面杂项区块。然后分别统计空输出、必需单元召回、非目标单元泄漏,以及元数据字段。单一的总“质量分”很可能掩盖真正重要的失败模式。

同时也要验证下游对输出的契约。trafilatura 的 JSON 可以携带提取内容和元数据,但 JSON 序列化并不等于你定义好的类型化行结构。对于文章文本,应该检查最小正文长度和必要标记,而不是只要非空就算过。对于元数据,要区分“缺失”和“值错误”,并保留来源 URL 和提取版本,这样以后才能重放漏检案例。

抓取环节也应该单独测试。前面提到的 30 秒本地失败现象针对的是 fetch_url,不是针对你已经拿到 HTML 之后的提取过程,而且它内部具体机制并未被证实。如果你在意超时、重试、登录认证或代理策略,就用一个你能控制行为的客户端,记录最终响应字节,再把这些字节交给提取器。这样可以把采集失败和内容选择失败分开,也让对比更容易复现。

最后,要在目标平台上评估部署属性。在 Python 3.14 环境里安装 17 个包且无需单独浏览器,确实是优势,但这并不能说明吞吐、内存增长、各架构 wheel 可用性,或者并发工作线程下的行为。本文证明的是它在和 Readability 对比时有一个有价值的精确率/保留率机制;是否适合生产,还得看你的语料和运行环境测试。

如果你想看一个外部交叉验证,而不是只看这个基线自己的结果,可以参考 trafilatura 的官方评估页以及公开的 ScrapingHub article-extraction-benchmark。这两个来源都表明,它在大约 181 个真实页面上的 word-F1 表现优于 readability-lxml,方向与上面的表格一致。很多引用这个基准测试的文章会跳过一个细节:广为流传的 trafilatura F1(约 0.945)对应的是更早的 0.5.1 版本,而不是本文测试的 2.1.0。

优缺点

优点:

  • 在共享样本集上,比 Readability 更少泄漏被标注为噪音的内容:17 个区块里只漏了 1 个,而 Readability 漏了 5 个。
  • 在本地样本上正确提取了作者和日期;在两张真实文章页面上则正确提取了标题、日期和主机名。
  • 同一份 HTML 可序列化为文本、Markdown 或 JSON。
  • 只需安装 17 个包,不需要额外浏览器运行时。
  • 失败时表现安静:fetch_url 遇到 HTTP 500 时返回 None,不会抛异常。
  • 测试版本就是最新版本(2.1.0),不存在版本漂移问题。
  • 采用 Apache-2.0 许可证,宽松且适合商业使用。

缺点:

  • 不是结构化爬虫:目录测试只返回了 12 个名称和 12 个价格的文本,0 条类型化记录。没有 schema,也没有字段。
  • 不支持 JavaScript 渲染——只处理静态 HTML;如果页面是客户端渲染的,就需要单独配一个渲染器。
  • 在两张真实的 MediaWiki 页面上,authorsitename 都是 null,因此署名提取并不是稳妥保证的。
  • 清理过于激进有代价:它丢掉了 Readability 保留的 <figcaption>,而在超短文章上只拿到 0.571,对比 Readability 的 0.800。
  • 那次安静返回的 500 错误耗时 30.012 秒;如果你关心截止时间,就该用你可控的抓取器。
  • 内置的抓取 / sitemap 爬虫以及 CSV/XML 输出格式在这次测试中没有覆盖,因此我不对它们下结论。

适合谁,不适合谁

trafilatura 面向的是文章型正文提取。如果你要从静态 HTML 里构建文本语料、可读性档案或 NLP 输入,而且能接受启发式清理,它是一个值得考虑的候选。共享样本对比显示,它比 Readability 更少泄漏噪音内容,而 Readability 在短文本和非散文场景中保留得更多。

如果你真正需要的是结构化提取——比如带价格的商品行、类型化记录、key: value 字段——那就跳过它,因为它给你的是文本,不是表格(目录测试里虽然拿回了 12 个名称和 12 个价格,但 0 条记录)。如果目标页面的内容是在浏览器里渲染出来的,而你又不想额外接一个渲染器,那也不适合,因为 trafilatura 只读静态 HTML,读完就停。要是你的语料大多是短摘要、图片图注和表格密集页面,也要三思:在标注样本上,这正是它清理开始伤到真实内容的地方(超短文章 F1 只有 0.571,还丢了一个 <figcaption>)。工具要配任务:需要完整文章文本可以,用它;需要结构化 JSON、JS 页面或 100 字以内的短条目,就另找方案。

替代方案,以及 Thunderbit 的位置

trafilatura 是一个 Apache-2.0 的自托管库,没有按次收费;但计算资源、带宽、抓取、监控和维护都仍由使用方承担。它能处理你提供的 HTML 里的文章型内容提取,但不负责浏览器执行,也不负责你自定义的重复行 schema。

如果你想看同样六个提取器在同一组样本上的结果,可以参考六个库的提取对比

托管服务则可以把采集、渲染和 schema 构建都放到供应商边界之后。我们开发 Thunderbit,但没有拿它跑这些样本,所以本文无法给出质量、渲染、延迟、反爬或成本方面的对比。选择的关键在于:你是要自己托管、可控的 HTML 到内容提取,还是要一个托管式的采集与结构化提取边界。

相关基准评测还包括:完整的开源爬虫对比Crawl4AI 的浏览器驱动 Markdown 评测,以及 Firecrawl 的自托管 Markdown 评测

试用 Thunderbit 进行网页数据提取

结论

如果你的任务是从静态 HTML 中提取文章正文,并且最在意的是屏蔽被标注为噪音的内容,那么 trafilatura 值得考虑。在共享样本上,它只漏掉了 1 个标注噪音单元,而 Readability 漏掉了 5 个。不过,这个优势是以超短文本和非散文样本上的更低保留率换来的,所以最终应由你的语料形态来决定。

它不会执行 JavaScript,也不会输出你自定义的重复行。对那两张 MediaWiki 页面来说,authorsitename 都是 null,这是模板范围内的观察结果。Readability 保留了 trafilatura 丢掉的图注,并且在标记为 f3_short_120 的样本上得分更高;可见证据支持的是“在超短样本上 F1 更低”,并不支持字符数之类的说法,也不支持“输出被弄坏了”这种结论。

试用 Thunderbit 进行网页数据提取 Get Started Free

常见问题

trafilatura 会返回什么样的结构? 它可以把提取内容和元数据序列化为 JSON、Markdown、文本、HTML、XML 或 CSV。这些是结构化序列化,但不是你自定义的重复行 schema,例如商品名称、价格和评分。目录样本返回的是扁平内容,而不是类型化行数据。

trafilatura 能把产品目录抓成结构化行吗? 不能。它是内容提取器,不是结构化爬虫。在目录样本上,它确实返回了全部 12 个商品名称的扁平文本,但 0 条结构化记录——名称虽然在输出里,但不是字段。如果你需要 name/price/rating 这类类型化记录,应该改用基于选择器的解析器,或者基于 schema 的提取 API。

trafilatura 支持 JavaScript 渲染吗? 不支持。它只处理静态 HTML。把它用于客户端渲染页面时,你拿到的只是 JS 执行前服务器发回来的内容,而那通常并不是你想要的内容。如果目标站点大量依赖 JS,请配一个单独的渲染器。

trafilatura 安装起来麻烦吗? 在测试用的 Python 3.14 虚拟环境里,安装过程拉取了 17 个包,也不需要单独的浏览器运行时。记录到的最大 wheel 是 lxml,体积 8.6 MB。另外,单次本地 500 调用返回 None 花了 30.012 秒;如果你需要可验证的截止时间,就用你自己掌控的 HTTP 客户端。

trafilatura 可以免费用于商业用途吗? 可以,它采用 Apache-2.0 许可证,宽松且适合商业使用。和往常一样,在基于它开发之前,最好先到仓库确认最新许可证状态。

Ke
Ke
Thunderbit 首席技术官 | 高级数据科学家与机器学习专家 Ke Shen 拥有近十年的机器学习和数据科学经验,毕业于哥伦比亚大学,曾任 Walmart Labs 高级数据科学家。他在 Python、R、Java 和统计学方面拥有深厚且备受同行认可的专业能力,并分享如何将复杂的 AI 算法从理论落地到生产级架构的实战经验。
目录
Thunderbit · AI 网页数据代理

一键 内提取任意页面数据

深受 250,000+ 用户信赖
提供免费方案
从网页到表格
描述你的需求——Thunderbit 的 AI 代理会帮你抓取并导出到 Excel、Google Sheets、Airtable 或 Notion。可免费开始。
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week