7.9 KiB
7.9 KiB
项目规划:WeChat 消息自动点击器
项目目标
创建一个长期稳定运行的自动化工具,自动点击微信桌面端中未读消息的图片和文件,触发微信下载原始文件到本地目录,配合信息收集系统完成数据入库流程。
项目状态
已完成 (v0.1.0 - 2026/04/22)
- 项目结构搭建
- 配置系统(YAML 配置文件、默认值、白/黑名单)
- AXUIElement 底层封装(ax_bridge.py)
- 微信 UI 导航(wechat_ui.py)— 聊天列表解析、消息类型分类
- UI 状态机(state_machine.py)— 基于窗口计数的状态检测与恢复
- 拟人行为引擎(human_like.py)— 高斯分布延迟、长休息、工作时间
- 主自动化逻辑(automator.py)— 完整扫描-点击-关闭循环
- 入口脚本(main.py)— 参数解析、信号处理
- 调试工具(--dump-ui, --dry-run)
v0.2.0 修复与增强 (2026/04/22)
- 修复: 聊天项点击失败 — AXStaticText 无 AXPress 动作,改用 CGEvent 鼠标坐标点击
- 修复: AXValue 位置解包 — get_position/get_size 改用 AXValueGetValue 正确提取 CGPoint/CGSize
- 新增: 消息列表滚动 — 进入聊天后向上滚动 5 轮,加载更多历史媒体消息
- 新增: 图片"使用预览打开"流程 — 点击大图 → 点"..." → "使用预览打开" → 关闭 Preview.app,确保原始文件保存到本地
- 新增: 文件直接点击下载 — 点击文件气泡触发微信下载
- 新增: Preview.app 管理 — state_machine 添加检测与关闭 macOS Preview.app 的能力
- 新增: 鼠标双击、滚轮滚动 — ax_bridge 扩展 CGEvent 操作
v0.3.0 修复与调试增强 (2026/04/23)
- 修复: 滚动误点击 —
_scroll_at()原先用 mouseDown/mouseUp 聚焦导致误点侧边栏按钮,改用 kCGEventMouseMoved 仅移动鼠标不触发点击 - 修复: 未跳转最新消息 — 进入聊天后先
scroll_to_bottom()滚到消息列表底部(最新消息),再向上滚动加载历史 - 修复: "..."按钮误匹配 —
_find_more_button_in_preview()限制搜索范围,主窗口中只搜索 x>200 区域(排除左侧侧边栏),增加位置日志 - 修复: 重复点击同一图片 — 用消息列表子元素索引(child index)做去重,processed_indices 跟踪已处理元素,跨滚动轮次不重复
- 修复: 裁剪图片点击无效 — 只处理完全在消息列表可见区域内的媒体(上下各 30px margin),跳过部分被裁剪的元素
- 增强: 全链路调试日志 — click_at_element 记录坐标/角色/标题,get_media_messages 输出每个媒体详情,find_menu_item 记录搜索过程,状态检测记录所有窗口标题
v0.4.0 诊断工具与窗口恢复 (2026/04/23)
- 新增: --dump-ui --chat 诊断工具 —
python main.py --dump-ui --chat "聊天名"进入指定聊天,滚到底部,以 max_depth=10 dump 每个消息子元素的完整 AX 树(含索引、position、actions、identifier),用于诊断不同图片元素结构差异 - 新增: dump_element 增强 — 输出 AXPosition、AXActions、AXIdentifier 字段
- 新增: 微信窗口最小化自动恢复 — 新增
WECHAT_MINIMIZED状态,detect_state 区分"未运行"和"已最小化",通过 AppleScript 自动取消最小化并恢复前台 - 增强: verify_setup 自动恢复 — 启动时找不到主窗口先尝试恢复最小化,再判断失败
v0.5.0 图片点击与滚动修复 (2026/04/23)
- 修复: 图片点击不生效(根本原因) — AXStaticText 覆盖整行(575px宽),实际图片气泡仅在左侧 80~170px 区域。改用
click_at_element_offset(x=120, y=height/2)命中实际缩略图区域(通过逐像素探测确认可点击边界) - 修复: 滚动方向反转 — macOS CGEvent ScrollWheel 正值=向上滚(看旧消息),负值=向下滚(看新消息)。
scroll_to_bottom从 +20 改为 -20,历史加载滚动从 -10 改为 +10 - 修复: 可见性判断过严 — 原先要求元素完全在可见区域内(30px margin),289px 高图片经常被判定裁剪。改为只检查元素中心点是否在可见区域内
- 新增: click_at_element_offset — ax_bridge 新增带偏移量的点击方法,文件/视频点击也使用偏移量
- 已验证: 完整图片处理流程 — 蜗牛聊天 4 张不同尺寸图片(289px、155px、180px)全部成功:缩略图→预览窗口→...按钮→使用预览打开→关闭 Preview→恢复
- 已验证: 带滚动的媒体处理 — scroll_to_bottom 正确到达最新消息,向上滚动正确加载历史,去重正确(processed_indices=[45,47,49,50])
v0.6.0 最小化窗口恢复修复 (2026/04/23)
- 修复: 最小化时恢复失败(根本原因) — 原 AppleScript
tell application "WeChat"方案存在两个致命问题:(1) 微信的 localizedName 是"微信"不是"WeChat",AppleScript 找错应用或静默失败导致打开了别的窗口;(2) 微信不支持标准 AppleScriptminiaturized属性(返回 error -10006) - 修复: 最小化检测遗漏 — 微信窗口最小化后 AXWindows 仍返回该窗口(AXMinimized=True),原
detect_state和ensure_wechat_visible未检查此属性,误判窗口已可见 - 改用 AX API 恢复窗口 — 通过
AXUIElementSetAttributeValue(window, "AXMinimized", False)取消最小化,比 AppleScript 更可靠 - 多策略窗口恢复 — unhide(Cmd+H隐藏)→ AXMinimized=False(最小化)→ activate(前台),覆盖所有不可见场景
- 恢复重试与验证 —
ensure_wechat_visible增加 3 次重试循环,每次验证主窗口 AXMinimized=False 后才返回成功 - 已验证 — 两次完整测试通过:最小化微信→运行
--once --debug→自动恢复→正常扫描处理
待验证
验证最小化窗口自动恢复功能(需手动最小化微信窗口测试)- 有未读图片消息时的完整 --once 自动化流程
- 长时间运行稳定性测试
未来可能的改进
- 聊天列表滚动支持(处理不在可见区域的聊天)
- 已处理消息去重(记录已点击的媒体,避免重复)
- 微信版本适配(检测 UI 结构变化并自动调整)
- 运行状态 Web 面板(远程监控)
- 与信息收集系统直接集成
技术细节
微信 UI 结构 (v4.1.9)
- 主窗口 "微信" 包含侧边栏 + 聊天列表
- 聊天列表:
AXList name="会话",子元素为AXStaticText(无 AXPress 动作) - 聊天项 AXIdentifier 格式:
session_item_聊天名 - AXStaticText 的 AXPosition/AXSize 需通过 AXValueGetValue 解包
- 点击聊天项打开独立会话窗口
- 消息列表:
AXList name="消息" - 图片消息 title = "图片",文件消息 title 以 "文件\n" 开头
点击策略
- 聊天项和消息元素均使用 CGEvent 鼠标坐标点击(AXStaticText 不支持 AXPress)
- 计算元素中心坐标 = position + size/2
- 图片预览中的按钮优先尝试 click_at_element,后备 AXPress
图片下载流程
- 点击图片缩略图 → 打开大图预览(微信内窗口)
- 在预览窗口找到 "..." (更多) 按钮并点击
- 在弹出菜单中找到 "使用'预览'打开" 并点击
- 等待 macOS Preview.app 打开(此时原始文件已保存到本地)
- 关闭 Preview.app 窗口
- 回到微信,关闭大图预览
防封策略
- 高斯分布随机延迟(非均匀)
- ±20% 扫描间隔抖动
- 5% 概率长休息(30-120 秒)
- 工作时间限制
- 每次最多 5 个聊天
依赖
- pyobjc-framework-Quartz
- pyobjc-framework-ApplicationServices
- pyobjc-framework-Cocoa
- PyYAML
系统要求
- macOS Sonoma 14+
- Python 3.11+
- 辅助功能权限(终端/Python 需要授权)
- 微信桌面端 v4.1.9+