# WeChat 消息自动点击器 自动点击微信桌面端未读消息中的图片和文件,触发原始文件下载到本地目录。 ## 项目背景 配合另一个信息收集项目使用:信息收集脚本负责将微信消息入库,但图片和文件需要被点击预览后微信才会下载原始文件到本地。本工具自动完成这个"点击"操作。 ## 技术架构 - **语言**: Python 3.11+ - **核心技术**: macOS Accessibility API (AXUIElement) via pyobjc - **目标应用**: 微信桌面端 v4.1.9+ (bundle ID: com.tencent.xinWeChat) - **运行平台**: macOS Sonoma 14+ ### 模块结构 ``` wechat_clicker/ ├── ax_bridge.py # AXUIElement 底层封装(属性读取、鼠标点击、键盘事件、滚动) ├── wechat_ui.py # 微信 UI 导航(聊天列表、消息列表、预览界面元素查找) ├── state_machine.py # UI 状态机(窗口状态检测、恢复、Preview.app 管理) ├── automator.py # 主自动化逻辑(扫描→进入聊天→锚点+箭头导航点击图片→点击文件→循环) ├── human_like.py # 拟人行为(高斯分布延迟、长休息、工作时间) ├── config.py # YAML 配置加载 └── logger_setup.py # 日志配置 ``` ### 关键设计决策 - 聊天列表项为 AXStaticText(无 AXPress),使用 **CGEvent 鼠标坐标点击** - AXValue 位置/尺寸需用 AXValueGetValue 解包 CGPoint/CGSize - 消息类型通过 title 内容判断:`"图片"` → 图片,`"文件\n..."` → 文件 - **图片/文件气泡偏移点击**:AXStaticText 覆盖整行(575px宽),实际气泡仅在左侧 ~80-170px 区域,使用 `click_at_element_offset(x=120, y=height/2)` 命中 - **图片处理(锚点+箭头导航)**:滚到底部 → 找最底部可见图片(锚点)→ 点击锚点进入预览 → 按 i 次左箭头到达第 i 张 → 点"..."→"使用预览打开"→ 关闭 Preview.app → 回到微信 → 再次点击锚点 → 左箭头 i+1 次 → ... 循环直到覆盖 `unread_count + overlap` 张。彻底绕过滚动覆盖、元素可见性、去重等问题 - **锚点稳定性**:连续 3 次失败自动重锚(重新滚到底部 + 重找锚点 + i 归零),最多重锚 2 次;每聊天最多处理 30 张图片(`MAX_IMAGES_PER_CHAT`),防止单聊天垄断处理时间 - 文件处理:直接点击触发下载(不走箭头导航) - **滚动方向**:macOS CGEvent ScrollWheel **负值=向下滚**(看新消息),**正值=向上滚**(看旧消息) - 进入聊天后滚到底部(负值),图片通过箭头导航覆盖历史 - 滚动使用 **kCGEventMouseMoved + ScrollWheel**(不触发点击),避免误点 UI 元素 - "..."按钮搜索限制在预览区域(独立窗口或主窗口 x>200),排除侧边栏 - 可见性检查基于元素**中心点**是否在消息列表可见区域内(30px margin) - 状态检测基于窗口计数 + **AXMinimized 属性**:区分窗口存在但最小化 vs 真正可见 - **窗口恢复策略**:NSRunningApplication.unhide(隐藏)→ AX API 设置 AXMinimized=False(最小化)→ activate(前台);AppleScript 不可靠(微信不支持 miniaturized 属性) ## 使用方法 ```bash # 前置条件 pip install -r requirements.txt # 系统设置 > 隐私与安全 > 辅助功能 → 添加终端/Python # 复制配置 cp config.example.yaml config.yaml # 运行 python main.py # 持续运行 python main.py --once # 单次扫描 python main.py --dry-run # 只扫描不点击 python main.py --dump-ui # 输出 UI 元素树 python main.py --dump-ui --chat "聊天名" # 进入指定聊天 dump 消息元素树(诊断用) python main.py --debug # 详细日志 ``` ## 配置重点 - `config.yaml` 中可设置扫描间隔、延迟范围、白/黑名单、工作时间、媒体类型开关 - `max_chats_per_scan: 0` 表示不限制,处理全部未读聊天(适合大量群聊场景) - 默认只点击图片(`media.click_files: false`, `media.click_videos: false`) - 默认黑名单包含微信系统账号 - 处理完有未读的聊天后立即重扫,不等待 scan interval;只有无未读时才 sleep - 忙时(未读 > 5)自动跳过随机休息 ## 注意事项 - 微信窗口最小化或隐藏时工具会自动恢复(通过 AX API 设置 AXMinimized=False + NSRunningApplication activate) - 运行时会占用微信前台操作 - 建议在专用电脑上运行