使用 Defuddle CLI(首选)或 web_reader MCP 工具(备用)从网页文章提取干净内容,然后写入结构化的 Obsidian 笔记。
支持平台: 任何公开网页文章(博客、新闻、技术文章等)
输出目录: AI/Articles/
输入: URL
↓
Step 0: 解析URL识别平台 → 确认检查点 (0.5)
↓
Step 1: defuddle 提取内容 (失败→web_reader fallback)
↓
Step 2: 解析 metadata + 估算阅读时间
↓
Step 3: 生成 Obsidian 笔记结构 → 写入前确认 (3.5)
↓
Step 4: 写入 AI/Articles/<title>.md → 清理临时文件
> 外部工具依赖(无需内部 scripts/references):
defuddle CLI — 首选方法,用于提取干净内容(npm install -g defuddle)
web_reader MCP tool — defuddle 失败时的备用方案
import re
from urllib.parse import urlparse
url = "URL"
parsed = urlparse(url)
domain = parsed.netloc.replace('www.', '')
# Categorize source
known_sources = {
'medium.com': 'Medium',
'dev.to': 'DEV Community',
'zhuanlan.zhihu.com': '知乎专栏',
'www.zhihu.com': '知乎',
'mp.weixin.qq.com': '微信公众号',
'juejin.cn': '掘金',
'segmentfault.com': '思否',
'sspai.com': '少数派',
'36kr.com': '36氪',
'arxiv.org': 'arXiv',
'blog.csdn.net': 'CSDN',
}
platform = known_sources.get(domain, domain)
output_dir = "AI/Articles"
print(f"Platform: {platform}, Domain: {domain}")
> 在后续流程中使用 platform 和 output_dir。
> ⚠️ 暂停确认以下信息:
> - 平台识别: {platform} (如果识别有误,告知正确的平台名称)
> - 输出目录: {output_dir}
> - 文件名将保存为: AI/Articles/
>
> 用户确认后继续 Step 1。如有特殊要求(例如修改输出路径、跳过某部分),在此处提出。
首选:Defuddle CLI
# Extract full article as markdown
defuddle parse "URL" --md -o ./.article_content.md 2>&1
# Also extract metadata
defuddle parse "URL" -p title 2>&1
defuddle parse "URL" -p description 2>&1
defuddle parse "URL" -p author 2>&1
defuddle parse "URL" -p date 2>&1
备用 1:web_reader MCP 工具
如果 defuddle 失败(未安装、网络错误、付费内容等),使用 mcp__web_reader__webReader 工具:
URL: <article URL>
return_format: markdown
retain_images: true
然后从工具输出中读取提取的内容。
备用 2:webfetch 工具
如果 web_reader 也失败(如微信公众号等国内平台),使用 webfetch 工具作为最终备用方案:
URL: <article URL>
format: markdown
常见场景:
提取后,读取内容并识别:
import re
# Read extracted content
with open('./.article_content.md', 'r') as f:
content = f.read()
# Extract metadata from defuddle JSON if available, or infer from content
# - title: from defuddle -p title or <h1> in content
# - author: from defuddle -p author or byline in content
# - date: from defuddle -p date or date pattern in content
# - description: from defuddle -p description or first paragraph
# Infer publish date from content
date_match = re.search(r'(\d{4}[-/]\d{2}[-/]\d{2})', content[:2000])
publish_date = date_match.group(1).replace('/', '-') if date_match else ''
# Estimate reading time (Chinese: ~400 chars/min, English: ~200 words/min)
char_count = len(content)
if re.search(r'[\u4e00-\u9fff]', content):
reading_time = max(1, round(char_count / 400))
else:
word_count = len(content.split())
reading_time = max(1, round(word_count / 200))
print(f"Content length: {char_count} chars, Estimated reading time: {reading_time} min")
> 传递到 Step 3: title、author、date、reading_time 将用于 frontmatter。
笔记结构模板:
---
title: <article title>
tags: [<topic1>/<topic2>, e.g. AI/机器学习, 产品/设计, 编程/Rust]
source: <original url>
author: <author name>
date: <YYYY-MM-DD>
reading_time: <N min>
type: 文章笔记
platform: <platform>
---
# <title>
> [!info] 文章信息
> author / reading time / date / [link](URL)
## 核心观点
[1-3 句话概括文章的主要论点或主题]
## [根据文章内容推断的章节标题]
[使用标注、表格、列表的结构化摘要]
## 个人思考
- [ ] 待办事项
## 原文摘录
> [!note]-
> 摘录内容段落一……
>
> 摘录内容段落二……
>
> 摘录内容段落三……
> 内容存储规则: 如果原文超过 20000 字符,不要保存原文——只留下一条注释 > 原文内容过长(N 字符),未保存。可从 原文链接 获取。。小于 20000 字符时,用可折叠标注块嵌入内容,并保持逻辑段落分隔(每个段落用 > 行分隔)。
>
> 内容分段(重要): 原文摘录必须按照内容逻辑分段,而非机械切割。
> - 通读全文,在话题转换处断段(如:新论点提出、举例结束回到主旨、从一种类型切换到另一种类型)
> - 跨段落边界的句子必须合并为完整段落
> - 分段粒度:一般每 1000-2000 字分成一段。每段应是一个完整的论点、叙述单元或话题。
> - 过长且价值较低的部分(如大段代码、冗长的数据罗列)可以适当省略,用 [...省略...] 标注
Tags 推断规则:
领域/子领域 格式(如 AI/机器学习、编程/Python、产品/UX)
platform:<平台名> 标签
写入策略:
/.md ,Obsidian 会自动检测文件变化
/ 替换为 _,避免路径问题
> ⚠️ 最终确认:
> 预览上述笔记结构(如有需要可调整 ## 核心观点 的_summary 或 ## 原文摘录 的分段)
> 确认后执行写入。如无需调整,可直接跳过此检查点继续 Step 4。
import os
for f in ['./.article_content.md', './.article_meta.json']:
if os.path.isfile(f):
os.remove(f)
| 错误 | 原因 | 解决方案 |
|-------|-------|---------|
| defuddle: command not found | 未安装 | npm install -g defuddle |
| Empty content extracted | 付费墙 / JS 渲染 | 使用 web_reader MCP 工具备用方案 |
| Content is HTML, not markdown | Defuddle 解析失败 | 使用 web_reader 工具,设置 return_format: markdown |
| Title extraction fails | 页面结构异常 | 手动从 或 标签提取 |
| Chinese encoding garbled | 编码错误 | Defuddle 原生处理 UTF-8;使用 --md 重新运行 |
| WeChat article: only intro extracted | 微信反爬 | 使用 web_reader MCP tool,defuddle 对微信支持较差 |
| WeChat: "utf-8 encoding not supported" | defuddle 编码问题 | 直接使用 webfetch 工具作为备用 |
| summarize 返回空/no model | CLI 内部问题 | 使用 webfetch 工具 |
| Article older than 2019 archive | 页面已下架 | 检查 URL 是否完整,尝试 Internet Archive |
| Very long article (>50000 chars) | 内容过长 | 按 20000 字符规则处理,只保留摘要和摘录 |
| Non-article URL (homepage/profile) | URL 指向非内容页 | 要求用户提供具体文章页 URL |
问题:
utf-8 encoding is not supported
via html, no model(空结果)
解决:
webfetch 工具,指定 format: markdown 成功提取
经验:
URL → 识别平台(基于域名分类)
→ defuddle parse URL --md(首选)
├─ 成功 → 读取内容和元数据 → 继续
├─ 失败 → web_reader MCP tool(备用1)
└─ 失败 → webfetch 工具(备用2,微信公众号必用)
→ 推断阅读时间和元数据
→ 总结 → 写入 AI/Articles/<title>.md → 清理
平台优先级建议:
共 1 个版本