Skip to content

Latest commit

 

History

History
311 lines (232 loc) · 18.6 KB

File metadata and controls

311 lines (232 loc) · 18.6 KB

wx-kit 产品需求文档(PRD)

版本:v1.0(第一阶段) 日期:2026-06-06 状态:待评审


1. 一句话定义

wx-kit 是一个微信百宝箱桌面应用。 第一阶段聚焦"文章下载"这一个模块——把微信公众号文章下载为多种格式并在应用内浏览,同时提供一套 CLI 接口,让 AI 大模型能通过 agent skill 直接调用这些能力。

下载只是第一阶段的需求。产品按"多模块容器"组织,为后续工具(如内容分析、批量改写、素材管理等)留出扩展位,但本阶段不预先搭建任何空模块(YAGNI)。


2. 背景与由来

本产品脱胎于一个技术探索原型(x-downloader),该原型验证了微信文章下载的可行性。产品化阶段做三件事:

  1. 砍掉代理模式:原型用 AnyProxy 做全局 HTTPS MITM 拦截 PC 微信流量,安装根证书、自动改系统代理,体验脆弱且有还原风险。直接弃用。
  2. 去掉 Python 边车:原型的爬取逻辑跑在 FastAPI + Playwright + PyInstaller 的独立进程里(PyQt 时代遗留),打包复杂、体积大、有 0.0.0.0 监听等问题。本阶段用纯 Node/Electron 重写,单进程单语言。
  3. 新增 AI 友好的 CLI 接口:核心能力不再只活在 GUI 里,抽到与界面无关的核心层,供 GUI 与 CLI 两个入口共享。

3. 目标与非目标

3.1 目标

  • 用户能基于文章 URL(单个或一次多个)下载文章,自选下载内容。
  • 用户能基于公众号批量爬取并下载其历史文章,自选下载内容。
  • 用户能在应用内浏览已下载的文章(md / html)。
  • AI 大模型能通过 CLI 调用上述下载与爬取能力,获得结构化(JSON)结果。

3.2 非目标(本阶段明确不做)

  • ❌ 代理模式 / 流量拦截 / 证书安装(已弃用)。
  • ❌ 激活、授权、付费门槛系统(第一阶段开箱即用;后续商业化再议)。
  • ❌ 下载以外的"百宝箱"其他工具模块(留架构位,不实现)。
  • ❌ 云端同步、多端、账号体系。
  • ❌ 评论/留言/阅读数等需要额外接口或风险较高的数据抓取(本阶段只做正文、图片、元数据;列表数据来自公众号后台接口)。

4. 用户与使用场景

用户 场景 主要入口
个人创作者 / 研究者 收藏、归档某篇或某些文章,离线阅读 GUI · URL 下载
内容运营 / 分析者 批量归档某个公众号的历史文章,做素材库 GUI · 公众号批量
知识管理用户 在本地统一浏览已归档文章 GUI · 文章库
AI Agent(大模型) 通过 skill 自动下载/爬取文章,拿到 md 与元数据做下游处理 CLI

AI Agent 是一等公民用户。CLI 的输出契约(JSON + 退出码)按"被程序消费"而非"被人阅读"来设计。


5. 功能需求

F1 · URL 下载

  • 输入:一个多行文本框,每行一个微信文章 URL。支持 1 个到多个。
  • 格式可选(多选,至少选一项):
    • 封面图片(cover)
    • Markdown(md)
    • HTML(html,图片本地化的自包含单文件)
    • PDF(pdf)
    • 文章元数据(meta,JSON)
  • 行为:所有 URL 进入统一下载队列,逐条处理。
  • 进度信息(详见 §8.4):
    • 整体进度:已完成 / 总数。
    • 每条状态:等待 / 下载中 / 成功 / 失败(+ 失败原因)。
    • 单条内的阶段提示:抓取正文 → 下载图片 → 转换格式(md/html/pdf)→ 写入入库,让用户清楚卡在哪一步而非只看到"下载中"。
  • 无需登录:URL 下载抓取的是公开文章页,不依赖公众号后台登录。
  • 完成后:每篇文章入库,可在文章库浏览。

F2 · 公众号批量爬取

  • 前置:扫码登录后台
    • 首次使用批量功能时,引导用户用自己的微信公众号扫码登录 mp.weixin.qq.com
    • 登录在应用内的窗口完成,登录成功后捕获并持久化 session(token + cookie)。
    • session 失效时,自动检测并重新引导登录,不让用户面对一句冷冰冰的报错。
  • 搜索公众号:输入公众号名称 → 调后台接口返回候选列表(名称、头像、简介、fakeid)→ 用户选定目标号。
  • 选择爬取范围(二选一):
    • 按数量:最近 N 篇
    • 按日期:起止日期段
  • 格式可选:同 F1(cover / md / html / pdf / meta)。
  • 队列下载
    • 默认串行 + 随机延迟抓取,宁慢勿封(详见 §9 风控)。
    • 进度信息(详见 §8.4):整体进度(已完成 / 总数)、预计剩余耗时、当前正在处理的文章及其阶段;可暂停/取消。
    • 单篇失败不中断整体,记录失败项,支持重试失败项。
  • 断点续传:已下载的文章跳过,不重复下载(按文章唯一标识去重)。

F3 · 文章库与内置阅读器

  • 文章库:列出所有已下载文章,按公众号 / 时间分组。
    • 每条展示:标题、公众号、发布时间、下载时间、已下载的格式标记。
  • 搜索:按文件名 / 标题实时搜索定位文章,可叠加按公众号筛选。
  • 内置阅读器:点击文章在应用内直接渲染正文阅读。
    • md:渲染为排版良好的阅读视图。
    • html:在受控的内嵌视图中展示自包含 HTML。
  • 辅助入口:提供"在文件夹中显示""用系统程序打开""导出/拷贝"等操作,方便用户把文章带走。
  • 文章管理(删除)
    • 删除单篇 / 多选批量删除。
    • 删除时同时清理磁盘文件(整篇文章文件夹)与 library.json 索引,保证库与磁盘一致。
    • 删除为不可逆操作,执行前给确认提示。

F4 · CLI 接口(AI Agent 友好)

CLI 与 GUI 是同一个 Electron 二进制的两种启动模式:检测到命令行子命令即进入无窗口 CLI 模式,执行完打印结果并退出。

输出契约(关键):

  • 结构化结果走 stdout,纯 JSON(agent 直接解析)。
  • 人类可读的进度/日志走 stderr(不污染 stdout 的 JSON)。
  • 退出码0 成功;非 0 表示失败,错误详情同时写入 stdout 的 JSON({ "ok": false, "error": {...} })。

命令集(第一阶段):

命令 作用 关键参数
wx-kit login 打开扫码登录窗口,持久化 session
wx-kit auth-status 查询登录态是否有效 --json
wx-kit search <name> 搜索公众号,返回候选列表(每项含名称、头像、简介、fakeid),由调用方决定选用哪个 --json
wx-kit download 下载一个或多个文章 URL --url <u>(可重复)/ --urls-file <f>--formats cover,md,html,pdf,meta--out <dir>
wx-kit crawl <name> 批量爬取某公众号 --count N--from YYYY-MM-DD --to YYYY-MM-DD--formats ...--out <dir>
wx-kit library list 列出已下载文章 --account <name>--json

Agent 调用约定:

  • crawl / search 需要登录态。若无有效 session,命令以结构化错误返回(error.code = "AUTH_REQUIRED"),提示需先执行 wx-kit login(交互式扫码,需人工参与一次)。
  • download 不需要登录。
  • 所有耗时命令在 stderr 输出进度,stdout 仅在结束时输出一次最终 JSON。

后续可在 CLI 之上再封装 MCP server,但本阶段先交付 CLI(对 agent skill 最通用、最简单)。

F5 · 设置

  • 默认下载目录、默认勾选格式。
  • 批量爬取的抓取节流参数(延迟区间、单次步长)——给高级用户,提供合理默认值。
  • 登录态管理(查看登录状态、退出登录/清除 session)。
  • 文章库根目录位置(可配置;默认在用户文档目录下,用户可改到任意目录)。

6. 下载格式规格

每篇文章下载后,落到独立文件夹(见 §7)。各格式定义:

格式 文件 说明
封面图 cover.<ext> 文章封面原图,按原始格式保存
Markdown content.md 正文经 HTML→MD 转换(turndown);图片引用指向本地 images/;文首附 frontmatter 元数据
HTML index.html 清洗后的自包含单文件:内联样式、图片本地化(指向 images/ 或 base64),断网可读
PDF content.pdf 由清洗后的页面经 Electron printToPDF 生成
元数据 meta.json 标题、作者/公众号、发布时间、原文 URL、摘要、封面 URL、下载时间、已生成格式等
图片 images/ 正文图片本地化副本(md/html 选中时生成)

图片本地化:选中 md 或 html 时,正文图片一律下载到本地并改写引用路径,保证离线可读、可整体拷走。


7. 数据与存储结构

  • 文件系统存储 + 一个 JSON 索引(library.json),不引入数据库(第一阶段够用,且便于用户直接操作文件)。
  • 每篇文章一个自包含文件夹,方便整体拷贝/迁移。
<文章库根目录>/
├─ library.json                 # 索引:所有文章的元信息 + 路径 + 已下载格式
└─ <公众号名>/
   └─ <日期>_<标题>/            # 单篇文章自包含文件夹
      ├─ index.html             # (选中 html 时)
      ├─ content.md             # (选中 md 时)
      ├─ content.pdf            # (选中 pdf 时)
      ├─ cover.jpg              # (选中 cover 时)
      ├─ images/                # 正文图片本地化
      └─ meta.json              # 元数据
  • 文章库根目录默认在用户文档目录下(如 ~/Documents/wx-kit/ 或同级),且可在设置中配置到任意目录。
  • session、设置等应用数据存于 Electron userData 目录,与文章库分离。
  • 文件夹/文件命名做非法字符清洗与去重处理。

8. 技术架构

8.1 总体:单进程 Electron,分层

┌─────────────────────────────────────────────────────────┐
│  入口层(两种启动模式,同一二进制)                          │
│  ┌──────────────────┐        ┌──────────────────────┐    │
│  │ GUI 模式          │        │ CLI 模式              │    │
│  │ React 渲染进程     │        │ 命令解析 + JSON 输出   │    │
│  │ ↕ IPC             │        │ ↕ 直接调用            │    │
│  └────────┬─────────┘        └──────────┬───────────┘    │
│           └───────────────┬─────────────┘                 │
│                           ▼                                │
│  核心层 core(UI 无关,被两个入口共享)                      │
│  ┌──────────────┬──────────────┬──────────────┐          │
│  │ article-     │ mp-crawler    │ exporter     │          │
│  │ fetcher      │ mp-auth       │ library      │          │
│  │              │ download-queue│              │          │
│  └──────────────┴──────────────┴──────────────┘          │
│                           ▼                                │
│  平台能力(Electron 提供):printToPDF · 登录/抓取用的       │
│  BrowserWindow · 文件系统                                  │
└─────────────────────────────────────────────────────────┘
                            ▼
                      本地文件系统(§7)

核心层不依赖 React/渲染层;GUI 经 IPC 调它,CLI 经命令行调它。二者同在 Electron 主进程,因此都能复用 printToPDF 与 BrowserWindow 登录能力——这是选择"统一 Electron 二进制"的根本原因:一套能力、零额外重型依赖。

8.2 核心模块职责边界

模块 职责 依赖
mp-auth 用 BrowserWindow 承载扫码登录,捕获 token+cookie,持久化 session,失效检测与重登引导 Electron BrowserWindow、文件系统
mp-crawler 公众号名→fakeid 搜索;按数量/日期范围翻 appmsg 历史列表;内置节流与失效重登 mp-auth、HTTP 客户端
article-fetcher 给定文章 URL 抓 HTML,cheerio 清洗正文,下载并本地化图片 HTTP 客户端、cheerio
exporter 把清洗后的文章导出为 cover/md/html/pdf/meta turndown、Electron printToPDF、文件系统
download-queue 串行队列、随机延迟、进度上报、失败记录与重试、去重 上述模块
library 维护 library.json 索引,提供列表 / 按文件名·标题搜索 / 删除(连带清理磁盘文件夹) 文件系统

每个模块单一职责、接口清晰、可独立测试。

8.3 技术栈

  • 运行时/打包:Electron + electron-builder(mac dmg/zip、win nsis/zip)
  • 渲染层:React + TypeScript + Vite;UI 组件沿用 Ant Design 体系(与原型一致,降低迁移成本)+ Tailwind
  • 抓取/解析:axios、cheerio
  • 格式转换:turndown(HTML→MD)、Electron printToPDF(PDF)
  • CLI:轻量命令解析(如 commander),主进程入口分流
  • 无 Python、无独立 chromium 依赖、无数据库

8.4 进度上报机制

download-queue 是唯一的进度来源,对外发射统一的进度事件,两个入口各自渲染,逻辑不重复:

  • 进度事件包含:整体(已完成 / 总数、预计剩余耗时)、当前文章(标题)、当前阶段(抓取 / 下载图片 / 转换 md·html·pdf / 入库)、单条结果(成功 / 失败 + 原因)。
  • GUI:经 IPC 把进度事件推到渲染层,实时刷新队列 UI 与进度条。
  • CLI:把进度事件格式化写入 stderr(人类可读),stdout 仅在命令结束时输出一次最终 JSON 汇总(含每条成败),保证 agent 解析不被进度污染。

9. 关键约束与风控

微信公众号后台接口有频率限制,抓取过快会触发风控甚至封号。这是产品稳定性的头号约束。

  • 节流优先于并发:批量爬取默认串行,请求间插入随机延迟(默认值给保守区间,可在设置调整)。瓶颈是限速不是带宽,并发无意义。
  • 退避:遇到风控信号(接口返回频控错误)时自动退避、降速,并在 UI/CLI 明确告知,而非静默失败或一味重试。
  • session 失效:检测到失效立即引导重新登录(GUI 弹登录窗 / CLI 返回 AUTH_REQUIRED),不让用户/agent 面对裸报错。
  • 去重续传:已下载文章跳过,崩溃/中断后可继续。
  • 反馈引导行动:所有失败态都给"下一步怎么办",不只报告问题。

10. 非功能需求

  • 体验:用户触碰到的每一层要丝滑——能自动化的不让用户做(如系统自动管理 session、自动去重);反馈引导行动;渐进式展示(先给核心选项,高级参数收进设置)。
  • 跨平台:以 macOS 为主要开发/验证平台(开发者在 mac),构建产物覆盖 macOS 与 Windows。
  • 性能:CLI 单次命令在 Electron 运行时下额外启动开销控制在亚秒级;URL 下载单篇在正常网络下数秒内完成(不含限速等待)。
  • 可扩展:核心层模块化,为"百宝箱"后续工具预留接入方式,但本阶段不实现空模块。
  • 可观测:保留运行日志,便于排查抓取失败。

11. 阶段划分(建议)

第一阶段交付以下里程碑(具体拆分在后续实现计划中细化):

  1. M1 核心层 + URL 下载(CLI 优先):article-fetcher + exporter + download-queue + library + wx-kit download CLI 跑通五种格式。
  2. M2 GUI 接入 URL 下载 + 文章库 + 内置阅读器:F1、F3。
  3. M3 登录 + 公众号批量:mp-auth + mp-crawler + wx-kit login/search/crawl,GUI 批量页。
  4. M4 打包与跨平台验证:electron-builder 出包,mac/win 验证,CLI 二进制可被 agent skill 调用。

12. 风险与开放问题

说明 处置
微信接口变更 后台 appmsg 接口/登录流程可能变动,导致爬取失效 抓取逻辑集中在 mp-crawler,便于快速适配;加清晰的失败上报
风控/封号 高频抓取风险 默认保守节流 + 退避(§9);文档明确告知用户风险
CLI 登录交互 扫码登录天然需要人工一次 login 命令交互完成;crawl 在无 session 时返回 AUTH_REQUIRED 引导
文章页结构差异 不同文章 HTML 结构不一,清洗可能漏内容 fetcher 做容错;保留原始 HTML 兜底
PDF 渲染保真 printToPDF 对复杂排版可能有偏差 第一阶段以"可读、完整"为准,不追求像素级还原

已决议(原开放问题):

  • search 返回候选列表,由调用方决定选用哪个(不自动取最匹配项)。
  • 文章库根目录默认在用户文档目录下,且可配置到任意目录。

13. 验收标准

  • GUI 中粘贴多行 URL,勾选任意格式组合,能正确下载并入库。
  • GUI 中扫码登录后台后,搜索公众号、按数量或日期范围批量下载成功,失败项可重试。
  • 文章库能列出、按文件名/标题搜索、在内置阅读器中打开 md/html。
  • 删除文章(单篇/批量)能同时清理磁盘文件夹与索引,且有确认提示。
  • 下载过程(URL 与批量)实时展示整体进度、当前文章与所处阶段;CLI 在 stderr 输出进度、stdout 输出最终 JSON。
  • wx-kit download --url ... --formats md,pdf 输出合法 JSON,文件正确生成,退出码正确。
  • wx-kit crawl <name> --count 10 --formats md 在已登录时成功;未登录时返回 AUTH_REQUIRED
  • 无 Python 运行时、无独立 chromium、无数据库依赖;构建产物在 mac 与 win 可运行。
  • 批量爬取默认串行节流,触发频控时能退避并给出明确提示。

评审通过后,进入实现计划(implementation plan)阶段。