# 2026-08-19 工作日志 ## 企业微信聊天记录导出(完成) **成果**:成功导出 2 个已登录账号的全部聊天记录,共 **2792 条消息、88 个会话**。 **输出文件**(`wxwork_export/` 目录): - `企业微信聊天记录.csv` / `.xlsx` — 全部消息(账号、会话、时间、发送者、消息类型、内容等 12 列) - `会话汇总.csv` / `.xlsx` — 88 个会话的消息数与时间范围 - `聊天记录_1688856770803435.csv`(2756 条)、`聊天记录_1688855555743233.csv`(36 条) - `decrypted/` — 解密后的 SQLite 数据库 **技术要点**: - 企业微信 5.x 用 wxSQLite3 AES-128-CBC 加密(每页 4096B 独立加密,密钥派生 `MD5(raw_key + page_no(LE) + "sAlT")`) - 16 字节原始密钥从 `WXWork.exe` 进程内存提取(内存中 `sAlT` 结构:`[key(16B)] + [page_no(4B LE)] + "sAlT"`) - 已提取 2 个密钥存于 `wxwork_keys.json`:账号 1688856770803435(`db7288a3...`)、1688855555743233(`d18e7f9a...`) - 表名:`message_table`(非 message)、`conversation_table`(非 session)、`user_table`(非 userinfo) - 消息内容为 protobuf 编码,需递归解析 length-delimited 字段 **本轮修复的问题**: 1. `SyntaxWarning: invalid escape sequence '\-'` — 正则字符串中 `''` 提前终止字符串,改为中文引号 `“”‘’` 2. 5 条短文本消息(如"在不")被 `extra_content` 二进制替换 — 兜底条件从 `len(content)<3` 改为 `content.strip()` 为空 3. `?` 前缀残留(protobuf 内部 tag/length 字节 0x3F/0x7A 混入文本)— parse_content 中增加模式 A(`T 残留 T` 去重保留后半)和模式 B(前导 ASCII 残留清理,支持后跟中文标点) **最终质量**:二进制残留 0、?前缀 0、空内容 0、控制字符 0。 **未完成/限制**: - 8 个历史用户目录未解密(旧账号未登录,密钥不在内存)——需用户登录后重新提取密钥 - 部分 `S:` 群聊无名称显示为"群聊 S:xxxx" - 脚本需用 venv python 运行(`pycryptodome`、`openpyxl` 装在 `~/.workbuddy/binaries/python/envs/default/`) ## 桌面应用打包(完成) 将导出能力打包为 Windows 桌面应用 **`dist/企业微信导出助手.exe`**(19MB 单文件,PyInstaller onefile + windowed + 自定义图标)。 **GUI 功能**(`wxwork_gui.py`): - 一键导出全部聊天记录(CSV + Excel,含进度与日志面板) - "重新提取密钥"按钮:扫描企微进程内存提取所有已登录账号密钥并保存到 exe 旁 `wxwork_keys.json` - 每日定时自动导出(时间可设,应用运行期间到点自动触发) - 输出目录可自定义(默认 exe 旁 `wxwork_export/`)、完成后一键打开文件夹 - 配置持久化到 `wxwork_gui_config.json` **技术要点**: - managed Python 3.13 无 tkinter → 改用系统 Python 3.11 建 venv:`C:\Users\pc\.workbuddy\binaries\python\envs\gui311`(继承 tkinter,装 pycryptodome/openpyxl/pyinstaller/pillow) - PyInstaller 打包命令:`pyinstaller --onefile --windowed --name 企业微信导出助手 --icon app_icon.ico wxwork_gui.py` - 路径兼容 onefile:`APP_DIR = sys.executable` 所在目录(frozen 模式),密钥/配置/输出目录都在 exe 旁 - 验证:exe 启动进程存活 ✅;打包环境完整导出(2792 消息 + xlsx 校验 2793 行)✅ - 交付:dist/ 含 exe + wxwork_keys.json(2 个已提取密钥)+ app_icon.png ## 按天/范围导出改造(完成) 用户需求:聊天记录可按"天数"导出(如只导今天)。 **核心脚本 `wxwork_export_final.py` v2.1**: - `export_messages(dbs, out_dir, date_from=None, date_to=None)` — 日期范围过滤(含两端) - CLI:`--days N`(最近 N 天含今天)、`--date YYYY-MM-DD`、`--all`;默认 `--days 1` - 输出:单天 `按天/YYYY-MM-DD_聊天记录.csv`,多天 `按天/YYYY-MM-DD_至_YYYY-MM-DD_聊天记录.csv`,全量在根目录(原结构不变) - 解密缓存:`decrypted/` 下已有解密文件时跳过(二次运行 1 秒,首次 1-2 分钟),`decrypt_with_keys(db_base, out_dir, keys_map, use_cache=True)` - 实测:`--days 1` 今天 0 条正常提示;`--days 2` 正确导出 08-19 的 17 条 **GUI `wxwork_gui.py`**: - 设置卡片新增「导出范围」下拉:只导今天/最近3天/7天/30天/全部历史(`DAYS_OPTIONS=[1,3,7,30,0]`) - 导出按钮文字动态化(`_export_btn_text()`):"立即导出今天的聊天记录" / "最近 N 天" / "全部聊天记录" - `do_export(keys, out_dir, log, days=N)` 计算 date_from/date_to 传给 export_messages;Excel 生成跟随实际 CSV 路径(按天模式在 按天/ 目录生成 xlsx);空范围返回 None 并提示"该时间范围内没有新消息" - 定时自动导出也按所选范围执行;days 持久化到 config - 清理 `_auto_loop` 死代码(`or True: pass`) **打包**:重新 PyInstaller 打包 `dist/企业微信导出助手.exe`(19MB),启动验证 ✅,三种模式(days=2/1/0)打包环境实测通过 ## 数据库导出 (CRM 绑定版, 完成) 用户需求:导出数据入库建表、只导出聊天记录、能否取 unionid 做 CRM 绑定。 **关键发现(unionid)**: - `user_table.unionid` 字段存在且有数据:主账号 386 联系人中 332 个有 unionid(微信外部联系人,`ozynqs...` 开头);内部成员无 unionid 但 `account` 字段是企微 userid - `message_table.sender_id` = `user_table.id` 可关联:2794 条消息中 1746 条(62%)能拿到 unionid - 无 unionid 的消息主要是应用消息(489)/朋友圈(227)/图文链接(133) 等非人工对话 **新脚本 `wxwork_export_db.py`**(复用 wxwork_export_final.py 的 decrypt/parse 逻辑): - 只导出聊天记录:消息表带 `sender_unionid/sender_userid/sender_mobile` 关联列(CRM 绑定键) - 产出 `crm_import/`:`crm_wecom.db`(SQLite 三表:chat_messages/chat_users/chat_conversations,每次重建)、`聊天记录_仅消息.csv`(干净消息 CSV)、`create_tables_mysql.sql`、`create_tables_sqlite.sql` - CLI:`--all` / `--days N` / `--date`;chat_users 总是全量(390 联系人,333 带 unionid) - 实测:全量 2794 条 / 带 unionid 1746 条(62%);CRM 查询示例:高兴亮 669 条、李思佳 111 条 **解析增强(wxwork_export_final.py parse_content)**: - 模式 C:单数字残留前缀剥离(`^[0-9](?=[\u4e00-\u9fff])(?![\u4e00-\u9fff]{0,2}(?:量词表))`),保护 "3月13日" 等合法文本 - 子串去重:meaningful 中互为子串的短文本跳过(`len(t)>=3`),消除 `A | 子串A` 冗余 - 修复效果:拼接冗余 596 → 0 条;`3关于系统...` 残留清理为干净文本