- Android用户:装Android Studio(自动管理SDK、ADB),开启开发者模式的「USB调试」「USB安装」「允许模拟位置(可选)」
- iOS用户(仅macOS):装Xcode(自动管理模拟器/真机签名),执行
xcode-select --install安装命令行工具
:::
1.3 验证环境是否跑通
启动Appium服务器(默认监听http://127.0.0.1:4723):
appium --address 127.0.0.1 --port 4723 --session-override --log-timestamp
看到输出里有 「Appium REST http interface listener started」 就说明服务器没问题!
二、轻量通用工具类封装
避免每次写脚本都重复配置连接、显式等待等代码,先封装一个开箱即用的AppiumHelper类。
2.1 完整Python代码
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
class AppiumHelper:
"""Android UiAutomator2轻量自动化助手(可扩展iOS)"""
def __init__(self,
device_name: str,
app_package: str = None,
app_activity: str = None,
remote_url: str = "http://127.0.0.1:4723"):
"""
初始化助手
:param device_name: 设备名/模拟器名(adb devices/Xcode模拟器列表获取)
:param app_package: 目标APP包名
:param app_activity: 目标APP启动页Activity
:param remote_url: Appium服务器地址
"""
self.remote_url = remote_url
self.driver = None
# 配置默认Android选项(可覆盖)
self.options = UiAutomator2Options()
self.options.platform_name = "Android"
self.options.device_name = device_name
self.options.auto_grant_permissions = True # 自动授权所有权限
self.options.unicode_keyboard = True # 支持中文输入
self.options.reset_keyboard = True # 脚本结束恢复默认键盘
self.options.no_reset = True # 保留APP登录状态
# 可选配置:指定APP包和启动页
if app_package:
self.options.app_package = app_package
if app_activity:
self.options.app_activity = app_activity
def connect(self) -> bool:
"""连接Appium并启动APP"""
try:
self.driver = webdriver.Remote(self.remote_url, options=self.options)
print(f"✅ Appium连接成功:{self.options.device_name}")
return True
except Exception as e:
print(f"❌ Appium连接失败:{str(e)}")
return False
def disconnect(self) -> None:
"""安全断开连接"""
if self.driver:
self.driver.quit()
print("🔌 连接已断开")
# -------------------- 显式等待与元素操作 --------------------
def wait_element(self, locator: tuple, timeout: int = 10):
"""
显式等待元素出现
:param locator: 定位器元组,如(AppiumBy.ID, "xxx")
:param timeout: 最长等待时间
:return: WebElement对象或None
"""
try:
return WebDriverWait(self.driver, timeout).until(
EC.presence_of_element_located(locator)
)
except Exception:
return None
def tap_element(self, locator: tuple, timeout: int = 10) -> bool:
"""点击元素(带等待)"""
el = self.wait_element(locator, timeout)
if el:
el.click()
return True
print(f"⚠️ 未找到可点击元素:{locator}")
return False
def input_text(self, locator: tuple, text: str, timeout: int = 10) -> bool:
"""输入文本(自动清空原内容)"""
el = self.wait_element(locator, timeout)
if el:
el.clear()
el.send_keys(text)
return True
print(f"⚠️ 未找到可输入元素:{locator}")
return False
# -------------------- 基础手势操作 --------------------
def swipe_up(self, duration: int = 800) -> None:
"""向上滑动屏幕(刷视频/滚动列表通用)"""
size = self.driver.get_window_size()
w, h = size["width"], size["height"]
start = (w // 2, h * 3 // 4)
end = (w // 2, h // 4)
self.driver.swipe(*start, *end, duration)
三、抖音实战:模拟真实用户浏览
用刚才的AppiumHelper,写一个能随机点赞、随机关注、模拟真实停留时间的抖音脚本。
3.1 先获取APP关键信息
打开抖音APP,执行ADB命令获取包名和启动页:
# Windows CMD
adb shell dumpsys window | findstr mCurrentFocus
# macOS/Linux终端
adb shell dumpsys window | grep mCurrentFocus
通常输出类似:
mCurrentFocus=Window{abc123 u0 com.ss.android.ugc.aweme/com.ss.android.ugc.aweme.splash.SplashActivity}
- 包名:
com.ss.android.ugc.aweme
- 启动页:
com.ss.android.ugc.aweme.splash.SplashActivity
3.2 完整实战代码
from appium.webdriver.common.appiumby import AppiumBy
import time
import random
# 假设刚才的封装放在同目录的appium_helper.py里
from appium_helper import AppiumHelper
class DouyinAuto:
"""抖音模拟浏览自动化类"""
def __init__(self, device_name: str):
# 配置抖音的连接信息
self.helper = AppiumHelper(
device_name=device_name,
app_package="com.ss.android.ugc.aweme",
app_activity=".splash.SplashActivity"
)
self.driver = None
def start(self) -> None:
"""启动连接并等待APP加载完成"""
if self.helper.connect():
self.driver = self.helper.driver
print("⏳ 等待抖音冷启动...")
time.sleep(10) # 抖音冷启动时间较长
def like_current(self) -> bool:
"""尝试多个定位器点赞(防止版本更新失效)"""
like_locs = [
(AppiumBy.ID, "com.ss.android.ugc.aweme:id/like_icon"),
(AppiumBy.XPATH, '//android.widget.ImageView[@content-desc="点赞"]')
]
for loc in like_locs:
if self.helper.tap_element(loc, timeout=3):
print("❤️ 点赞成功")
return True
print("⚠️ 未找到点赞按钮")
return False
def follow_author(self) -> None:
"""随机关注当前作者(模拟真实行为)"""
# 先点击头像进入主页
avatar_loc = (AppiumBy.ID, "com.ss.android.ugc.aweme:id/author_avatar")
if self.helper.tap_element(avatar_loc, timeout=3):
time.sleep(2)
# 点击关注按钮(支持文本匹配)
follow_loc = (AppiumBy.XPATH, '//android.widget.Button[contains(@text, "关注")]')
if self.helper.tap_element(follow_loc, timeout=2):
print("👤 关注成功")
# 返回视频页面
self.driver.back()
time.sleep(1)
def run(self, cycles: int = 5, like_rate: float = 0.7, follow_rate: float = 0.05):
"""
运行自动化任务
:param cycles: 浏览视频的次数
:param like_rate: 点赞概率(0-1)
:param follow_rate: 关注概率(0-1)
"""
if not self.driver:
return
print(f"🤖 开始任务:共浏览{cycles}个视频")
for i in range(cycles):
print(f"\n🔄 第{i+1}个视频:")
# 随机点赞
if random.random() < like_rate:
self.like_current()
# 随机关注
if random.random() < follow_rate:
self.follow_author()
# 模拟真实停留时间(2-6秒)
stay = random.uniform(2, 6)
print(f"⏳ 停留{stay:.1f}秒")
time.sleep(stay)
# 滑到下一个视频
if i < cycles - 1:
print("📱 滑动到下一个")
self.helper.swipe_up(duration=700)
time.sleep(0.8) # 等待视频预加载
print("\n🏁 任务全部完成!")
self.helper.disconnect()
if __name__ == "__main__":
# 替换成你自己的设备名(adb devices获取)
AUTO = DouyinAuto(device_name="emulator-5554")
AUTO.start()
AUTO.run(cycles=3, like_rate=0.9, follow_rate=0.1)
四、总结与拓展
Appium的核心优势在于跨平台统一API和生态完善,入门后可以做这些拓展:
- 更精准的定位:用Appium Inspector直接抓取UI元素,替换示例里的备用定位器
- 更复杂的手势:用
ActionChain实现长按、拖拽、双指缩放
- 并行多设备:用Docker容器或者Appium Grid同时控制多台设备
- 与测试框架结合:和Pytest、Allure一起做专业的UI自动化测试报告
:::warning 合规提示
使用自动化脚本时,请严格遵守目标平台的用户协议和法律法规,禁止用于恶意刷量、批量爬取隐私数据等违规行为。