Skip to main content

蜂巢云控 Python SDK - 手机自动化控制

Project description

🐝 蜂巢云控 Python SDK

简单、强大的手机自动化控制SDK,支持 无障碍服务ADB USBADB WiFiHID/OTG 多种控制方式。

PyPI version Python

✨ 特性

  • 🚀 简单易用 - 几行代码即可控制手机
  • 📶 无障碍服务 - 无需ROOT,稳定可靠
  • 🔄 批量控制 - 同时控制50+台设备
  • 并行操作 - 多线程同时执行,效率翻倍
  • 🔍 OCR识别 - 屏幕文字识别与点击
  • 🖼️ 图像识别 - 模板匹配查找图标
  • 📱 元素查找 - 按ID/类名/文本查找元素
  • 🌐 远程控制 - 通过中继服务器远程控制

📦 安装

pip install fengchao-sdk

安装全部功能:

pip install fengchao-sdk[all]  # 包含OCR和图像识别

📱 无障碍模式(推荐)

无障碍模式无需ROOT,通过安卓无障碍服务实现控制,支持远程操作。

1️⃣ WiFi直连模式

手机和电脑在同一局域网时使用:

from fengchao import Device

# 连接设备(手机IP:端口)
device = Device('192.168.1.100', port=8888, mode='wifi')

# 基础操作
device.screenshot()           # 截图
device.click(500, 800)        # 点击
device.swipe(100, 800, 100, 200)  # 滑动
device.input_text('Hello')    # 输入文字

# 按键操作
device.press_home()           # Home键
device.press_back()           # 返回键
device.press_menu()           # 菜单键

# APP操作
device.start_app('com.android.settings')  # 启动APP
device.stop_app('com.android.settings')   # 停止APP
device.get_current_app()      # 获取当前APP

2️⃣ 中继服务器模式

通过中继服务器远程控制设备:

from fengchao import Device

# 连接中继服务器
device = Device(
    device_id='设备ID',
    api_key='你的API密钥',
    relay_server='http://服务器地址:9999',
    mode='relay'
)

# 所有操作与WiFi直连一致
device.screenshot()
device.click(500, 800)
device.press_home()

3️⃣ 元素查找(无障碍核心功能)

通过无障碍服务可以精确查找和操作UI元素:

# 按文本查找
elem = device.find_element(text='登录')
if elem:
    elem.click()  # 点击元素

# 按资源ID查找
elem = device.find_element(resource_id='com.example:id/btn_login')

# 按类名查找
elems = device.find_elements(class_name='android.widget.Button')
print(f'找到 {len(elems)} 个按钮')

# 按内容描述查找
elem = device.find_element(content_desc='返回')

# 组合查找
elem = device.find_element(
    class_name='android.widget.TextView',
    text='确定'
)

# 检查元素是否存在
if device.element_exists(text='登录成功'):
    print('登录成功!')

# 等待元素出现
elem = device.wait_element(text='加载完成', timeout=10)

# 直接点击元素
device.click_element(text='确定')
device.click_element(resource_id='com.example:id/btn')

元素属性

elem = device.find_element(text='登录')
print(elem.text)           # 文本内容
print(elem.resource_id)    # 资源ID
print(elem.class_name)     # 类名
print(elem.content_desc)   # 内容描述
print(elem.bounds)         # 坐标范围
print(elem.clickable)      # 是否可点击

4️⃣ 图像识别

# 截图并裁剪模板
img = device.screenshot()
template = img.crop((100, 100, 200, 200))
template.save('button.png')

# 查找图片
result = device.find_image('button.png', threshold=0.8)
if result:
    print(f"找到位置: {result['center']}")
    print(f"置信度: {result['confidence']}")

# 点击图片
device.click_image('button.png')

# 等待图片出现
device.wait_image('loading_done.png', timeout=10)

# 检查图片是否存在
if device.image_exists('success.png'):
    print('操作成功!')

5️⃣ OCR文字识别

需要安装:pip install rapidocr-onnxruntime

# OCR识别屏幕文字
texts = device.ocr()
for t in texts:
    print(f"{t['text']} @ {t['center']}")

# 查找文字
result = device.find_text('登录')
if result:
    print(f"找到: {result['text']} @ {result['center']}")

# 点击文字
device.click_text('登录')
device.click_text('确定', timeout=5)

# 检查文字是否存在
if device.text_exists('登录成功'):
    print('成功!')

# 等待文字出现
device.wait_text('加载完成', timeout=10)

6️⃣ 完整API列表

基础操作

方法 说明 示例
screenshot() 截图,返回PIL Image img = device.screenshot()
click(x, y) 点击坐标 device.click(500, 800)
long_press(x, y, duration) 长按 device.long_press(500, 800, 1000)
swipe(x1, y1, x2, y2, duration) 滑动 device.swipe(500, 1500, 500, 500)
input_text(text) 输入文字 device.input_text('Hello')

按键操作

方法 说明
press_home() Home键
press_back() 返回键
press_menu() 菜单键
press_key(keycode) 发送按键码

APP操作

方法 说明 示例
start_app(package) 启动APP device.start_app('com.android.settings')
stop_app(package) 停止APP device.stop_app('com.android.settings')
get_current_app() 获取当前APP app = device.get_current_app()

元素查找

方法 说明
find_element(text, resource_id, class_name, content_desc) 查找单个元素
find_elements(...) 查找多个元素
click_element(...) 查找并点击元素
element_exists(...) 检查元素是否存在
wait_element(..., timeout) 等待元素出现

图像识别

方法 说明
find_image(template, threshold) 查找图片
click_image(template) 点击图片
image_exists(template) 检查图片是否存在
wait_image(template, timeout) 等待图片出现

OCR识别

方法 说明
ocr(region) OCR识别
find_text(text) 查找文字
click_text(text, timeout) 点击文字
text_exists(text) 检查文字是否存在
wait_text(text, timeout) 等待文字出现

🔌 ADB 连接方式

1️⃣ USB 连接(最简单)

from fengchao import ADBDevice

# 自动连接第一台USB设备
device = ADBDevice()

# 或指定设备序列号
device = ADBDevice(serial="A9GVVB2B30026001")

# 开始操作
device.click(500, 800)
device.swipe_up()

2️⃣ WiFi 连接(无需USB线)

方式A:USB转WiFi(推荐首次使用)

from fengchao import ADBDevice

# 1. 先用USB连接
device = ADBDevice()

# 2. 开启WiFi调试模式
device.enable_tcpip(5555)

# 3. 获取手机IP
ip = device.get_ip_address()
print(f"手机IP: {ip}")

# 4. 现在可以拔掉USB线了!

# 5. 通过WiFi连接
wifi_device = ADBDevice.connect_wifi(ip, 5555)

# 6. WiFi控制手机
wifi_device.click(500, 800)
wifi_device.swipe_up()

方式B:直接WiFi连接(手机已开启tcpip)

from fengchao import ADBDevice

# 直接用IP连接(手机需要已开启 adb tcpip 5555)
device = ADBDevice.connect_wifi("192.168.1.100", 5555)

# 操作手机
device.start_app("com.smile.gifmaker")
device.swipe_up()

WiFi连接数量

限制因素 推荐数量
单台电脑 20-50台
极限测试 100台+

主要受限于:电脑性能、网络带宽


🔄 批量操作(重点!)

串行批量(简单但慢)

from fengchao import ADBDevice

# 获取所有设备
serials = ADBDevice.list_devices()
devices = [ADBDevice(s) for s in serials]

# 逐个操作(一台一台来)
for d in devices:
    d.swipe_up()

⚡ 并行批量(同时操作,超快!)

from fengchao import ADBDevice
from concurrent.futures import ThreadPoolExecutor

# 连接所有设备
serials = ADBDevice.list_devices()
devices = [ADBDevice(s) for s in serials]

# 🚀 同时操作所有设备(不是for循环!)
with ThreadPoolExecutor(max_workers=50) as pool:
    # 所有设备同时上滑
    list(pool.map(lambda d: d.swipe_up(), devices))
    
    # 所有设备同时打开快手
    list(pool.map(lambda d: d.start_app("com.smile.gifmaker"), devices))

🎯 封装成一行代码

from fengchao import ADBDevice
from concurrent.futures import ThreadPoolExecutor

# 连接所有设备
devices = [ADBDevice(s) for s in ADBDevice.list_devices()]

def batch(func):
    """批量并行执行"""
    with ThreadPoolExecutor(max_workers=50) as pool:
        return list(pool.map(func, devices))

# 使用示例 - 一行代码控制所有设备!
batch(lambda d: d.swipe_up())                              # 全部上滑
batch(lambda d: d.press_home())                            # 全部回桌面
batch(lambda d: d.click(500, 800))                         # 全部点击
batch(lambda d: d.start_app("com.smile.gifmaker"))         # 全部打开快手
batch(lambda d: d.screenshot(f"screen_{d.serial}.png"))    # 全部截图

📊 批量获取信息

# 获取所有设备电量
results = batch(lambda d: {"serial": d.serial, "battery": d.get_battery_level()})
for r in results:
    print(f"{r['serial']}: {r['battery']}%")

# 获取所有设备信息
infos = batch(lambda d: d.get_device_info())
for info in infos:
    print(f"{info['brand']} {info['model']} - Android {info['android_version']}")

📚 完整API文档

设备连接

方法 说明 示例
ADBDevice() 自动连接第一台USB设备 device = ADBDevice()
ADBDevice(serial) 连接指定序列号设备 device = ADBDevice("ABC123")
ADBDevice.connect_wifi(ip, port) WiFi连接设备 device = ADBDevice.connect_wifi("192.168.1.100", 5555)
ADBDevice.list_devices() 列出所有已连接设备 serials = ADBDevice.list_devices()
device.enable_tcpip(port) 开启WiFi调试模式 device.enable_tcpip(5555)
device.disconnect() 断开WiFi连接 device.disconnect()

触摸操作

方法 参数 说明
click(x, y) x, y: 坐标 点击屏幕
double_click(x, y) x, y: 坐标 双击屏幕
long_press(x, y, duration) duration: 毫秒,默认1000 长按屏幕
swipe(x1, y1, x2, y2, duration) duration: 毫秒,默认300 滑动
swipe_up(duration) duration: 毫秒,默认300 上滑(刷视频)
swipe_down(duration) duration: 毫秒,默认300 下滑
swipe_left(duration) duration: 毫秒,默认300 左滑
swipe_right(duration) duration: 毫秒,默认300 右滑
device.click(500, 800)                    # 点击
device.double_click(500, 800)             # 双击
device.long_press(500, 800, duration=2000) # 长按2秒
device.swipe(100, 800, 900, 800, duration=500)  # 从左滑到右
device.swipe_up()                         # 上滑
device.swipe_down()                       # 下滑

按键操作

方法 说明
press_back() 返回键
press_home() Home键
press_menu() 菜单键
press_recent() 最近任务键
press_key(keycode) 发送任意按键码
device.press_back()       # 返回
device.press_home()       # 回到桌面
device.press_menu()       # 菜单
device.press_recent()     # 最近任务
device.press_key(24)      # 音量+ (KEYCODE_VOLUME_UP)
device.press_key(25)      # 音量- (KEYCODE_VOLUME_DOWN)
device.press_key(26)      # 电源键 (KEYCODE_POWER)

文本输入

方法 参数 说明
input_text(text) text: 要输入的文字 输入文字(仅英文数字)
clear_text(length) length: 删除字符数,默认50 清空输入框
set_clipboard(text) text: 文字内容 设置剪贴板
input_from_clipboard() - 粘贴剪贴板内容
device.input_text("hello123")      # 输入英文数字
device.clear_text()                # 清空
device.set_clipboard("中文内容")   # 支持中文
device.input_from_clipboard()      # 粘贴

屏幕操作

方法 参数 说明
screenshot(path) path: 保存路径(可选) 截图
get_screen_size() - 获取屏幕尺寸,返回 (width, height)
wake_up() - 唤醒屏幕
lock_screen() - 锁屏
is_screen_on() - 屏幕是否亮着
is_screen_locked() - 屏幕是否锁定
device.screenshot("screen.png")           # 保存截图
width, height = device.get_screen_size()  # 获取尺寸
device.wake_up()                          # 唤醒
device.lock_screen()                      # 锁屏
print(device.is_screen_on())              # True/False

APP管理

方法 参数 说明
start_app(package) package: 包名 启动APP
stop_app(package) package: 包名 停止APP
get_current_app() - 获取当前APP信息
is_app_installed(package) package: 包名 检查是否安装
install_app(apk_path) apk_path: APK路径 安装APP
uninstall_app(package) package: 包名 卸载APP
list_packages() - 列出所有已安装包
clear_app_data(package) package: 包名 清除APP数据
# 常用APP包名
KUAISHOU = "com.smile.gifmaker"      # 快手
DOUYIN = "com.ss.android.ugc.aweme"  # 抖音
WECHAT = "com.tencent.mm"            # 微信
TAOBAO = "com.taobao.taobao"         # 淘宝

device.start_app(KUAISHOU)           # 打开快手
device.stop_app(KUAISHOU)            # 关闭快手
app = device.get_current_app()       # 获取当前APP
print(app["package"])                # 包名
print(app["activity"])               # Activity

设备信息

方法 返回值 说明
get_device_info() dict 设备完整信息
get_battery_level() int 电量百分比
get_battery_status() dict 电池详细状态
get_ip_address() str 设备IP地址
get_mac_address() str MAC地址
get_brightness() int 屏幕亮度
get_density() int 屏幕密度
get_cpu_usage() float CPU使用率
get_memory_info() dict 内存信息
info = device.get_device_info()
print(f"品牌: {info['brand']}")
print(f"型号: {info['model']}")
print(f"Android版本: {info['android_version']}")
print(f"分辨率: {info['screen_resolution']}")

print(f"电量: {device.get_battery_level()}%")
print(f"IP: {device.get_ip_address()}")

文件操作

方法 参数 说明
push(local, remote) local: 本地路径, remote: 手机路径 推送文件到手机
pull(remote, local) remote: 手机路径, local: 本地路径 从手机拉取文件
list_files(path) path: 目录路径 列出目录文件
file_exists(path) path: 文件路径 检查文件是否存在
delete_file(path) path: 文件路径 删除文件
mkdir(path) path: 目录路径 创建目录
device.push("local.txt", "/sdcard/remote.txt")  # 上传
device.pull("/sdcard/remote.txt", "local.txt")  # 下载
files = device.list_files("/sdcard/")           # 列出文件
device.mkdir("/sdcard/mydir")                   # 创建目录
device.delete_file("/sdcard/mydir")             # 删除

OCR文字识别

需要安装:pip install rapidocr-onnxruntime

方法 参数 说明
init_ocr(engine) engine: "rapidocr"/"easyocr"/"paddleocr" 初始化OCR引擎
ocr_screen() - 识别屏幕所有文字
find_text(text) text: 要查找的文字 查找文字位置
find_all_text(text) text: 要查找的文字 查找所有匹配
click_text(text) text: 要点击的文字 找到文字并点击
text_exists(text) text: 要查找的文字 检查文字是否存在
wait_for_text(text, timeout) timeout: 超时秒数 等待文字出现
# 初始化OCR(首次会慢,后续复用)
device.init_ocr(engine="rapidocr")

# 识别屏幕所有文字
results = device.ocr_screen()
for r in results:
    print(f"{r['text']} @ {r['position']}")

# 查找并点击文字
device.click_text("登录")
device.click_text("确定")
device.click_text("关闭")

# 检查文字是否存在
if device.text_exists("登录成功"):
    print("登录成功!")

# 等待文字出现
device.wait_for_text("加载完成", timeout=10)

UI元素分析

方法 参数 说明
dump_ui() - 获取UI XML
get_ui_elements() - 获取所有UI元素
find_element_by_text(text) text: 文字 通过文字查找元素
find_element_by_id(resource_id) resource_id: 资源ID 通过ID查找元素
find_element_by_desc(desc) desc: 描述 通过描述查找元素
click_by_text(text) text: 文字 点击文字元素
click_by_id(resource_id) resource_id: 资源ID 点击ID元素
click_by_desc(desc) desc: 描述 点击描述元素
# 查找元素
elem = device.find_element_by_text("登录")
if elem:
    print(f"找到: {elem['text']} @ {elem['bounds']}")
    device.click(*elem["center"])  # 点击元素中心

# 通过ID查找
elem = device.find_element_by_id("com.xxx:id/btn_login")

# 通过描述查找
elem = device.find_element_by_desc("点赞")

# 直接点击
device.click_by_text("确定")
device.click_by_id("com.xxx:id/btn")
device.click_by_desc("返回")

# 打印UI树
device.print_ui_tree()

图像识别

需要安装:pip install opencv-python

方法 参数 说明
find_image(template, threshold) template: 模板图片路径, threshold: 阈值0-1 查找图片位置
find_all_images(template, threshold) 同上 查找所有匹配
click_image(template, threshold) 同上 找到图片并点击
image_exists(template, threshold) 同上 检查图片是否存在
wait_for_image(template, timeout) timeout: 超时秒数 等待图片出现
# 查找并点击图标
device.click_image("heart.png")           # 点击心形图标
device.click_image("button.png", threshold=0.8)

# 检查图标是否存在
if device.image_exists("success.png"):
    print("操作成功!")

# 等待图片出现
device.wait_for_image("loading_done.png", timeout=10)

系统设置

方法 参数 说明
set_brightness(level) level: 0-255 设置亮度
set_auto_brightness(enable) enable: True/False 自动亮度
enable_wifi() / disable_wifi() - WiFi开关
enable_mobile_data() / disable_mobile_data() - 移动数据开关
enable_airplane_mode() / disable_airplane_mode() - 飞行模式开关
set_screen_timeout(ms) ms: 毫秒 屏幕超时时间
set_density(dpi) dpi: 密度值 设置屏幕密度
reset_density() - 恢复默认密度
device.set_brightness(128)        # 设置亮度50%
device.set_auto_brightness(True)  # 开启自动亮度
device.enable_wifi()              # 打开WiFi
device.disable_wifi()             # 关闭WiFi
device.set_screen_timeout(60000)  # 屏幕1分钟后关闭

其他功能

方法 说明
open_url(url) 打开网址
call_phone(number) 拨打电话
send_sms(number, text) 发送短信
open_settings() 打开设置
get_logcat(lines) 获取日志
clear_logcat() 清除日志
reboot() 重启设备
shell(cmd) 执行Shell命令
device.open_url("https://www.baidu.com")
device.open_settings()
device.shell("pm list packages")

🎬 实战示例

批量刷快手视频

from fengchao import ADBDevice
from concurrent.futures import ThreadPoolExecutor
import time

def kuaishou_script(device):
    """快手刷视频脚本"""
    print(f"[{device.serial}] 开始")
    
    # 打开快手
    device.start_app("com.smile.gifmaker")
    time.sleep(3)
    
    # 关闭弹窗
    for text in ["关闭", "跳过", "我知道了"]:
        try:
            device.click_text(text)
            time.sleep(0.5)
        except:
            pass
    
    # 刷10个视频
    for i in range(10):
        time.sleep(5)  # 看5秒
        device.swipe_up()  # 下一个
        print(f"[{device.serial}] 视频 {i+1}/10")
    
    print(f"[{device.serial}] 完成")

# 连接所有设备
devices = [ADBDevice(s) for s in ADBDevice.list_devices()]
print(f"共 {len(devices)} 台设备")

# 并行执行
with ThreadPoolExecutor(max_workers=len(devices)) as pool:
    pool.map(kuaishou_script, devices)

print("全部完成!")

WiFi批量控制

from fengchao import ADBDevice
from concurrent.futures import ThreadPoolExecutor

# WiFi设备IP列表
DEVICE_IPS = [
    "192.168.1.101",
    "192.168.1.102",
    "192.168.1.103",
    "192.168.1.104",
    "192.168.1.105",
]

# 连接所有WiFi设备
devices = []
for ip in DEVICE_IPS:
    try:
        d = ADBDevice.connect_wifi(ip, 5555)
        devices.append(d)
        print(f"✅ 连接成功: {ip}")
    except:
        print(f"❌ 连接失败: {ip}")

print(f"共连接 {len(devices)} 台设备")

# 批量操作
def batch(func):
    with ThreadPoolExecutor(max_workers=50) as pool:
        return list(pool.map(func, devices))

# 全部回桌面
batch(lambda d: d.press_home())

# 全部打开快手
batch(lambda d: d.start_app("com.smile.gifmaker"))

# 全部刷视频
for i in range(10):
    print(f"第 {i+1} 次上滑")
    batch(lambda d: d.swipe_up())
    time.sleep(5)

📋 常用APP包名

APP 包名
快手 com.smile.gifmaker
抖音 com.ss.android.ugc.aweme
微信 com.tencent.mm
淘宝 com.taobao.taobao
拼多多 com.xunmeng.pinduoduo
京东 com.jingdong.app.mall
支付宝 com.eg.android.AlipayGphone
QQ com.tencent.mobileqq
微博 com.sina.weibo
小红书 com.xingin.xhs
B站 tv.danmaku.bili
设置 com.android.settings

🔧 常见问题

Q: WiFi连接失败?

# 1. 确保手机和电脑在同一WiFi
# 2. 先用USB连接,执行:
adb tcpip 5555
# 3. 获取手机IP后连接

Q: OCR识别慢?

# 预加载OCR引擎
device.init_ocr(engine="rapidocr")
# 后续识别会很快

Q: 如何查看设备序列号?

adb devices

Q: 批量操作有数量限制吗?

  • 推荐:20-50台/电脑
  • 极限:100台+
  • 取决于电脑性能和网络

📄 许可证

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fengchao_sdk-1.2.0.tar.gz (45.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fengchao_sdk-1.2.0-py3-none-any.whl (41.9 kB view details)

Uploaded Python 3

File details

Details for the file fengchao_sdk-1.2.0.tar.gz.

File metadata

  • Download URL: fengchao_sdk-1.2.0.tar.gz
  • Upload date:
  • Size: 45.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for fengchao_sdk-1.2.0.tar.gz
Algorithm Hash digest
SHA256 5e460ea703a2c6b57324e17dec38ac6d1560626b887067713ce08fd11ce2c00e
MD5 8b894771711734acad5a1e8b54420cac
BLAKE2b-256 f84ff361ea6e3b1a01fd87d4e1d6c5d1d6091a309fa2dce462eff776ca614fcd

See more details on using hashes here.

File details

Details for the file fengchao_sdk-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: fengchao_sdk-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 41.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for fengchao_sdk-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 20b3db7bd56f016494b42be045453748f980386d04bf285905bc113d49074a38
MD5 a7405f938bc6486bad84901c391529d3
BLAKE2b-256 5de9e8a2bc2de63dcc43fb2f8a0dbd2aceaaf32cdc3c10a91db88f4057122583

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page