news 2026/8/25 18:46:46

动手实测 Defuddle:拆解 Obsidian 创始人的网页内容提取引擎

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
动手实测 Defuddle:拆解 Obsidian 创始人的网页内容提取引擎

动手实测 Defuddle:拆解 Obsidian 创始人的网页内容提取引擎

本文所有内容均基于对 GitHub 源码的阅读和实际命令行测试,无任何厂家供稿或转载。

从一次需求说起

上周在做一个知识库抓取工具时,需要把网页正文提取出来转成 Markdown。用了 Mozilla 的 Readability.js,发现 GitHub 上一些用 React 渲染的页面它提取不全,数学公式直接丢了,脚注也乱。

翻了一圈替代方案,发现了 Defuddle。它来自 Obsidian 创始人 Steph Ango,GitHub 9K+ Star,npm 包周下载量持续增长。但市面上的介绍文章大多只讲「是什么」,我决定直接拉源码看它到底怎么工作。


安装与第一印象

npminstall-gdefuddle# 或者用 npx 免安装npx defuddle parse https://stephango.com/saw--markdown

跑完第一行输出,干净到让我怀疑是不是只输出了个摘要:

When I learned to use a table saw, my teacher impressed upon me that the machine wants to cut fingers. Fear the saw! ...

143 个单词,没有导航栏、没有页脚、没有广告,正文精准提取。90ms跑完。

源码拆解:它到底怎么做的?

拉下源码,src/目录结构非常清晰:

src/ ├── defuddle.ts # 主入口 ├── standardize.ts # HTML 标准化 ├── metadata.ts # 元数据提取 ├── markdown.ts # Markdown 转换 ├── fetch.ts # 远程抓取 ├── frontmatter.ts # YAML 前言 ├── removals/ # 清除管道 │ ├── scoring.ts # 评分算法(核心) │ ├── selectors.ts # 选择器匹配 │ ├── hidden.ts # 隐藏元素检测 │ ├── small-images.ts # 小图片过滤 │ └── content-patterns.ts ├── elements/ # 元素标准化 │ ├── headings.ts # 标题处理 │ ├── code.ts # 代码块 │ ├── footnotes.ts # 脚注 │ ├── images.ts # 图片 │ ├── math.ts # 数学公式 │ └── callouts.ts # 标注/提示框 └── extractors/ # 22+ 站点专用提取器 ├── bilibili.ts ├── github.ts ├── wikipedia.ts ├── reddit.ts ├── twitter.ts └── ...

核心:评分算法

我打开removals/scoring.ts看评分逻辑,核心思路不复杂:

  1. 遍历 DOM 树,为每个容器节点打分
  2. 内容密度加分<p>标签越多、文本越长,分数越高
  3. 链接密度惩罚:统计区域内<a>标签的文本占比,超过阈值大幅扣分——导航栏、标签页就是被这个筛掉的
  4. 聚类取最高:相邻的高分区域聚合成候选块,取分数最高的作为正文

通过--debug模式,可以看到完整的评分过程:

{"element":"ARTICLE","selector":"html > body > main > article","score":478}

实测中,<article>标签的评分最高(478 分),<body>次之(459 分),<main>再次(422 分)。Defuddle 会选择最高的<article>作为正文区域。

清除管道

源码中removals/目录定义了 6 个清除阶段的管道:

阶段文件名作用
1. 精确选择器selectors.ts匹配已知广告/社交按钮的 CSS 选择器,精确删除
2. 模糊选择器selectors.ts匹配关键词含 “ad”、“sidebar”、“footer” 等元素
3. 隐藏元素hidden.ts移除display:nonevisibility:hidden元素
4. 低分内容scoring.ts评分低于阈值的块被移除
5. 小图片small-images.ts移除图标、追踪像素(< 32px 图片)
6. 内容模式content-patterns.ts匹配评论区、相关文章等常见模式

实测抓取 stephango.com 的日志显示:35 个元素通过精确选择器删除,1 个隐藏元素被移除,整个过程 90ms。

与 Readability.js 的关键差异

读源码时发现几个设计决策上的差异:

1. 更宽容,移除更少的不确定元素
Readability 倾向于「宁可错删,不可保留」,而 Defuddle 的策略是「宁可保留,不可错删」。这对内容提取来说是一个更安全的选择——多余的内容可以后续处理,但丢失的内容无法恢复。

2. 利用移动端样式辅助判断
源码里hidden.ts不仅检查display:none,还利用移动端响应式布局中隐藏的元素来推断哪些部分是「次要的」。

3. 22+ 站点专用提取器
这是 Readability 没有的设计。src/extractors/目录下为每个平台写了专门的提取逻辑:

提取器目标平台特殊处理
bilibili.tsB 站视频信息、弹幕元数据
github.tsGitHubREADME、Issues、PR 正文
wikipedia.ts维基百科信息框、目录结构
reddit.tsReddit帖子+评论层级
twitter.tsX/Twitter推文线程、媒体卡片
medium.tsMedium自定义嵌入元素
chatgpt.tsChatGPT对话格式
claude.tsClaude对话格式

4. 异步降级
当本地 HTML 提取不到内容(比如客户端渲染的 SPA),parseAsync()会尝试从第三方 API 获取内容。默认开启,可通过useAsync: false关闭。

三套构建产物

源码里package.json定义了三个入口:

{"exports":{".":"dist/index.js",// Core:仅 HTML,无依赖"./full":"dist/index.full.js",// Full:含 Markdown + 数学公式"./node":"dist/node.js"// Node:含服务端 DOM 解析}}
产物大小能力
Core~20KB仅 HTML 输出,无外部依赖
Full~40KBHTML + Markdown + 数学公式转换
Node~45KB服务端 DOM + 完整能力

这种按需加载的设计,让浏览器插件(Core)和笔记工具(Full)用同一套代码但不同体积。

实测对比

我拿同一篇博客(stephango.com/saw)测试了三种提取方式:

指标Readability.jsDefuddle
提取字数139143
处理时间112ms90ms
丢失内容
元数据提取标题+作者标题+作者+描述+域名+语言+字数
调试模式有,输出完整决策链
数学公式丢失转换为 MathML
脚注格式混乱标准化<sup>引用

当然,这只是一个简单页面的测试。对于复杂页面(评论区、多级导航、JavaScript 渲染),差异会更明显。

适用场景

翻完源码、跑完测试后,我认为 Defuddle 最适合以下场景:

1. Obsidian Web Clipper 用户
这是 Defuddle 的原生场景——剪藏网页到 Obsidian 笔记库,保留 Markdown 格式和 YAML 前言。

2. RSS 全文抓取
很多 RSS 源只有摘要,用 Defuddle 在服务端提取全文后再推送,比直接抓取原始 HTML 干净得多。

3. AI 上下文准备
把网页喂给 LLM 之前,先用 Defuddle 剔除广告和导航,节省 token。实测 143 词的正文,原始 HTML 大约 3000+ token,Defuddle 处理后只剩下 1/10。

4. 知识库构建
自建知识库时,Defuddle 的--frontmatter选项可以直接输出带 YAML 元数据的 Markdown,天然适合 Obsidian、Logseq 等工具。

不足

根据源码阅读和测试,几个尚未解决的问题:

  • 中英文混合页面:对中文内容的评分不如英文准确(链接密度惩罚对中文链接效果差)
  • SPA 页面:依赖parseAsync()的第三方 API 降级,但 API 可用性不稳定
  • 评论区提取:默认会移除评论区,即使includeReplies: true,部分平台(如 Disqus)仍无法提取

总结

Defuddle 不是 Readability 的简单复刻,而是一次从 Obsidian 生态需求出发的重新设计。它的核心优势在于:

  • 管道式清除架构,每个阶段独立可调
  • 22+ 站点专用提取器,覆盖主流平台
  • 三套构建产物,按场景选择体积
  • 完整的调试模式,开发者可以精确追踪每次提取的决策过程

如果你正在做网页内容提取相关的工作,无论是笔记工具、RSS 阅读器还是 AI 数据管道,Defuddle 都值得认真评估。


项目地址:https://github.com/kepano/defuddle
npm 包:npm install defuddle
CLI 使用:npx defuddle parse <url> --markdown

本文所有结论均基于对 GitHub 源码(commit 最新)的分析和实际命令行测试。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/25 18:40:59

AI Agent驱动开发实战:基于Cursor Origin的智能代码托管与自动化工作流

如果你最近关注AI编程工具&#xff0c;可能会发现一个现象&#xff1a;很多开发者开始讨论“AI Agent”和“代码托管平台”的结合。这背后其实是一个关键趋势&#xff1a; AI正在从“代码补全助手”向“自主执行任务的智能体&#xff08;Agent&#xff09;”演进&#xff0c;而…

作者头像 李华
网站建设 2026/8/25 18:40:28

电商和本地服务先别急,但GEO的埋伏已经开始了

# 电商与本地服务的 GEO 埋伏&#xff1a;不抢首发&#xff0c;但要做好结构化准备 电商与本地服务的搜索场景以「商品/商家 位置」为主&#xff0c;GEO 入口目前在通用 AI 引擎中渗透还不够&#xff0c;但趋势已经明确。本文给出低投入埋伏、待入口成熟的策略。一、为什么现在…

作者头像 李华
网站建设 2026/8/25 18:37:33

浏览器文章转视频工作台:零安装、一站式图文转视频技术方案

你是不是也遇到过这样的场景&#xff1a;想快速把一篇技术文章、产品说明或者学习笔记变成视频&#xff0c;却卡在了复杂的剪辑软件、繁琐的素材准备和漫长的渲染等待上&#xff1f;对于开发者、内容创作者和知识分享者来说&#xff0c;从图文到视频的转化&#xff0c;往往意味…

作者头像 李华
网站建设 2026/8/25 18:37:00

LeetCode 405题解析:位运算实现整数转十六进制(含负数处理)

在算法面试和日常编程中&#xff0c;进制转换是一个基础且高频的考点。很多同学在处理负数时容易卡壳&#xff0c;或者对位运算的理解不够深入&#xff0c;导致代码冗长或出错。本文将围绕LeetCode 第405题「数字转换为十六进制数」&#xff0c;从问题本质、位运算技巧到完整代…

作者头像 李华
网站建设 2026/8/25 18:32:53

AI面试教练如何解析GitHub项目提升技术面试表现

1. 项目概述&#xff1a;当GitHub项目遇上AI面试教练去年帮学弟修改简历时发现一个现象&#xff1a;90%的技术求职者会把GitHub项目写在简历上&#xff0c;但当被问到"这个项目解决了什么问题"、"你负责哪些核心模块"时&#xff0c;往往语焉不详。这正是我…

作者头像 李华