起因
这次想验证一个很简单的场景:能不能让 Claude Code 帮我完成两件日常小事——
用飞书给自己的机器人「克劳德」发一条消息
打开微信,给「三个臭皮匠」群发个表情包

听起来是两个几乎一样的任务:找到聊天对象 → 输入内容 → 发送。但实际跑下来,一个几分钟搞定,另一个卡在了"打开聊天窗口"这一步,最后没能收尾。这篇就记录一下这次的差异到底出在哪,以及背后的技术原因。

第一关:飞书,靠 API 一路顺畅
飞书这边用的是 lark-cli,本质上是在调飞书开放平台的 API,而不是操作 GUI。过程中遇到的唯一插曲是:
一开始以为「克劳德」是通讯录里的某个真人,后来确认它其实是我自己应用的机器人,对应的是一个 P2P 会话(oc_ec26cce1f178c2f67fb3a66adfa51a76)
首次调用发送接口时报错,缺少 im:message.send_as_user 权限,于是走了一遍标准的 OAuth 授权流程——生成二维码、我手机扫码确认、拿到 token
重试,消息发出去了
整个过程没有涉及任何界面点击,全是接口调用。这也是为什么它顺利:API 是结构化的,输入输出都是明确定义好的字段,不存在"猜"的环节。

第二关:微信,卡在"看得见但摸不着"
微信这边的目标本该更简单——就是发一个默认 emoji 到一个已经置顶在列表里的群。但恰恰是这个"看起来简单"的任务,暴露了 GUI 自动化的核心痛点。
问题出在哪:
回头复盘发现,真正的根因其实很意外:「三个臭皮匠」这个聊天框我本来就已经打开了,根本不需要"查找 → 打开"这一步。但执行时还是默认走了一套固定流程——先 Ctrl+F 搜索,再从结果里选中打开。也就是说,第一步就没有先确认当前窗口的状态,而是无条件执行了"查找目标聊天"这个动作,相当于人已经站在目标房间里,却先跑去翻通讯录找这个房间在哪。
这一步走偏之后,才暴露出第二层问题——微信桌面端的界面是自绘的(不是标准 Win32/WPF 控件树):
Windows 的 UI Automation(UIA)拿不到微信内部的控件层级,没法像操作普通程序那样"找到这个按钮,点它"
Ctrl+F 搜索框和真正的聊天列表是两套完全独立的渲染层,程序化地"粘贴群名 + 回车"或"方向键 + 回车",选中的经常不是预期的那一项——因为搜索结果的弹出、聚焦、渲染时序本身就不稳定,方向键到底选中了搜索框自己,还是搜索结果第一项,是不确定的
全程聊天窗口标题栏都停留在"微信",没有跳转成群聊标题,说明点击/回车压根没有触发预期的窗口切换
如果第一步先检查了"当前激活的聊天窗口是不是已经是目标群",这条本可以跳过的搜索路径根本不会被触发,后面这些自绘 UI 的坑也就不会踩上。
备用方案:截图 + OCR + 坐标点击
既然拿不到控件树,只能退一步,把微信当成一张"图片"来处理:

截屏
OCR 识别屏幕上的文字,拿到"三个臭皮匠"几个字在屏幕上的像素坐标
直接模拟鼠标点击这个坐标
这个方案在这次会话里已经跑通了定位这一步——OCR 成功识别到了两处「臭皮匠」文字(一处在聊天列表区,一处在搜索结果区),但受限于当时的会话环境,没能操作电脑执行最后的点击+发送。

两条路径的本质区别
飞书(API) 微信(GUI 自动化)
交互方式 结构化接口调用 模拟人类操作界面
定位目标 按 ID/字段精确匹配 靠像素坐标"猜"
稳定性 高,只要权限对就必成功 低,依赖窗口布局、渲染时序、分辨率
失败模式 报错信息明确(如缺权限) 静默失败,只能靠"窗口标题没变"这种旁证倒推

说白了,能走 API 就不要走 GUI 自动化。飞书之所以顺,是因为它把自己的能力开放成了接口;微信没有开放个人号自动化接口(也是出于风控考虑),留给外部程序的只有"假装自己是一个用鼠标键盘的人"这一条路,而这条路天然脆弱。
但这次的教训更前置一步:在选择走哪条路之前,得先确认有没有必要走。GUI 自动化的坑是真实存在的,可如果一开始就先判断"当前状态是不是已经满足目标",很多本不必要的操作根本不会被触发。执行动作之前先"看一眼现状",比操作本身更容易被忽略,却往往是决定成败的第一步。

后续打算
下一步不急着补 OCR 点击这一步,而是先把执行流程补上一道"状态检查":动手之前先确认当前聊天窗口是不是已经是目标群,是的话直接输入发送,不是才触发查找。这道检查加上之后,再考虑 OCR 坐标点击要不要封装成通用的兜底方案——毕竟自绘 UI 拿不到控件树这个限制本身还在,只是不该在每次任务里都无条件触发它。

posted on 2026-08-13 21:18  chenyun_922  阅读(11)  评论(0)    收藏  举报