# Wx Favorites Report

> 微信收藏可视化：从加密的微信本地数据库端到端解密、解析，生成交互式 HTML 可视化报告。 触发词：/wx-favorites-report、微信收藏可视化、收藏报告、收藏分析 支持输入：加密/解密后的 Favorite.db（SQLite）或 CSV/JSON 导出文件

- Skill: `zhuyansen/wx-favorites-report` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add zhuyansen/wx-favorites-report`
- Raw SKILL.md: https://api.skillmd.com/api/skills/zhuyansen/wx-favorites-report/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: zhuyansen (https://skillmd.com/u/zhuyansen)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/zhuyansen/wx-favorites-report

---


# 微信收藏可视化 Skill

将微信收藏数据（加密 Favorite.db）端到端解密、解析、生成交互式 HTML 可视化报告。

## 执行流程

### Step 1: 确认数据源

询问用户是否已有解密后的 Favorite.db。

- **已有解密 DB** → 跳到 Step 3
- **未解密** → 进入 Step 2 密钥提取 + 解密

### Step 2: 密钥提取与数据库解密（macOS）

#### 2a. 准备签名副本
```bash
# 复制微信到桌面并去掉 Hardened Runtime
cp -R /Applications/WeChat.app ~/Desktop/WeChat.app
codesign --force --deep --sign - ~/Desktop/WeChat.app
```

#### 2b. 安装 frida
```bash
pip3 install frida frida-tools
```

#### 2c. 提取密钥
```bash
# 关闭原版微信，从桌面副本启动
killall WeChat 2>/dev/null; sleep 2

# 用 frida spawn 模式启动微信并 hook PBKDF2
PYTHONPATH=$(python3 -c "import site; print(site.getusersitepackages())") python3 << 'PYEOF'
import frida, time

JS_CODE = """
function buf2hex(buffer) {
    var a = new Uint8Array(buffer); var h = '';
    for (var i = 0; i < a.length; i++) h += ('0' + a[i].toString(16)).slice(-2);
    return h;
}
var found = false;
Process.enumerateModules().forEach(function(m) {
    if (found) return;
    m.enumerateExports().forEach(function(exp) {
        if (found) return;
        if (exp.name === "CCKeyDerivationPBKDF") {
            found = true;
            send("[*] Hook installed on " + m.name);
            Interceptor.attach(exp.address, {
                onEnter: function(args) {
                    this.pwLen = args[2].toInt32();
                    this.saltLen = args[4].toInt32();
                    this.rounds = args[6].toInt32();
                    this.pw = args[1]; this.salt = args[3];
                    this.dk = args[7]; this.dkLen = args[8].toInt32();
                },
                onLeave: function(retval) {
                    if (this.pwLen < 4 || this.pwLen > 256) return;
                    if (this.saltLen < 4 || this.saltLen > 64) return;
                    var saltHex = buf2hex(this.salt.readByteArray(this.saltLen));
                    var dkHex = buf2hex(this.dk.readByteArray(this.dkLen));
                    var pwHex = buf2hex(this.pw.readByteArray(this.pwLen));
                    send("[PBKDF2] r=" + this.rounds + " salt=" + saltHex);
                    var f = new File("/tmp/wechat_frida_keys.log", "a");
                    f.write("rounds=" + this.rounds + "\\npw=" + pwHex + "\\nsalt=" + saltHex + "\\ndk=" + dkHex + "\\n\\n");
                    f.flush(); f.close();
                }
            });
        }
    });
});
if (!found) send("[!] CCKeyDerivationPBKDF not found");
"""

device = frida.get_local_device()
pid = device.spawn(["/Users/" + __import__('os').getenv('USER') + "/Desktop/WeChat.app/Contents/MacOS/WeChat"])
session = device.attach(pid)
script = session.create_script(JS_CODE)
script.on("message", lambda msg, data: print(msg.get("payload", msg)))
script.load()
device.resume(pid)
print("WeChat running. Login → open Favorites → wait 60s...")
time.sleep(120)
session.detach()
print("Done. Check /tmp/wechat_frida_keys.log")
PYEOF
```

**重要**：微信启动后必须登录并打开「收藏」页面，触发 favorite.db 的密钥加载。

#### 2d. 匹配密钥并解密

解析 frida 日志，找到 favorite.db 对应的 enc_key（通过 salt 匹配），然后用 Python 解密：

```python
# 核心解密逻辑（内置在 parse_favorites.py 的上游）
import hashlib, hmac, struct
from Crypto.Cipher import AES

# enc_key = 从 frida 日志中 256000 轮 PBKDF2 输出匹配 DB salt 的 dk
# 逐页 AES-256-CBC 解密，HMAC-SHA512 校验
```

安装依赖：`pip3 install pycryptodome`

### Step 3: 解析数据

```bash
python3 ~/.claude/skills/wechat-favorites-viz/scripts/parse_favorites.py \
  --input "<解密后的 favorite.db 路径>" \
  --output "<输出目录>/data.json"
```

兼容 WeChat 3.x (FavItems) 和 4.x (fav_db_item) 表结构。

### Step 4: 生成可视化报告

```bash
python3 ~/.claude/skills/wechat-favorites-viz/scripts/generate_report.py \
  --input "<输出目录>/data.json" \
  --output "<输出目录>/report.html"
```

### Step 5: 预览

```bash
# 推荐用 http server（file:// 下部分交互可能受限）
cd <输出目录> && python3 -m http.server 8765 &
open http://localhost:8765/report.html
```

## 报告功能

| 区域 | 内容 |
|------|------|
| 统计卡片 | 总数、时间跨度、日均收藏、最忙日 |
| 亮点发现 | 最爱来源、主力类型 |
| 月度趋势 | 折线 + 面积图 |
| 类型分布 | 甜甜圈图 |
| 来源 Top15 | 水平柱状图 |
| 活跃热力图 | 星期 × 小时 |
| 时段分布 | 小时 / 星期柱状图 |
| 词云 | 标题 + 描述提取 |
| 标签云 | 微信收藏标签 |
| **收藏浏览** | 按类型筛选 + 按标签筛选 + 搜索 + 排序 + 分页 |
| **详情弹窗** | 点击卡片展开完整内容、链接、来源、标签 |

## 收藏类型

| Type | 含义 | 解析字段 |
|------|------|----------|
| 1 | 文本 | desc |
| 2 | 图片 | datafmt + fullsize |
| 4 | 视频 | datatitle + datadesc |
| 5 | 文章/链接 | pagetitle + pagedesc + link + pagethumb_url |
| 8 | 文件 | datatitle + datafmt + fullsize |
| 14 | 聊天记录 | datalist → 逐条 datadesc 拼接 |
| 其他 | 位置/笔记/小程序等 | 通用 title + desc 回退 |

## 技术依赖

- Python 3.9+ 标准库（sqlite3, json, re, html, collections, datetime）
- PyCryptodome（仅解密步骤需要：`pip3 install pycryptodome`）
- frida（仅密钥提取步骤需要：`pip3 install frida frida-tools`）
- ECharts 5.x + echarts-wordcloud 2.x（CDN 内联，无需安装）

## 输出文件

```
<输出目录>/
├── data.json      # 解析后的结构化数据
└── report.html    # 单文件可视化报告（可直接分享）
```

## 已知限制

- 图片/视频/文件的原始内容存储在微信 CDN（加密内部格式），本地缓存也加密，无法在报告中直接预览
- 文章缩略图来自微信公众号 CDN，需联网加载
- 密钥提取需要 macOS，frida 需要 ad-hoc 签名的微信副本

