wechat_msg_crawler/CLAUDE.md
2026-05-06 14:31:10 +08:00

3.9 KiB
Raw Permalink Blame History

wechat-cli 项目

项目概述

基于本地微信数据库的 CLI 查询工具支持会话、消息、联系人、群成员等查询。AI-first 设计,输出结构化 JSON。

技术栈

  • Python 3.10+, Click, pycryptodome, zstandard
  • SQLCipher 4 解密AES-256-CBC
  • npm 分发 + PyInstaller 打包

目录结构

  • wechat_cli/ — 主 CLI 包commands/, core/, keys/, output/
  • skills/ — Claude Code skillsexport-chat, tencent-cos-upload
  • collector/ — 群聊消息自动采集器
  • collect_chats.py — 采集器入口脚本
  • npm/ — npm 分发包

群聊采集器collector/

自动采集微信群聊消息的子系统:

  • collector/config.py — 配置管理MySQL、COS、扫描策略、回溯补录
  • collector/storage.py — MySQL 存储层wechat_group_message 表)
  • collector/wechat_adapter.py — 封装 wechat_cli.core 的适配层,包含 XML 元信息提取
  • collector/scanner.py — 优先级队列扫描调度 + COS 媒体上传
  • collector/backfill.py — 媒体回溯补录watchdog 实时监听 + 定时兜底扫描)

关键约定

  • wechat-cli 是只读工具,不修改微信数据
  • 群聊通过 @chatroom 后缀识别
  • 消息可跨多个 message_N.db 文件
  • DBCache 使用 mtime 机制缓存解密副本到 /tmp/wechat_cli_cache/
  • 采集器独立维护状态,不干扰 ~/.wechat-cli/last_check.json
  • 非文本消息(文件/视频/链接等)从 XML 中提取元信息存入 content 字段,不依赖本地文件下载
  • 群聊消息 content_raw 格式为 wxid:\n<xml>,解析 XML 时需先剥离发送者前缀
  • 聊天记录合并转发app_type=19解析 recorditem XML格式化为多行纯文本
  • 引用/回复消息app_type=57提取 refermsg 中的 svrid 建立消息关联content 格式化为 "正文\n ↳ 回复 发送者: 被引用内容"
  • 数据库通过 svr_msg_id(微信 server_idrefer_msg_svridrefermsg/svrid实现引用消息的关联查询
  • 采集器扫描策略: hot=5s, warm=10s, cold 退避至 60sbackoff 1.2),保证 ≤1min 入库
  • 媒体文件只采集原始可读文件,不做 .dat 解密
    • 图片: 从 temp/RWTemp/YYYY-MM/{md5}.ext 获取(微信查看图片后自动生成)
    • 文件: 从 msg/file/YYYY-MM/filename 获取
    • 视频: 从 msg/video/YYYY-MM/{rawmd5}.mp4 获取,或从 temp/RWTemp/YYYY-MM/{rawmd5}.mp4 获取(直接发送的视频点击预览后缓存于此)
  • 图片消息 content 格式为 [图片] {md5} size:{length}md5 来自消息 XML 的 md5 属性length 为 XML 的 length 属性(= RWTemp 中文件的精确字节数)
  • 重要: XML md5 属性并非文件内容的 md5可能是加密前或服务端 hash文件名也是派生 hash。匹配图片的可靠方式是通过 XML length 与文件大小精确比对md5 仅作为兼容旧记录的回退
  • 视频消息 content 格式为 [视频] {playlength}秒 rawmd5:{rawmd5} size:{rawlength}rawmd5 是本地 mp4 文件名rawlength 是文件字节数。匹配优先 rawmd5文件名精确匹配回退 rawlength 与文件大小比对
  • 注意: 直接发送的视频 rawmd5 和 rawlength 为空/0此时使用 XML 的 length 属性作为 size即缓存到 RWTemp 中文件的精确字节数content 为 [视频] {playlength}秒 size:{length}
  • 语音消息 content 格式为 [语音] {N}秒 size:{length}voicelength 为语音时长ms→s四舍五入length 为语音数据字节数。匹配通过文件大小精确比对
  • 文件消息 content 格式为 {filename} ({human_size}) size:{exact_bytes},匹配优先文件名+精确size双重校验回退纯文件名子串匹配
  • 回溯补录: PollingObserver5s轮询监听 temp/RWTemp + msg/file + msg/video 目录,匹配失败 30s 后自动重试;每 1 分钟定时扫描 media_url=NULL 记录7天内兜底
  • 默认日志级别 DEBUG可通过配置文件 ~/.wechat-cli/collect-chats/config.json 修改