不止于测试:用uiautomator2打造你的Android手机自动化“外挂”(附完整脚本)
不止于测试用uiautomator2打造你的Android手机自动化“外挂”在数字生活高度渗透的今天手机早已成为我们身体的延伸。每天重复的签到、抢购、消息回复等操作不仅消耗时间更让人感到疲惫。有没有一种方式能让手机像拥有自主意识一样自动完成这些琐碎任务这就是uiautomator2带给我们的可能性——它远不止是一个测试工具更是解放双手的自动化利器。1. 为什么选择uiautomator2提到Android自动化很多人会想到Appium或ADB命令。但uiautomator2在易用性和功能深度上找到了完美平衡无界面依赖不同于需要开启开发者选项中指针位置的辅助功能方案它直接与系统服务交互Python生态所有操作都可以用Python脚本控制轻松集成到现有工作流全面覆盖从基础点击到复杂手势从应用管理到设备控制API设计极其完备性能优势相比基于WebDriver的方案执行速度更快资源占用更低我曾用它在凌晨3点自动抢到限量球鞋也实现了微信消息的智能回复原型。这些看似黑科技的操作其实只需要几十行代码。2. 环境搭建5分钟快速入门2.1 基础环境配置确保你的开发环境已经具备# 检查Python版本需要3.6 python --version # 安装基础工具 pip install uiautomator2 weditor手机端需要开启USB调试模式进入设置 → 关于手机 → 连续点击版本号7次开启开发者模式返回设置 → 系统 → 开发者选项 → 开启USB调试连接电脑后在手机上允许调试请求提示部分厂商手机需要额外开启USB安装和USB调试安全设置2.2 设备连接方式对比连接方式命令示例适用场景稳定性USB直连d u2.connect()开发调试★★★★★WiFi连接d u2.connect(192.168.1.100:7912)远程控制★★★☆☆多设备指定d u2.connect(设备序列号)多机操作★★★★☆推荐初次使用选择USB连接稳定性最佳。连接成功后可以打印设备信息验证import uiautomator2 as u2 d u2.connect() print(d.info)3. 实战案例从自动化到外挂3.1 短视频自动刷播脚本很多短视频平台会有观看时长奖励手动操作既耗时又无聊。下面脚本实现自动滑动和随机间隔点赞import random import time def auto_swipe(d, count100): width, height d.window_size() for i in range(count): # 随机滑动距离和时长 start_y height * 0.8 end_y height * 0.2 duration random.uniform(0.3, 0.8) # 滑动操作 d.swipe(width/2, start_y, width/2, end_y, duration) # 30%概率点赞 if random.random() 0.7: d.click(width-100, height/2) # 随机间隔1-3秒 time.sleep(random.uniform(1, 3))优化技巧加入random制造人类操作的不确定性通过window_size()适配不同分辨率设备使用相对坐标而非绝对坐标值3.2 微信自动回复原型虽然完整实现消息自动回复需要更高权限但我们可以监控特定联系人消息并模拟点击回复def wechat_auto_reply(d, contact_name, reply_content): # 启动微信 d.app_start(com.tencent.mm) # 等待主界面加载 d(text微信).wait(timeout10) # 进入聊天列表 d(resourceIdcom.tencent.mm:id/cns).click() # 搜索指定联系人 d(resourceIdcom.tencent.mm:id/iq).set_text(contact_name) time.sleep(1) # 监控新消息 watcher d.watcher(NEW_MSG) watcher.when(resourceIdcom.tencent.mm:id/aou).click() # 设置自动回复 def do_reply(): d(resourceIdcom.tencent.mm:id/amr).set_text(reply_content) d(resourceIdcom.tencent.mm:id/amv).click() watcher.when(text发送).call(do_reply) watcher.start()注意实际使用需考虑微信版本差异建议先在测试环境验证3.3 游戏日常任务自动化以某热门手游为例自动完成每日签到和简单任务def game_daily(d): # 启动游戏 d.app_start(com.game.example) # 等待加载完成 while not d(text每日签到).exists: time.sleep(1) # 签到流程 if d(text每日签到).exists: d(text每日签到).click() time.sleep(1) d(text领取).click() time.sleep(1) d.click(540, 1800) # 关闭弹窗 # 执行日常任务 task_positions [ (200, 800), # 任务1坐标 (500, 800), # 任务2坐标 (800, 800) # 任务3坐标 ] for x, y in task_positions: d.click(x, y) time.sleep(3) d.press(back) # 返回键 time.sleep(1)定位技巧使用weditor分析界面元素对动态元素采用相对定位关键操作后加入合理等待4. 高级技巧与避坑指南4.1 元素定位的六种武器文本定位d(text设置)资源ID定位d(resourceIdcom.android.settings:id/title)组合定位d(classNameandroid.widget.TextView, textWi-Fi)相对定位d(textWi-Fi).right(classNameandroid.widget.Switch)XPath定位d.xpath(//*[content-desc更多选项])图像识别d.image.click(button.png)定位策略选择优先级资源ID 文本 组合条件 相对定位 XPath 图像识别4.2 稳定性提升方案等待策略对比表等待方式代码示例适用场景超时处理固定等待time.sleep(3)简单场景不灵活元素等待d(textOK).wait(10)元素出现抛出异常全局超时d.implicitly_wait(15)通用设置自动处理智能等待while not condition: sleep(1)复杂条件自定义逻辑推荐实践# 设置合理的全局等待超时 d.implicitly_wait(10) # 关键操作添加显式等待 if d(text同意).wait(timeout5): d(text同意).click() else: raise Exception(协议页面加载超时) # 复杂界面使用监控器 watcher d.watcher(POPUP) watcher.when(text确定).click() watcher.start()4.3 常见问题排查问题1点击无效检查元素是否可点击d(text按钮).info[clickable]尝试坐标点击d.click(x, y)确认没有遮挡物问题2脚本在不同设备表现不一致使用相对坐标而非绝对坐标通过window_size()适配分辨率增加异常处理和重试机制问题3性能突然下降关闭不必要的watcher减少截图操作频率重启uiautomator服务d.service(uiautomator).restart()5. 扩展应用自动化生态构建5.1 与Tasker联动通过uiautomator2执行复杂操作用Tasker设置触发条件将Python脚本打包为APK使用Termux等工具Tasker监测特定事件如时间、通知等调用脚本执行自动化任务5.2 搭建自动化服务器将常用脚本部署为HTTP服务实现远程触发from flask import Flask, request import uiautomator2 as u2 app Flask(__name__) d u2.connect() app.route(/wechat/reply) def wechat_reply(): contact request.args.get(contact) message request.args.get(msg) # 调用之前的自动回复函数 wechat_auto_reply(d, contact, message) return OK if __name__ __main__: app.run(host0.0.0.0, port5000)5.3 数据采集与分析结合Pandas进行行为数据收集和分析import pandas as pd from datetime import datetime data [] def collect_action(action): data.append({ time: datetime.now(), action: action, screen: d.app_current()[activity] }) # 在操作中插入采集点 d.click(100, 200) collect_action(点击签到按钮) # 保存数据 df pd.DataFrame(data) df.to_csv(action_log.csv, indexFalse)在实际项目中我发现最耗时的不是编写脚本本身而是处理各种边界情况和异常。比如某次自动签到失败是因为系统弹出了新版协议确认框。后来我加入了弹窗监控机制脚本稳定性大幅提升。