Appium 手机自动化控制教程
简介
Appium 是专业级的跨平台移动自动化测试框架,支持 iOS 和 Android,使用 WebDriver 协议。适合需要跨平台方案或专业测试的开发者。
一、Appium 简介
1.1 什么是 Appium
Appium 是一个开源的自动化测试工具,用于测试原生、混合和移动 Web 应用。
核心特点:
- 跨平台支持(iOS、Android、Windows)
- 多语言支持(Python、Java、JavaScript、Ruby 等)
- 基于 WebDriver 协议
- 不需要修改应用代码
- 支持真机和模拟器
1.2 Appium 架构
客户端(Python脚本)↓ WebDriver 协议
Appium Server↓ 平台驱动
iOS/Android 设备
二、环境准备
2.1 系统要求
所有系统:
- Node.js 14 或更高版本
- npm(Node.js 包管理器)
- Python 3.6 或更高版本
Android:
- Java JDK 8 或更高版本
- Android SDK
- ADB 工具
iOS(仅 macOS):
- Xcode
- Xcode Command Line Tools
- xcrun
2.2 安装 Node.js
检查是否已安装:
node --version
npm --version
Windows 安装:
- 访问 https://nodejs.org/
- 下载 LTS 版本
- 运行安装程序
- 验证:
node --version
macOS 安装:
# 使用 Homebrew
brew install node
Linux 安装:
# Ubuntu/Debian
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs# CentOS/RHEL
curl -fsSL https://rpm.nodesource.com/setup_lts.x | sudo bash -
sudo yum install -y nodejs
2.3 安装 Java JDK
检查是否已安装:
java -version
Windows 安装:
- 访问 https://www.oracle.com/java/technologies/downloads/
- 下载 JDK 8 或更高版本
- 安装后配置环境变量:
JAVA_HOME: JDK 安装路径- 添加到
PATH:%JAVA_HOME%\bin
macOS 安装:
brew install openjdk@11
Linux 安装:
# Ubuntu/Debian
sudo apt update
sudo apt install openjdk-11-jdk# CentOS/RHEL
sudo yum install java-11-openjdk-devel
2.4 安装 Android SDK
方法一:安装 Android Studio(推荐)
- 访问 https://developer.android.com/studio
- 下载并安装 Android Studio
- 打开 SDK Manager,安装必要组件:
- Android SDK Platform-Tools
- Android SDK Build-Tools
- Android SDK Platform(至少一个版本)
方法二:仅安装 SDK Command Line Tools
- 访问 https://developer.android.com/studio#command-tools
- 下载 Command Line Tools
- 解压到指定目录
配置环境变量:
# Windows (添加到系统环境变量)
ANDROID_HOME=C:\Users\YourName\AppData\Local\Android\Sdk
Path=%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools# macOS/Linux (添加到 ~/.bashrc 或 ~/.zshrc)
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/tools
验证:
adb version
三、安装 Appium
3.1 安装 Appium Server
方法一:使用 npm 全局安装(推荐)
npm install -g appium
验证安装:
appium --version
# 应显示版本号,如 2.x.x
方法二:安装 Appium Desktop(图形界面)
- 访问 https://github.com/appium/appium-desktop/releases
- 下载对应系统版本
- 安装并启动
3.2 安装 Appium 驱动
Appium 2.0 使用驱动系统,需要单独安装:
# 安装 UiAutomator2 驱动(Android)
appium driver install uiautomator2# 安装 XCUITest 驱动(iOS,仅 macOS)
appium driver install xcuitest# 查看已安装驱动
appium driver list
3.3 安装 Python 客户端
# 安装 Appium Python 客户端
pip install Appium-Python-Client
使用国内镜像:
pip install Appium-Python-Client -i https://pypi.tuna.tsinghua.edu.cn/simple
3.4 安装 Appium Inspector(可选)
用于查看应用元素结构:
# 方法一:使用 npm
npm install -g appium-inspector# 方法二:下载独立应用
# 访问 https://github.com/appium/appium-inspector/releases
四、配置和启动
4.1 启动 Appium Server
方法一:命令行启动
# 默认端口 4723
appium# 指定端口
appium --port 4725# 详细日志
appium --log-level debug
成功启动会显示:
[Appium] Welcome to Appium v2.x.x
[Appium] Appium REST http interface listener started on 0.0.0.0:4723
保持终端运行,不要关闭!
方法二:使用 Appium Desktop
- 打开 Appium Desktop
- 保持默认配置(Host: 0.0.0.0, Port: 4723)
- 点击 “Start Server”
4.2 手机配置
Android 手机:
- 开启开发者模式
- 开启 USB 调试
- 连接电脑,授权调试
- 验证:
adb devices
获取设备信息:
# 设备名称
adb devices# Android 版本
adb shell getprop ro.build.version.release# 平台版本(API Level)
adb shell getprop ro.build.version.sdk
4.3 获取应用信息
获取应用包名和 Activity:
# 先打开目标应用,然后执行:
adb shell dumpsys window | grep mCurrentFocus# 输出示例:
# mCurrentFocus=Window{abc123 u0 com.ss.android.ugc.aweme/com.ss.android.ugc.aweme.main.MainActivity}
# 包名:com.ss.android.ugc.aweme
# Activity:com.ss.android.ugc.aweme.main.MainActivity
五、第一个 Appium 脚本
5.1 测试连接脚本
创建 test_appium.py:
"""
测试 Appium 连接
"""from appium import webdriver
from appium.options.android import UiAutomator2Optionsdef test_connection():# 配置选项options = UiAutomator2Options()options.platform_name = "Android"options.device_name = "Android" # 可以是任意名称options.automation_name = "UiAutomator2"# 连接 Appium Serverappium_server_url = 'http://localhost:4723'try:driver = webdriver.Remote(appium_server_url, options=options)print("✅ 连接成功!")print(f"设备信息: {driver.capabilities}")# 关闭连接driver.quit()return Trueexcept Exception as e:print(f"❌ 连接失败: {e}")return Falseif __name__ == "__main__":test_connection()
运行前确保:
- Appium Server 已启动
- 手机已连接并授权
- 执行:
python test_appium.py
5.2 启动应用脚本
创建 appium_basic.py:
"""
Appium 基础操作:启动应用
"""from appium import webdriver
from appium.options.android import UiAutomator2Options
import timedef start_app_demo():# 配置选项options = UiAutomator2Options()options.platform_name = "Android"options.device_name = "Android"options.automation_name = "UiAutomator2"# 指定要启动的应用options.app_package = "com.ss.android.ugc.aweme" # 抖音包名options.app_activity = "com.ss.android.ugc.aweme.main.MainActivity"# 不重置应用数据options.no_reset = True# 连接appium_server_url = 'http://localhost:4723'driver = webdriver.Remote(appium_server_url, options=options)print("✅ 应用已启动")time.sleep(3)# 关闭driver.quit()print("✅ 测试完成")if __name__ == "__main__":start_app_demo()
六、自动化滑动脚本
6.1 基础滑动脚本
创建 appium_swipe.py:
"""
Appium 基础滑动脚本
"""from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
import timeclass AppiumSwiper:def __init__(self, package, activity):self.package = packageself.activity = activityself.driver = Nonedef connect(self):"""连接设备并启动应用"""options = UiAutomator2Options()options.platform_name = "Android"options.device_name = "Android"options.automation_name = "UiAutomator2"options.app_package = self.packageoptions.app_activity = self.activityoptions.no_reset = Trueappium_server_url = 'http://localhost:4723'self.driver = webdriver.Remote(appium_server_url, options=options)print("✅ 已连接设备")return Truedef get_screen_size(self):"""获取屏幕尺寸"""size = self.driver.get_window_size()return size['width'], size['height']def swipe_up(self):"""向上滑动"""width, height = self.get_screen_size()# 从屏幕下方滑到上方start_x = width // 2start_y = int(height * 0.8)end_x = width // 2end_y = int(height * 0.2)duration = 300 # 毫秒self.driver.swipe(start_x, start_y, end_x, end_y, duration)print("✅ 滑动成功")def run(self, interval=5, count=10):"""运行自动滑动"""if not self.connect():returnprint(f"⏰ 每 {interval} 秒滑动一次,共 {count} 次")print("-" * 50)try:for i in range(count):print(f"[{i+1}/{count}] {time.strftime('%H:%M:%S')} ", end="")self.swipe_up()if i < count - 1: # 最后一次不等待time.sleep(interval)except KeyboardInterrupt:print("\n⏹️ 用户停止")finally:self.driver.quit()print("✅ 已断开连接")def main():# 配置应用信息package = "com.ss.android.ugc.aweme" # 抖音activity = "com.ss.android.ugc.aweme.main.MainActivity"# 创建并运行swiper = AppiumSwiper(package, activity)swiper.run(interval=5, count=10)if __name__ == "__main__":main()
6.2 高级自动化脚本
创建 appium_advanced.py:
"""
Appium 高级自动化脚本
功能:
1. 元素查找和操作
2. 手势操作
3. 异常处理
4. 日志记录
"""from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.common.exceptions import NoSuchElementException
import time
import random
from datetime import datetimeclass AdvancedAutomation:def __init__(self, package, activity):self.package = packageself.activity = activityself.driver = Noneself.count = 0def connect(self):"""连接设备"""try:options = UiAutomator2Options()options.platform_name = "Android"options.device_name = "Android"options.automation_name = "UiAutomator2"options.app_package = self.packageoptions.app_activity = self.activityoptions.no_reset = Trueoptions.new_command_timeout = 300 # 超时时间(秒)appium_server_url = 'http://localhost:4723'self.driver = webdriver.Remote(appium_server_url, options=options)print(f"✅ 已连接: {self.driver.capabilities.get('deviceName')}")time.sleep(2)return Trueexcept Exception as e:print(f"❌ 连接失败: {e}")return Falsedef find_element_safe(self, by, value, timeout=5):"""安全查找元素"""try:self.driver.implicitly_wait(timeout)element = self.driver.find_element(by, value)return elementexcept NoSuchElementException:return Nonedef close_popup(self):"""关闭弹窗"""close_texts = ["关闭", "跳过", "我知道了", "取消"]for text in close_texts:element = self.find_element_safe(AppiumBy.XPATH, f"//*[@text='{text}']")if element:element.click()print(f"✅ 关闭弹窗: {text}")time.sleep(0.5)return Truereturn Falsedef swipe_with_variation(self):"""带随机变化的滑动"""size = self.driver.get_window_size()width = size['width']height = size['height']# 添加随机偏移x = width // 2 + random.randint(-50, 50)start_y = int(height * 0.75) + random.randint(-30, 30)end_y = int(height * 0.25) + random.randint(-30, 30)duration = random.randint(250, 350)self.driver.swipe(x, start_y, x, end_y, duration)self.count += 1def take_screenshot(self, name="screenshot"):"""截图"""timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")filename = f"{name}_{timestamp}.png"self.driver.save_screenshot(filename)print(f"📸 已保存截图: {filename}")def double_tap(self, x=None, y=None):"""双击(点赞)"""if x is None or y is None:size = self.driver.get_window_size()x = size['width'] // 2y = size['height'] // 2# 执行双击action = self.driver.execute_script('mobile: doubleClickGesture',{'x': x, 'y': y})print("❤️ 点赞")def run(self, interval=5, total_count=None):"""运行自动化"""if not self.connect():return# 关闭启动弹窗time.sleep(2)self.close_popup()print(f"\n⏰ 平均间隔: {interval} 秒")if total_count:print(f"🎯 目标: {total_count} 次")else:print(f"🔄 无限循环")print("-" * 50)start_time = time.time()try:while True:if total_count and self.count >= total_count:break# 关闭可能的弹窗self.close_popup()# 滑动timestamp = datetime.now().strftime('%H:%M:%S')print(f"[{self.count + 1}] {timestamp} ", end="")self.swipe_with_variation()print("✅")# 随机间隔wait_time = interval + random.uniform(-1, 1)time.sleep(wait_time)except KeyboardInterrupt:print("\n\n⏹️ 用户停止")except Exception as e:print(f"\n❌ 发生错误: {e}")self.take_screenshot("error")finally:elapsed = time.time() - start_timeself.print_stats(elapsed)self.driver.quit()def print_stats(self, elapsed):"""打印统计"""print(f"\n{'='*50}")print(f"📊 统计信息:")print(f" - 滑动次数: {self.count}")print(f" - 运行时长: {int(elapsed)} 秒")if self.count > 0:print(f" - 平均间隔: {elapsed/self.count:.1f} 秒")print(f"{'='*50}")def main():import argparseparser = argparse.ArgumentParser(description='Appium 自动化脚本')parser.add_argument('package', help='应用包名')parser.add_argument('activity', help='启动 Activity')parser.add_argument('-i', '--interval', type=float, default=5,help='滑动间隔(秒)')parser.add_argument('-n', '--count', type=int, default=None,help='滑动次数')args = parser.parse_args()automation = AdvancedAutomation(args.package, args.activity)automation.run(interval=args.interval, total_count=args.count)if __name__ == "__main__":main()
七、元素定位与操作
7.1 使用 Appium Inspector 查看元素
启动 Inspector:
- 启动 Appium Server
- 打开 Appium Inspector
- 配置 Desired Capabilities:
{"platformName": "Android","appium:deviceName": "Android","appium:automationName": "UiAutomator2","appium:appPackage": "com.ss.android.ugc.aweme","appium:appActivity": "com.ss.android.ugc.aweme.main.MainActivity","appium:noReset": true
}
- 点击 “Start Session”
- 查看元素层级和属性
7.2 常用定位方式
from appium.webdriver.common.appiumby import AppiumBy# ID 定位
element = driver.find_element(AppiumBy.ID, "com.app:id/button")# XPath 定位
element = driver.find_element(AppiumBy.XPATH, "//android.widget.Button[@text='登录']")# Class Name 定位
element = driver.find_element(AppiumBy.CLASS_NAME, "android.widget.Button")# Accessibility ID 定位
element = driver.find_element(AppiumBy.ACCESSIBILITY_ID, "login_button")# Android UiAutomator 定位(强大)
element = driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,'new UiSelector().text("登录")'
)# 组合定位
element = driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,'new UiSelector().className("android.widget.Button").text("确认")'
)
7.3 元素操作
# 点击
element.click()# 输入文本
element.send_keys("Hello World")# 清除文本
element.clear()# 获取文本
text = element.text# 获取属性
value = element.get_attribute("text")
enabled = element.get_attribute("enabled")# 判断元素状态
is_displayed = element.is_displayed()
is_enabled = element.is_enabled()
八、手势操作
8.1 滑动操作
# 基础滑动
driver.swipe(start_x, start_y, end_x, end_y, duration)# 从元素滑到另一个元素
element1 = driver.find_element(AppiumBy.ID, "source")
element2 = driver.find_element(AppiumBy.ID, "target")loc1 = element1.location
loc2 = element2.locationdriver.swipe(loc1['x'], loc1['y'], loc2['x'], loc2['y'], 500)
8.2 高级手势
from appium.webdriver.common.touch_action import TouchAction# 长按
action = TouchAction(driver)
action.long_press(x=500, y=1000, duration=2000).release().perform()# 拖拽
action.press(x=100, y=100).wait(1000).move_to(x=300, y=300).release().perform()# 多点触控(缩放)
from appium.webdriver.common.multi_action import MultiActionaction1 = TouchAction(driver)
action2 = TouchAction(driver)action1.press(x=100, y=500).move_to(x=100, y=300).release()
action2.press(x=300, y=500).move_to(x=300, y=700).release()multi = MultiAction(driver)
multi.add(action1, action2)
multi.perform()
8.3 滚动操作
# 滚动到元素可见
driver.execute_script('mobile: scrollGesture',{'left': 0, 'top': 0,'width': 1080, 'height': 2400,'direction': 'down','percent': 1.0}
)
九、运行指南
9.1 启动流程
步骤 1:启动 Appium Server
# 新终端窗口
appium
步骤 2:连接手机
# 新终端窗口
adb devices
步骤 3:运行脚本
# 基础脚本
python appium_swipe.py# 高级脚本(抖音,每5秒,共20次)
python appium_advanced.py com.ss.android.ugc.aweme com.ss.android.ugc.aweme.main.MainActivity -i 5 -n 20
9.2 常用应用配置
抖音:
package = "com.ss.android.ugc.aweme"
activity = "com.ss.android.ugc.aweme.main.MainActivity"
快手:
package = "com.smile.gifmaker"
activity = "com.yxcorp.gifshow.HomeActivity"
B站:
package = "tv.danmaku.bili"
activity = "tv.danmaku.bili.ui.splash.SplashActivity"
十、故障排查
10.1 “Could not start a new session”
解决方案:
# 1. 检查 Appium Server 是否启动
# 确保看到 "Appium REST http interface listener started"# 2. 检查驱动是否安装
appium driver list# 3. 重新安装驱动
appium driver uninstall uiautomator2
appium driver install uiautomator2# 4. 检查手机连接
adb devices
10.2 “An unknown server-side error occurred”
解决方案:
# 1. 重启 ADB
adb kill-server
adb start-server# 2. 清除应用数据
adb shell pm clear <package_name># 3. 重启 Appium Server
# Ctrl+C 停止,然后重新启动
10.3 元素找不到
解决方案:
# 1. 增加等待时间
driver.implicitly_wait(10)# 2. 使用显式等待
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ECwait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((AppiumBy.ID, "element_id"))
)# 3. 使用 Appium Inspector 确认元素属性
10.4 连接超时
解决方案:
# 增加超时设置
options.new_command_timeout = 600 # 10分钟
十一、性能优化
11.1 减少初始化时间
# 不重置应用
options.no_reset = True# 不卸载应用
options.full_reset = False# 跳过设备准备
options.skip_device_initialization = True
11.2 提高定位速度
# 设置隐式等待
driver.implicitly_wait(5)# 使用更快的定位方式(UiAutomator)
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,'new UiSelector().resourceId("id")'
)
11.3 并行执行
import threadingdef run_automation(device_name, port):options = UiAutomator2Options()options.platform_name = "Android"options.device_name = device_nameoptions.udid = device_name # 设备序列号driver = webdriver.Remote(f'http://localhost:{port}', options=options)# 执行操作...driver.quit()# 启动多个线程
thread1 = threading.Thread(target=run_automation, args=("device1", 4723))
thread2 = threading.Thread(target=run_automation, args=("device2", 4724))thread1.start()
thread2.start()
十二、完整项目结构
appium-automation/
├── test_appium.py # 连接测试
├── appium_basic.py # 基础操作
├── appium_swipe.py # 滑动脚本
├── appium_advanced.py # 高级脚本
├── config.py # 配置文件
├── utils/ # 工具模块
│ ├── __init__.py
│ ├── driver.py # 驱动管理
│ └── helpers.py # 辅助函数
├── screenshots/ # 截图目录
└── logs/ # 日志目录
十三、Appium vs uiautomator2 vs ADB
| 特性 | Appium | uiautomator2 | ADB |
|---|---|---|---|
| 跨平台 | ✅ iOS/Android | ❌ 仅 Android | ❌ 仅 Android |
| 学习曲线 | ⚠️ 较陡 | ⚠️ 中等 | ✅ 简单 |
| 配置复杂度 | ⚠️ 复杂 | ⚠️ 中等 | ✅ 简单 |
| 元素定位 | ✅ 强大 | ✅ 强大 | ❌ 不支持 |
| 手势操作 | ✅ 丰富 | ✅ 丰富 | ⚠️ 基础 |
| 性能 | ⚠️ 中等 | ✅ 较快 | ✅ 最快 |
| 多语言支持 | ✅ 多种 | ⚠️ Python | ⚠️ 命令行 |
| 专业度 | ✅ 最高 | ⚠️ 中等 | ⚠️ 基础 |
十四、最佳实践
14.1 配置管理
创建 config.py:
"""
配置文件
"""APPIUM_SERVER = "http://localhost:4723"DOUYIN = {"package": "com.ss.android.ugc.aweme","activity": "com.ss.android.ugc.aweme.main.MainActivity"
}KUAISHOU = {"package": "com.smile.gifmaker","activity": "com.yxcorp.gifshow.HomeActivity"
}DEFAULT_TIMEOUT = 10
DEFAULT_INTERVAL = 5
14.2 异常处理
from selenium.common.exceptions import (NoSuchElementException,TimeoutException,WebDriverException
)try:element = driver.find_element(AppiumBy.ID, "button")element.click()
except NoSuchElementException:print("元素不存在")
except TimeoutException:print("操作超时")
except WebDriverException as e:print(f"WebDriver 错误: {e}")
except Exception as e:print(f"未知错误: {e}")
14.3 日志记录
import logginglogging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s',filename='automation.log'
)logger = logging.getLogger(__name__)logger.info("开始自动化任务")
logger.warning("发现弹窗")
logger.error("操作失败")
十五、总结
恭喜完成 Appium 教程!你现在已经掌握:
✅ Appium 完整环境搭建
✅ 多种连接和启动方式
✅ 元素定位和操作技巧
✅ 手势和滑动操作
✅ 异常处理和调试
✅ 性能优化方法
Appium 优势:
- 跨平台支持(iOS + Android)
- 标准 WebDriver 协议
- 多语言客户端
- 专业测试框架
- 社区支持强大
适用场景:
- 跨平台自动化需求
- 专业测试项目
- 需要与 CI/CD 集成
- 团队协作项目
三种方案选择建议:
- 简单需求 → ADB(快速上手)
- Android 专项 → uiautomator2(功能丰富)
- 跨平台/专业 → Appium(最完整)
参考资源:
- Appium 官网:https://appium.io/
- Appium 文档:https://appium.io/docs/
- Python Client:https://github.com/appium/python-client
- Appium Inspector:https://github.com/appium/appium-inspector
