iPhone 有线自动化实战:Appium + XCUITest 实现签到App定时签到(多时间、前台监控)
文章目录
- [iPhone 有线自动化实战:Appium + XCUITest 实现签到App定时签到(多时间、前台监控)](#iPhone 有线自动化实战:Appium + XCUITest 实现签到App定时签到(多时间、前台监控))
-
- 一、项目背景
- 二、技术方案
-
- [1. 技术栈](#1. 技术栈)
- [2. 目录结构(当前可用版本)](#2. 目录结构(当前可用版本))
- 三、核心流程设计
-
- [1. 主流程顺序(重点)](#1. 主流程顺序(重点))
- [2. 解锁策略](#2. 解锁策略)
- [3. 时间策略](#3. 时间策略)
- 四、环境准备
-
- [1. iPhone 侧](#1. iPhone 侧)
- [2. Mac 侧](#2. Mac 侧)
- 五、配置文件示例
- 六、如何使用
-
- [1. 立即跑一次测试](#1. 立即跑一次测试)
- [2. 输入多个时间自动执行](#2. 输入多个时间自动执行)
- 七、关键实现点(可复用)
-
- [1. 一次性任务自动清理](#1. 一次性任务自动清理)
- [2. 运行环境隔离](#2. 运行环境隔离)
- [3. 证据留存](#3. 证据留存)
- 八、常见问题与排查
-
- [1. 输入时间后脚本秒退](#1. 输入时间后脚本秒退)
- [2. 点击偏移](#2. 点击偏移)
- [3. Appium 拉不起](#3. Appium 拉不起)
- 九、项目总结
- 十、匿名说明与合规提醒
一、项目背景
最近做了一个 iPhone 有线自动化小项目:在手机连接 Mac 的前提下,自动完成签到App的固定流程。
目标流程如下:
- 检查并开启蓝牙。
- 启动签到App。
- 若停留在图形页,则按预设轨迹完成图形解锁。
- 点击"出勤"。
- 等待 15~20 秒。
- 关闭签到App,再关闭蓝牙。
另外,我还补了两个关键能力:
- 支持一次输入多个执行时间(例如今晚 19:00、明早 07:00、明晚 19:00)。
- 任务创建后不隐藏,终端持续显示每个任务倒计时和状态。
当前版本不做系统锁屏/解锁自动化;如果手机系统锁屏,需要手动先解锁。
二、技术方案
1. 技术栈
- Python 3
- Appium 2
- XCUITest Driver
- launchd(macOS 定时任务)
- zsh 脚本(任务编排)
2. 目录结构(当前可用版本)
text
.
├── checkin_auto.py # 主流程(文中匿名名)
├── checkin_config.json # 配置文件(文中匿名名)
├── checkin_test.command # 立即测试一次(文中匿名名)
├── checkin_start.command # 输入多个时间并创建一次性任务 + 前台监控(文中匿名名)
├── run_checkin_once.sh # 单次执行入口(文中匿名名)
├── run_checkin_once_and_cleanup.sh # 执行后清理对应 launchd 任务(文中匿名名)
├── requirements.txt
├── logs/
├── screenshots/
└── page_sources/
三、核心流程设计
1. 主流程顺序(重点)
顺序必须是:
先蓝牙 -> 再启动 App -> 解锁/点击出勤 -> 关闭 App -> 关蓝牙
这个顺序在某些页面切换场景下会更稳定,避免"先开 App 再处理蓝牙"导致状态异常。
2. 解锁策略
- 优先根据检测到的控件区域动态推算九宫格坐标(抗分辨率偏差)。
- 检测失败再回落到配置里的比例坐标。
- 轨迹配置可直接调整,例如当前为
[2, 5, 8, 9]。
3. 时间策略
- App 首屏等待:随机 2~5 秒(模拟人工节奏)。
- 点击出勤后等待:随机 15~20 秒(给页面结果留足时间)。
四、环境准备
1. iPhone 侧
- 用数据线连接 Mac,并"信任此电脑"。
- 开启开发者模式。
- 打开
设置 -> 开发者 -> Enable UI Automation。
2. Mac 侧
- 安装 Xcode、Command Line Tools、Node.js。
- 安装 Appium:
bash
npm install -g appium
appium driver install xcuitest
- 安装 Python 依赖:
bash
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
chmod +x checkin_test.command checkin_start.command run_checkin_once.sh run_checkin_once_and_cleanup.sh
五、配置文件示例
checkin_config.json(精简后的关键字段,文中匿名名):
json
{
"appium": {
"server_url": "http://127.0.0.1:4723",
"udid": "你的UDID",
"bundle_id": "com.example.checkin.app",
"platform_version": "18.6.2",
"wda_local_port": 8100,
"new_command_timeout": 180,
"no_reset": true,
"show_xcode_log": true,
"xcode_org_id": "你的TeamID",
"xcode_signing_id": "Apple Development",
"updated_wda_bundle_id": "你的WDA BundleID",
"allow_provisioning_device_registration": true
},
"timing": {
"startup_wait_range_seconds": [2.0, 5.0]
},
"unlock": {
"enabled": true,
"use_detected_grid": true,
"pattern_nodes": [[0.31,0.28],[0.50,0.28],[0.69,0.28],[0.31,0.37],[0.50,0.37],[0.69,0.37],[0.31,0.46],[0.50,0.46],[0.69,0.46]],
"path": [2, 5, 8, 9],
"press_ms": 150,
"move_ms": 250,
"post_unlock_wait_range_seconds": [2.0, 5.0]
},
"attendance": {
"text_candidates": ["出勤"],
"fallback_tap": [0.38, 0.20],
"post_click_wait_range_seconds": [15.0, 20.0]
}
}
六、如何使用
1. 立即跑一次测试
bash
./checkin_test.command
适合调试解锁轨迹、出勤按钮定位、页面结构变化等问题。
2. 输入多个时间自动执行
bash
./checkin_start.command
支持输入格式:
2026-04-09 19:0019:00今晚7点明早7点明晚7点
输入完成后,脚本会:
- 解析并去重时间。
- 创建多个一次性 launchd 任务。
- 在当前终端持续显示每个任务的"计划时间 / 剩余倒计时 / 状态"。
七、关键实现点(可复用)
1. 一次性任务自动清理
每个定时任务执行后会调用清理脚本,自动卸载并删除对应 plist,避免任务残留污染。
2. 运行环境隔离
定时脚本会同步到独立 runner 目录执行,规避中文路径或终端环境差异对 launchd 的影响。
3. 证据留存
每次运行都会输出:
screenshots/截图page_sources/页面源码logs/运行日志
这对定位"按钮文本变了""层级变了""坐标偏了"非常有用。
八、常见问题与排查
1. 输入时间后脚本秒退
重点检查:
- Python 版本兼容性(尤其类型注解语法)。
- 时间解析逻辑是否覆盖你输入的中文格式。
- zsh 下 glob 与变量展开细节。
2. 点击偏移
优先开启并依赖 unlock.use_detected_grid=true;
如果控件检测失败,再微调 unlock.pattern_nodes 与 attendance.fallback_tap。
3. Appium 拉不起
先手动执行:
bash
appium --port 4723
再看 logs/appium.stdout.log,通常是驱动、签名或端口占用问题。
九、项目总结
这个项目本质上不是"写个脚本就完事",而是把真机自动化的不稳定因素工程化收敛:
- 流程顺序严格化(蓝牙/启动/关闭顺序)
- 时间窗口随机化(更接近人工节奏)
- 多任务可视化监控(降低黑盒感)
- 运行后证据沉淀(便于快速回归修复)
如果你也在做 iOS 有线自动化,这套结构可以直接复用:
把业务动作替换掉,保留"调度 + 监控 + 清理 + 证据"的骨架即可。
十、匿名说明与合规提醒
本文对应用名、脚本名、bundle id 均做了匿名化处理(统一称"签到App"),便于公开分享。
请遵守目标应用的平台规则与相关协议。
本文仅分享技术实现思路与工程化经验。