微信文章收藏——Week1 脚本设计文档
目标:一个命令,URL 进,Markdown 出,存入 Obsidian vault。
使用方式(目标体验)
# 从微信复制文章链接后,终端执行:
python wechat_save.py "https://mp.weixin.qq.com/s/xxxx"
# 输出:
# ✅ 抓取成功:《为什么说微信是知识黑洞》
# ✅ AI 摘要完成(3句话 + 5个标签)
# ✅ 已保存至:~/0PostNote/shine-box/wiki/raw/微信/为什么说微信是知识黑洞.md
文件结构
wechat_save.py ← 主脚本
config.py ← 配置(vault路径、Claude API Key)
requirements.txt ← 依赖包
output/ ← 暂存(正式落入 vault 前检查用)
输出 Markdown 格式
---
title: 为什么说微信是知识黑洞
source: https://mp.weixin.qq.com/s/xxxx
author: 公众号名称
date_saved: 2026-08-20
date_published: 2026-08-18
tags:
- 微信
- 知识管理
- 信息焦虑
- 产品设计
- 内容平台
category: 科技/产品
status: unread
---
# 为什么说微信是知识黑洞
> **AI 摘要:** 微信公众号虽然是中国最大的内容平台,但其收藏功能极为简陋,缺乏搜索和分类能力。大量用户每天阅读但无法沉淀知识,形成"读了即忘"的恶性循环。作者认为知识管理工具与内容消费平台的本质矛盾是根本原因,并提出了解决方案。
> **关键词:** `微信` `知识管理` `信息焦虑` `产品设计` `内容平台`
---
[原文内容]
...
脚本代码结构
# wechat_save.py
import requests
import re
import json
from bs4 import BeautifulSoup
from pathlib import Path
from datetime import datetime
import anthropic # Claude API
# ── 配置 ──────────────────────────────────────────
VAULT_PATH = Path("~/0PostNote/shine-box/wiki/raw/微信").expanduser()
CLAUDE_API_KEY = "your_key_here"
# ── Step 1:抓取文章 ───────────────────────────────
def fetch_article(url: str) -> dict:
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
}
resp = requests.get(url, headers=headers, timeout=10)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
title = soup.find("h1", class_="rich_media_title")
author = soup.find("span", class_="rich_media_meta_nickname")
content = soup.find("div", id="js_content")
pub_time = soup.find("em", id="publish_time")
return {
"title": title.text.strip() if title else "无标题",
"author": author.text.strip() if author else "未知",
"content": content.get_text("\n", strip=True) if content else "",
"pub_time": pub_time.text.strip() if pub_time else "",
"url": url,
}
# ── Step 2:Claude AI 摘要 ─────────────────────────
def ai_summarize(article: dict) -> dict:
client = anthropic.Anthropic(api_key=CLAUDE_API_KEY)
prompt = build_summarize_prompt(article["title"], article["content"])
message = client.messages.create(
model="claude-opus-4-5",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}]
)
raw = message.content[0].text
return parse_ai_response(raw)
# ── Step 3:写入 Markdown ─────────────────────────
def save_to_vault(article: dict, ai: dict):
VAULT_PATH.mkdir(parents=True, exist_ok=True)
safe_title = re.sub(r'[\\/:*?"<>|]', '', article["title"])[:50]
filename = f"{datetime.now().strftime('%Y%m%d')}-{safe_title}.md"
filepath = VAULT_PATH / filename
content = build_markdown(article, ai)
filepath.write_text(content, encoding="utf-8")
print(f"✅ 已保存至:{filepath}")
return filepath
# ── 入口 ─────────────────────────────────────────
if __name__ == "__main__":
import sys
url = sys.argv[1]
print(f"⏳ 抓取中:{url}")
article = fetch_article(url)
print(f"✅ 抓取成功:《{article['title']}》")
print("⏳ AI 摘要中...")
ai = ai_summarize(article)
print(f"✅ 摘要完成:{ai['summary'][:50]}...")
save_to_vault(article, ai)
核心:Claude Prompt 设计
System Prompt
你是一个专业的知识管理助手,负责处理微信公众号文章。
你的任务是:提取关键信息,生成结构化摘要,方便用户日后回顾。
输出必须是合法的 JSON,不要包含任何额外文字。
User Prompt 模板
def build_summarize_prompt(title: str, content: str) -> str:
# 内容过长时截断,避免超出 token 限制
truncated = content[:3000] if len(content) > 3000 else content
return f"""
请分析以下微信公众号文章,返回 JSON 格式的结构化信息。
文章标题:{title}
文章内容:
{truncated}
请返回如下 JSON(严格格式,不要有多余文字):
{{
"summary": "用3句话概括文章核心观点,每句不超过30字",
"tags": ["标签1", "标签2", "标签3", "标签4", "标签5"],
"category": "从以下选择最合适的一个:投资/科技/产品/个人成长/生活/育儿/历史/其他",
"key_points": [
"核心要点1(一句话)",
"核心要点2(一句话)",
"核心要点3(一句话)"
],
"worth_keeping": true,
"reason": "一句话说明为什么值得保存(或不值得)"
}}
"""
AI 响应解析
def parse_ai_response(raw: str) -> dict:
try:
# 提取 JSON(防止 Claude 返回多余文字)
match = re.search(r'\{.*\}', raw, re.DOTALL)
if match:
return json.loads(match.group())
except Exception:
pass
# 降级:返回空结构
return {
"summary": "(AI 摘要失败,请手动填写)",
"tags": [],
"category": "其他",
"key_points": [],
"worth_keeping": True,
"reason": ""
}
最终 Markdown 生成
def build_markdown(article: dict, ai: dict) -> str:
tags_yaml = "\n".join(f" - {t}" for t in ai.get("tags", []))
key_points = "\n".join(f"- {p}" for p in ai.get("key_points", []))
return f"""---
title: {article['title']}
source: {article['url']}
author: {article['author']}
date_saved: {datetime.now().strftime('%Y-%m-%d')}
date_published: {article['pub_time']}
tags:
{tags_yaml}
category: {ai.get('category', '其他')}
worth_keeping: {str(ai.get('worth_keeping', True)).lower()}
status: unread
---
# {article['title']}
> **AI 摘要:** {ai.get('summary', '')}
**关键要点:**
{key_points}
**来源:** [{article['author']}]({article['url']})
---
{article['content']}
"""
依赖安装
pip install requests beautifulsoup4 anthropic
已知边界情况
| 情况 | 处理方式 |
|---|---|
| 需关注才能查看的文章 | 报错提示"文章需要关注公众号" |
| 文章已删除 | requests 返回 200 但内容为空,检测后提示 |
| 内容过长(>10000字) | 截取前 3000 字给 AI,全文仍保存 |
| 标题含特殊字符 | 正则清洗后作为文件名 |
| 网络超时 | timeout=10,失败后提示重试 |
Week1 验收标准
See Also
- 微信公众号文章收藏整理工具.md — 产品整体构想
- ../../工具/ClaudeCode/多Agent协作技巧.md — Claude API 使用背景
Updated: 2026-08-20