← 返回
未分类

URL-To-Note

将网页文章转换为结构化 Obsidian 笔记。支持 Medium、微信公众号、知乎、DEV.to 等平台。触发词:文章、Article、转笔记、网页转笔记。
Moncy
未分类 community v1.0.0 1 版本 98989.9 Key: 无需
★ 0
Stars
📥 98
下载
💾 0
安装
1
版本
#latest

概述

Article → Obsidian Note

Overview

使用 Defuddle CLI(首选)或 web_reader MCP 工具(备用)从网页文章提取干净内容,然后写入结构化的 Obsidian 笔记。

支持平台: 任何公开网页文章(博客、新闻、技术文章等)

输出目录: AI/Articles/


TL;DR 速查

输入: 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 → 清理临时文件

Prerequisites

> 外部工具依赖(无需内部 scripts/references):

  • defuddle CLI — 首选方法,用于提取干净内容(npm install -g defuddle
  • web_reader MCP tool — defuddle 失败时的备用方案
  • Obsidian vault at working directory — 使用 Write tool 直接写入笔记

Step-by-Step Workflow

0. 解析 URL 并识别来源

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}")

> 在后续流程中使用 platformoutput_dir

0.5. 确认检查点 (Checkpoint)

> ⚠️ 暂停确认以下信息:

> - 平台识别: {platform} (如果识别有误,告知正确的平台名称)

> - 输出目录: {output_dir}

> - 文件名将保存为: AI/Articles/.md</code> </p><p>> </p><p>> 用户确认后继续 Step 1。如有特殊要求(例如修改输出路径、跳过某部分),在此处提出。 </p><h3>1. 提取文章内容 </h3><p><strong>首选:Defuddle CLI</strong> </p><pre><code># 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 </code></pre><p><strong>备用 1:web_reader MCP 工具</strong> </p><p>如果 defuddle 失败(未安装、网络错误、付费内容等),使用 <code>mcp__web_reader__webReader</code> 工具: </p><pre><code>URL: <article URL> return_format: markdown retain_images: true </code></pre><p>然后从工具输出中读取提取的内容。 </p><p><strong>备用 2:webfetch 工具</strong> </p><p>如果 web_reader 也失败(如微信公众号等国内平台),使用 <code>webfetch</code> 工具作为最终备用方案: </p><pre><code>URL: <article URL> format: markdown </code></pre><p><strong>常见场景:</strong> </p><ul><li>微信公众号:优先使用 webfetch(defuddle 支持差) </li><li>知乎/简书:web_reader 效果较好 </li><li>Medium/dev.to:defuddle 通常可用 </li></ul><h3>2. 解析内容和元数据 </h3><p>提取后,读取内容并识别: </p><pre><code>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") </code></pre><p>> <strong>传递到 Step 3:</strong> <code>title</code>、<code>author</code>、<code>date</code>、<code>reading_time</code> 将用于 frontmatter。 </p><h3>3. 创建 Obsidian 笔记 </h3><p><strong>笔记结构模板:</strong> </p><pre><code>--- 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]- > 摘录内容段落一…… > > 摘录内容段落二…… > > 摘录内容段落三…… </code></pre><p>> <strong>内容存储规则:</strong> 如果原文超过 <strong>20000 字符</strong>,不要保存原文——只留下一条注释 <code>> 原文内容过长(N 字符),未保存。可从 <a href="URL" target="_blank" rel="noopener">原文链接</a> 获取。</code>。小于 20000 字符时,用可折叠标注块嵌入内容,并保持<strong>逻辑段落分隔</strong>(每个段落用 <code>></code> 行分隔)。 </p><p>> </p><p>> <strong>内容分段(重要):</strong> 原文摘录必须按照<strong>内容逻辑</strong>分段,而非机械切割。 </p><p>> - 通读全文,在话题转换处断段(如:新论点提出、举例结束回到主旨、从一种类型切换到另一种类型) </p><p>> - 跨段落边界的句子必须合并为完整段落 </p><p>> - <strong>分段粒度</strong>:一般每 1000-2000 字分成一段。每段应是一个完整的论点、叙述单元或话题。 </p><p>> - 过长且价值较低的部分(如大段代码、冗长的数据罗列)可以适当省略,用 <code>[...省略...]</code> 标注 </p><p><strong>Tags 推断规则:</strong> </p><ul><li>从文章标题和首段提取核心主题 </li><li>使用 <code>领域/子领域</code> 格式(如 <code>AI/机器学习</code>、<code>编程/Python</code>、<code>产品/UX</code>) </li><li>通常 1-3 个标签,优先选择更通用的主题标签 </li><li>平台自动作为 <code>platform:<平台名></code> 标签 </li></ul><p><strong>写入策略:</strong> </p><ul><li><strong>默认直接用 Write tool 写入</strong> <code><output_dir>/<title>.md</code>,Obsidian 会自动检测文件变化 </li><li>文件名中的 <code>/</code> 替换为 <code>_</code>,避免路径问题 </li></ul><h3>3.5. 写入前确认 (Checkpoint) </h3><p>> <strong>⚠️ 最终确认:</strong> </p><p>> 预览上述笔记结构(如有需要可调整 <code>## 核心观点</code> 的_summary 或 <code>## 原文摘录</code> 的分段) </p><p>> 确认后执行写入。如无需调整,可直接跳过此检查点继续 Step 4。 </p><h3>4. 清理 </h3><pre><code>import os for f in ['./.article_content.md', './.article_meta.json']: if os.path.isfile(f): os.remove(f) </code></pre><hr><h2>Common Errors </h2><p>| 错误 | 原因 | 解决方案 | </p><p>|-------|-------|---------| </p><p>| <code>defuddle: command not found</code> | 未安装 | <code>npm install -g defuddle</code> | </p><p>| Empty content extracted | 付费墙 / JS 渲染 | 使用 <code>web_reader</code> MCP 工具备用方案 | </p><p>| Content is HTML, not markdown | Defuddle 解析失败 | 使用 <code>web_reader</code> 工具,设置 <code>return_format: markdown</code> | </p><p>| Title extraction fails | 页面结构异常 | 手动从 <code><h1></code> 或 <code><title></code> 标签提取 | </p><p>| Chinese encoding garbled | 编码错误 | Defuddle 原生处理 UTF-8;使用 <code>--md</code> 重新运行 | </p><p>| WeChat article: only intro extracted | 微信反爬 | 使用 <code>web_reader</code> MCP tool,defuddle 对微信支持较差 | </p><p>| WeChat: "utf-8 encoding not supported" | defuddle 编码问题 | 直接使用 <code>webfetch</code> 工具作为备用 | </p><p>| summarize 返回空/no model | CLI 内部问题 | 使用 <code>webfetch</code> 工具 | </p><p>| Article older than 2019 archive | 页面已下架 | 检查 URL 是否完整,尝试 Internet Archive | </p><p>| Very long article (>50000 chars) | 内容过长 | 按 20000 字符规则处理,只保留摘要和摘录 | </p><p>| Non-article URL (homepage/profile) | URL 指向非内容页 | 要求用户提供具体文章页 URL | </p><hr><h2>实际案例总结 </h2><h3>微信公众号文章提取失败 </h3><p><strong>问题:</strong> </p><ul><li>defuddle: <code>utf-8 encoding is not supported</code> </li><li>summarize: 返回 <code>via html, no model</code>(空结果) </li></ul><p><strong>解决:</strong> </p><ul><li>使用 <code>webfetch</code> 工具,指定 <code>format: markdown</code> 成功提取 </li></ul><p><strong>经验:</strong> </p><ul><li>微信公众号是 defuddle 高危平台,直接用 webfetch 更可靠 </li></ul><hr><h2>Quick Reference </h2><pre><code>URL → 识别平台(基于域名分类) → defuddle parse URL --md(首选) ├─ 成功 → 读取内容和元数据 → 继续 ├─ 失败 → web_reader MCP tool(备用1) └─ 失败 → webfetch 工具(备用2,微信公众号必用) → 推断阅读时间和元数据 → 总结 → 写入 AI/Articles/<title>.md → 清理 </code></pre><p><strong>平台优先级建议:</strong> </p><ul><li>微信公众号:直接用 webfetch(备用2) </li><li>知乎/简书:尝试 defuddle → 失败则 web_reader </li><li>Medium/dev.to:defuddle 通常可用 </li></ul></div> </div> </div> <div id="tab-versions" class="detail-content"> <div class="detail-section"> <h2>版本历史</h2> <p style="margin-bottom:12px;font-size:14px;color:#94a3b8;">共 1 个版本</p> <ul class="version-list"> <li> <div> <span class="version-tag">v1.0.0</span> <span style="font-size:13px;color:#64748b;margin-left:8px;">Initial release</span> <span style="font-size:11px;color:#5b6abf;margin-left:8px;background:#eef0ff;padding:1px 8px;border-radius:10px;">当前</span> </div> <div style="font-size:12px;color:#94a3b8;"> 2026-04-14 21:32 安全 安全 </div> </li> </ul> </div> </div> <div id="tab-security" class="detail-content"> <div class="detail-section"> <h2>安全检测</h2> <div class="sec-grid"> <div class="sec-card"> <h4>腾讯云安全 (Keen)</h4> <div class="sec-status sec-safe"> 安全,无风险 </div> <a href="https://tix.qq.com/search/skill?keyword=09348abbaa3b898b9559b0d4e21e42b1" target="_blank">查看报告</a> </div> <div class="sec-card"> <h4>腾讯云安全 (Sanbu)</h4> <div class="sec-status sec-safe"> 安全,无风险 </div> <a href="https://static.cloudsec.tencent.com/html-report-v2/2026/05/26/423215_3d6c94f8139848570acec6ef0821d18c.html?q-sign-algorithm=sha1&q-ak=AKID8JMG1bzBC1dz96qNhssfFftujT1NCoFi&q-sign-time=1781311389%3B1812847389&q-key-time=1781311389%3B1812847389&q-header-list=host&q-url-param-list=&q-signature=33c19b2814d13549a18e9ce9fc831c6f8d6954e4" target="_blank">查看报告</a> </div> </div> </div> </div> <!-- Recommended Skills --> <div style="margin-top:24px;"> <h2 style="font-size:18px;font-weight:600;margin-bottom:16px;">🔗 相关推荐</h2> <div class="rec-grid"> <div class="rec-card"> <span class="badge-cat" style="margin-bottom:8px;display:inline-block;"></span> <h3><a href="/s/jmy004">browser-useV1</a></h3> <div class="rec-owner">user_fe8721be</div> <div class="rec-desc">AI驱动的浏览器自动化 - 用自然语言描述任务,让AI自动控制浏览器完成网页操作。</div> <div class="rec-stats"> <span style="color:#f39c12;">★ 1</span> <span style="color:#5b6abf;">📥 276</span> </div> </div> <div class="rec-card"> <span class="badge-cat" style="margin-bottom:8px;display:inline-block;"></span> <h3><a href="/s/jmy001">bilibili-video-md</a></h3> <div class="rec-owner">user_fe8721be</div> <div class="rec-desc">当用户提供哔哩哔哩(B站)视频链接时使用此技能(URL 包含 bilibili.com/video/ 或 BV 开头加字母数字)。自动化完整流程:从 B 站视频下载音频、使用 Coli ASR(sensevoice 模型)将音频转录为中文文</div> <div class="rec-stats"> <span style="color:#f39c12;">★ 0</span> <span style="color:#5b6abf;">📥 290</span> </div> </div> <div class="rec-card"> <span class="badge-cat" style="margin-bottom:8px;display:inline-block;"></span> <h3><a href="/s/video-to-md">video-to-md</a></h3> <div class="rec-owner">user_fe8721be</div> <div class="rec-desc">视频转文字转换器。 该工具利用 使用 yt-dlp 下载其他网站视频,随后通过 faster-whisper 对音频进行转录。 适用场景: 当你需要将视频内容(B站/YouTube/本地文件)转换为文字稿或字幕时,请使用此工具。</div> <div class="rec-stats"> <span style="color:#f39c12;">★ 0</span> <span style="color:#5b6abf;">📥 154</span> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded',function(){ document.querySelectorAll('.detail-tab').forEach(function(btn){ btn.addEventListener('click',function(e){ var tab = this.getAttribute('data-tab'); document.querySelectorAll('.detail-tab').forEach(function(b){b.classList.remove('active')}); document.querySelectorAll('.detail-content').forEach(function(c){c.classList.remove('active')}); this.classList.add('active'); var el = document.getElementById('tab-'+tab); if(el) el.classList.add('active'); }); }); }); </script> <div class="footer"> <p>Skill工具集 © 2026</p> </div></body> </html>