Detailed explanation of Appium framework: cross-platform mobile automation practice

You can automatically refresh short videos and regression test new App versions without touching the phone screen - Appium has become one of the mainstream tools for mobile automation with its unified cross-platform UI automation capabilities. With only one set of Python API, you can drive real devices or simulators of Android and iOS at the same time, without having to go through the native tool chains of UiAutomator and XCUITest respectively.

This article takes you through three steps from environment-setup → core tool class packaging → Douyin practice to get you started quickly. All codes are adapted to Python highlighting, and you can modify and run them by copying.


1. Set up a cross-platform basic environment in 5 minutes

Appium uses the classic client-server architecture:

  • Server side: Based on the core transit layer of Node.js, it communicates with the device through the WebDriver protocol.
  • Client library: Supports multiple languages ​​such as Python/Java/JS. Developers only need to write business logic and call the unified API.

1.1 Common dependencies across all platforms

Whether you are working on Android or iOS, you need to install the following common core tools first:

ToolsFunctionInstallation suggestions
Node.js + npm LTSGlobal installation of Appium server, Inspector, etc.Official website download (automatically configure environment variables)
Appium Python ClientPython version API packaging librarypipInstall the latest stable version

1.2 One-click installation and platform supplement

Open a terminal or CMD and install common services and drivers in order:

# 全局安装 Appium 核心服务器(--session-override 方便调试)
npm install -g appium

# 全局安装 Appium Inspector(可视化定位元素的神器,强烈推荐)
npm install -g appium-inspector

# 本文以 Android 实战为主,先安装 UiAutomator2 驱动
appium driver install uiautomator2

# 安装 Python 客户端(建议在独立虚拟环境中操作)
pip install Appium-Python-Client
Additional preparations for different platforms
  • Android users: Install Android Studio (automatically manage SDK, ADB), and enable "USB debugging", "USB installation" and "Allow simulated locations (optional)" in developer mode on your phone.
  • iOS users (macOS only): Install Xcode (automatically manage simulator/real device signature), executexcode-select --installInstall command line tools. :::

1.3 Verify whether the environment is running smoothly

Start the Appium server (default listeninghttp://127.0.0.1:4723):

appium --address 127.0.0.1 --port 4723 --session-override --log-timestamp

When you see "Appium REST http interface listener started" appearing in the output, it means that the server started successfully!


2. Lightweight general tool class encapsulation

In order to avoid repeatedly configuring connections, explicit waiting, etc. every time we write a script, we first encapsulate an out-of-the-boxAppiumHelperkind.

2.1 Complete Python code

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)

3. Douyin actual combat: simulate real user browsing

Based on the just packagedAppiumHelper, let’s implement a Douyin browsing script that can randomly like, randomly follow, and simulate real dwell time.

3.1 Obtain APP key information

First open the Douyin APP and obtain the package name and startup page through the ADB command:

# Windows CMD
adb shell dumpsys window | findstr mCurrentFocus

# macOS/Linux 终端
adb shell dumpsys window | grep mCurrentFocus

Usually the output looks like:

mCurrentFocus=Window{abc123 u0 com.ss.android.ugc.aweme/com.ss.android.ugc.aweme.splash.SplashActivity}
  • Package name:com.ss.android.ugc.aweme
  • Startup page:com.ss.android.ugc.aweme.splash.SplashActivity

3.2 Complete actual code

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)

4. Summary and expansion

The core advantage of Appium lies in its cross-platform unified API and complete ecosystem. After getting started, you can continue to delve deeper into the following aspects:

  1. More precise positioning: Use Appium Inspector to directly grab UI elements and replace the alternate locator in the example.
  2. More complex gestures: UtilizeActionChainImplement advanced operations such as long press, drag, and two-finger zoom.
  3. Parallel Multiple Devices: Use Docker containers or Appium Grid to control multiple devices at the same time.
  4. Integration with testing framework: Integrate Pytest and Allure to generate professional UI automation test reports.

:::warning Compliance Tips When using automated scripts, please strictly abide by the user agreement and laws and regulations of the target platform. It is prohibited to use it for malicious brushing, batch crawling of private data and other violations.