# 常见问题
- adbui 交流微信群,加 hao1032,备注 adbui,会拉入微信群
- 使用 ocr 提示出错,请在该页面最后查看使用 ocr 示例
# adbui
adbui 所有的功能都是通过 adb 命令,adbui 的特色是可以通过 xpath,ocr 获取 ui 元素。
## 安装
pip install adbui
## 要求
- 在命令中可以使用 adb 命令,即adb已经配置到环境变量
- adb 的版本最好是 >= 1.0.39,用老版本的 adb 可能会有一些奇怪的问题
- 依赖的库:lxml 解析 xml,requests 发 ocr 请求,pillow 图片处理
## 说明
- adbui 当前还在完善,bug 和建议请直接在 github 反馈
- 主要在 win7,python3 环境使用,其他环境可能有问题
## import and init
from adbui import Device
d = Device('123abc') # 手机的sn号,如果只有一个手机可以不写
## adbui 可以分为 3 个部分
**util 负责执行完整的命令**
- **cmd** 用来执行系统命令
d.util.cmd('adb -s 123abc reboot')
out = d.util.cmd('ping 127.0.0.1')
- **adb** 用来执行 adb 命令
d.util.adb('install xxx.apk')
d.util.adb('uninstall com.tencent.mtt')
- **shell** 用来执行 shell 命令
d.util.shell('pm clear com.tencent.mtt')
d.util.shell('am force-stop com.tencent.mtt')
**adb_ext 对常用 adb 命令的封装,下面列出部分操作(可在 adbui/adb_ext.py 文件自行增加需要的操作)**
- **screenshot**
d.adb_ext.screenshot() # 截图保存到系统临时目录,也可指定目录
- **click**
d.adb_ext.click(10, 32) # 执行一个点击事件
- **input**
d.adb_ext.input('adbui') # 输入文本
- **back**
d.adb_ext.back() # 发出 back 指令
**get_ui 可以通过多种方式获取 UI**
- **by attr** 通过在 uiautomator 里面看到的属性来获取
ui = d.get_ui_by_attr(text='设置', desc='设置') # 支持多个属性同时查找
ui = d.get_ui_by_attr(text='设', is_contains=True) # 支持模糊查找
ui = d.get_ui_by_attr(text='设置', is_update=False) # 如果需要在一个界面上获取多个 UI, 再次查找时可以设置不更新xml文件和截图,节省时间
ui = d.get_ui_by_attr(class_='android.widget.TextView') # class 在 python 中是关键字,因此使用 class_ 代替
ui = d.get_ui_by_attr(desc='fffffff') # 如果没有找到,返回 None;如果找到多个返回第一个
ui = d.get_uis_by_attr(desc='fffffff') # 如果是 get uis 没有找到,返回空的 list
- **by xpath** 使用 xpath 来获取
![xpath](docs/image/xpath01.png)
mic_btn = d.get_ui_by_xpath('.//FrameLayout/LinearLayout/RelativeLayout/ImageView[2]') # 获取麦克风按钮
mic_btn.click() # 点击麦克风按钮
# adbui 使用 lxml 解析 xml 文件,因此 by xpath 理论上支持任何标准的 xpth 路径。
# 这里有一篇 xpath 使用的文章:https://cuiqingcai.com/2621.html
# 另外获取的 ui 对象实际是一个自定义的 UI 实类,ui 有一个 element 的属性,element 就是 lxml 里面的 Element 对象,
# 因此可以对 ui.element 执行 lxml 的相关操作。
# lxml element 对象的文档:http://lxml.de/api/lxml.etree._Element-class.html
scan_element = ui.element.getprevious() # 获取麦克风的上一个 element,即扫一扫按钮
scan_btn = d.get_ui_by_element(scan_element) # 使用 element 实例化 UI
scan_btn.click() # 点击扫一扫按钮
- **by ocr** 使用腾讯的OCR技术来获取
![xpath](docs/image/ocr01.png)
d.init_ocr('10126986', 'AKIDT1Ws34B98MgtvmqRIC4oQr7CBzhEPvCL', 'AAyb3KQL5d1DE4jIMF2f6PYWJvLaeXEk')
# 使用 ocr 功能前,必须要使用自己的开发密钥初始化,上面的密钥是我申请的公共测试密钥,要稳定使用请自行申请
# 腾讯的 ocr 功能是免费使用的,需要自己到 http://open.youtu.qq.com/#/develop/new-join 申请自己的开发密钥
btn = d.get_ui_by_ocr(text='爱拍') # 找到爱拍文字的位置
btn.click() # 点击爱拍
## Change Log
20210425 version 4.5.0
- screenshot 和 dump xml 优先使用 adbui,预期速度有很大的提升
- 删除 Pillow 依赖
20210425 version 4.0.0
- screenshot 参数有变化,升级请谨慎
- 尝试尽量使用 minicap 截图
- 尝试不使用 pillow 功能
20210418 version 3.5.2
- 增加 minicap 截图
20210325 version 2.6
- dump xml 优先使用 --compressed 模式
20210325 version 2.4
- 修复python3.8以上版本找控件报错 RuntimeError: dictionary keys changed during iteration
20200402 version 1.0
- 修改screenshot 参数情况
- 去掉 cmd out save 函数
- init ocr支持keys传入多个key
20200328 version 0.40.1
- 修改 push pull 方法等参数
- 使用 timeout 库控制超时
- get ui by orc 去掉 min hit 参数,增加 is contains 参数
Raw data
{
"_id": null,
"home_page": "https://github.com/hao1032/adbui",
"name": "adbui",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "testing android uiautomator ocr minicap",
"author": "Tango Nian",
"author_email": "hao1032@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/db/f0/15f00e1e1d80a3299ac77412ba2c223b6ad6eb86836d936efa0b6cc1f673/adbui-4.5.22.tar.gz",
"platform": "any",
"description": "# \u5e38\u89c1\u95ee\u9898\r\n- adbui \u4ea4\u6d41\u5fae\u4fe1\u7fa4\uff0c\u52a0 hao1032\uff0c\u5907\u6ce8 adbui\uff0c\u4f1a\u62c9\u5165\u5fae\u4fe1\u7fa4\r\n- \u4f7f\u7528 ocr \u63d0\u793a\u51fa\u9519\uff0c\u8bf7\u5728\u8be5\u9875\u9762\u6700\u540e\u67e5\u770b\u4f7f\u7528 ocr \u793a\u4f8b\r\n\r\n\r\n# adbui\r\nadbui \u6240\u6709\u7684\u529f\u80fd\u90fd\u662f\u901a\u8fc7 adb \u547d\u4ee4\uff0cadbui \u7684\u7279\u8272\u662f\u53ef\u4ee5\u901a\u8fc7 xpath\uff0cocr \u83b7\u53d6 ui \u5143\u7d20\u3002\r\n\r\n## \u5b89\u88c5\r\n pip install adbui\r\n\r\n## \u8981\u6c42\r\n- \u5728\u547d\u4ee4\u4e2d\u53ef\u4ee5\u4f7f\u7528 adb \u547d\u4ee4\uff0c\u5373adb\u5df2\u7ecf\u914d\u7f6e\u5230\u73af\u5883\u53d8\u91cf\r\n- adb \u7684\u7248\u672c\u6700\u597d\u662f >= 1.0.39\uff0c\u7528\u8001\u7248\u672c\u7684 adb \u53ef\u80fd\u4f1a\u6709\u4e00\u4e9b\u5947\u602a\u7684\u95ee\u9898\r\n- \u4f9d\u8d56\u7684\u5e93\uff1alxml \u89e3\u6790 xml\uff0crequests \u53d1 ocr \u8bf7\u6c42\uff0cpillow \u56fe\u7247\u5904\u7406\r\n\r\n## \u8bf4\u660e\r\n- adbui \u5f53\u524d\u8fd8\u5728\u5b8c\u5584\uff0cbug \u548c\u5efa\u8bae\u8bf7\u76f4\u63a5\u5728 github \u53cd\u9988\r\n- \u4e3b\u8981\u5728 win7\uff0cpython3 \u73af\u5883\u4f7f\u7528\uff0c\u5176\u4ed6\u73af\u5883\u53ef\u80fd\u6709\u95ee\u9898\r\n\r\n\r\n## import and init\r\n from adbui import Device\r\n\r\n d = Device('123abc') # \u624b\u673a\u7684sn\u53f7\uff0c\u5982\u679c\u53ea\u6709\u4e00\u4e2a\u624b\u673a\u53ef\u4ee5\u4e0d\u5199\r\n\r\n\r\n## adbui \u53ef\u4ee5\u5206\u4e3a 3 \u4e2a\u90e8\u5206\r\n**util \u8d1f\u8d23\u6267\u884c\u5b8c\u6574\u7684\u547d\u4ee4**\r\n\r\n - **cmd** \u7528\u6765\u6267\u884c\u7cfb\u7edf\u547d\u4ee4\r\n \r\n d.util.cmd('adb -s 123abc reboot')\r\n out = d.util.cmd('ping 127.0.0.1')\r\n \r\n - **adb** \u7528\u6765\u6267\u884c adb \u547d\u4ee4\r\n \r\n d.util.adb('install xxx.apk')\r\n d.util.adb('uninstall com.tencent.mtt')\r\n \r\n - **shell** \u7528\u6765\u6267\u884c shell \u547d\u4ee4\r\n \r\n d.util.shell('pm clear com.tencent.mtt')\r\n d.util.shell('am force-stop com.tencent.mtt')\r\n\r\n**adb_ext \u5bf9\u5e38\u7528 adb \u547d\u4ee4\u7684\u5c01\u88c5\uff0c\u4e0b\u9762\u5217\u51fa\u90e8\u5206\u64cd\u4f5c\uff08\u53ef\u5728 adbui/adb_ext.py \u6587\u4ef6\u81ea\u884c\u589e\u52a0\u9700\u8981\u7684\u64cd\u4f5c\uff09**\r\n\r\n - **screenshot**\r\n \r\n d.adb_ext.screenshot() # \u622a\u56fe\u4fdd\u5b58\u5230\u7cfb\u7edf\u4e34\u65f6\u76ee\u5f55\uff0c\u4e5f\u53ef\u6307\u5b9a\u76ee\u5f55\r\n \r\n - **click**\r\n \r\n d.adb_ext.click(10, 32) # \u6267\u884c\u4e00\u4e2a\u70b9\u51fb\u4e8b\u4ef6 \r\n \r\n - **input**\r\n \r\n d.adb_ext.input('adbui') # \u8f93\u5165\u6587\u672c \r\n \r\n - **back**\r\n \r\n d.adb_ext.back() # \u53d1\u51fa back \u6307\u4ee4 \r\n\r\n\r\n**get_ui \u53ef\u4ee5\u901a\u8fc7\u591a\u79cd\u65b9\u5f0f\u83b7\u53d6 UI**\r\n - **by attr** \u901a\u8fc7\u5728 uiautomator \u91cc\u9762\u770b\u5230\u7684\u5c5e\u6027\u6765\u83b7\u53d6\r\n \r\n ui = d.get_ui_by_attr(text='\u8bbe\u7f6e', desc='\u8bbe\u7f6e') # \u652f\u6301\u591a\u4e2a\u5c5e\u6027\u540c\u65f6\u67e5\u627e\r\n\r\n ui = d.get_ui_by_attr(text='\u8bbe', is_contains=True) # \u652f\u6301\u6a21\u7cca\u67e5\u627e\r\n\r\n ui = d.get_ui_by_attr(text='\u8bbe\u7f6e', is_update=False) # \u5982\u679c\u9700\u8981\u5728\u4e00\u4e2a\u754c\u9762\u4e0a\u83b7\u53d6\u591a\u4e2a UI\uff0c \u518d\u6b21\u67e5\u627e\u65f6\u53ef\u4ee5\u8bbe\u7f6e\u4e0d\u66f4\u65b0xml\u6587\u4ef6\u548c\u622a\u56fe\uff0c\u8282\u7701\u65f6\u95f4\r\n\r\n ui = d.get_ui_by_attr(class_='android.widget.TextView') # class \u5728 python \u4e2d\u662f\u5173\u952e\u5b57\uff0c\u56e0\u6b64\u4f7f\u7528 class_ \u4ee3\u66ff\r\n\r\n ui = d.get_ui_by_attr(desc='fffffff') # \u5982\u679c\u6ca1\u6709\u627e\u5230\uff0c\u8fd4\u56de None;\u5982\u679c\u627e\u5230\u591a\u4e2a\u8fd4\u56de\u7b2c\u4e00\u4e2a\r\n\r\n ui = d.get_uis_by_attr(desc='fffffff') # \u5982\u679c\u662f get uis \u6ca1\u6709\u627e\u5230\uff0c\u8fd4\u56de\u7a7a\u7684 list\r\n \r\n - **by xpath** \u4f7f\u7528 xpath \u6765\u83b7\u53d6\r\n ![xpath](docs/image/xpath01.png)\r\n \r\n mic_btn = d.get_ui_by_xpath('.//FrameLayout/LinearLayout/RelativeLayout/ImageView[2]') # \u83b7\u53d6\u9ea6\u514b\u98ce\u6309\u94ae\r\n mic_btn.click() # \u70b9\u51fb\u9ea6\u514b\u98ce\u6309\u94ae\r\n \r\n # adbui \u4f7f\u7528 lxml \u89e3\u6790 xml \u6587\u4ef6\uff0c\u56e0\u6b64 by xpath \u7406\u8bba\u4e0a\u652f\u6301\u4efb\u4f55\u6807\u51c6\u7684 xpth \u8def\u5f84\u3002\r\n # \u8fd9\u91cc\u6709\u4e00\u7bc7 xpath \u4f7f\u7528\u7684\u6587\u7ae0\uff1ahttps://cuiqingcai.com/2621.html\r\n \r\n # \u53e6\u5916\u83b7\u53d6\u7684 ui \u5bf9\u8c61\u5b9e\u9645\u662f\u4e00\u4e2a\u81ea\u5b9a\u4e49\u7684 UI \u5b9e\u7c7b\uff0cui \u6709\u4e00\u4e2a element \u7684\u5c5e\u6027\uff0celement \u5c31\u662f lxml \u91cc\u9762\u7684 Element \u5bf9\u8c61\uff0c\r\n # \u56e0\u6b64\u53ef\u4ee5\u5bf9 ui.element \u6267\u884c lxml \u7684\u76f8\u5173\u64cd\u4f5c\u3002\r\n # lxml element \u5bf9\u8c61\u7684\u6587\u6863\uff1ahttp://lxml.de/api/lxml.etree._Element-class.html\r\n \r\n scan_element = ui.element.getprevious() # \u83b7\u53d6\u9ea6\u514b\u98ce\u7684\u4e0a\u4e00\u4e2a element\uff0c\u5373\u626b\u4e00\u626b\u6309\u94ae\r\n scan_btn = d.get_ui_by_element(scan_element) # \u4f7f\u7528 element \u5b9e\u4f8b\u5316 UI\r\n scan_btn.click() # \u70b9\u51fb\u626b\u4e00\u626b\u6309\u94ae\r\n\r\n - **by ocr** \u4f7f\u7528\u817e\u8baf\u7684OCR\u6280\u672f\u6765\u83b7\u53d6\r\n ![xpath](docs/image/ocr01.png)\r\n \r\n d.init_ocr('10126986', 'AKIDT1Ws34B98MgtvmqRIC4oQr7CBzhEPvCL', 'AAyb3KQL5d1DE4jIMF2f6PYWJvLaeXEk')\r\n # \u4f7f\u7528 ocr \u529f\u80fd\u524d\uff0c\u5fc5\u987b\u8981\u4f7f\u7528\u81ea\u5df1\u7684\u5f00\u53d1\u5bc6\u94a5\u521d\u59cb\u5316\uff0c\u4e0a\u9762\u7684\u5bc6\u94a5\u662f\u6211\u7533\u8bf7\u7684\u516c\u5171\u6d4b\u8bd5\u5bc6\u94a5\uff0c\u8981\u7a33\u5b9a\u4f7f\u7528\u8bf7\u81ea\u884c\u7533\u8bf7\r\n # \u817e\u8baf\u7684 ocr \u529f\u80fd\u662f\u514d\u8d39\u4f7f\u7528\u7684\uff0c\u9700\u8981\u81ea\u5df1\u5230 http://open.youtu.qq.com/#/develop/new-join \u7533\u8bf7\u81ea\u5df1\u7684\u5f00\u53d1\u5bc6\u94a5\r\n \r\n btn = d.get_ui_by_ocr(text='\u7231\u62cd') # \u627e\u5230\u7231\u62cd\u6587\u5b57\u7684\u4f4d\u7f6e\r\n btn.click() # \u70b9\u51fb\u7231\u62cd\r\n\r\n## Change Log\r\n20210425 version 4.5.0\r\n- screenshot \u548c dump xml \u4f18\u5148\u4f7f\u7528 adbui\uff0c\u9884\u671f\u901f\u5ea6\u6709\u5f88\u5927\u7684\u63d0\u5347\r\n- \u5220\u9664 Pillow \u4f9d\u8d56\r\n\r\n20210425 version 4.0.0\r\n- screenshot \u53c2\u6570\u6709\u53d8\u5316\uff0c\u5347\u7ea7\u8bf7\u8c28\u614e\r\n- \u5c1d\u8bd5\u5c3d\u91cf\u4f7f\u7528 minicap \u622a\u56fe\r\n- \u5c1d\u8bd5\u4e0d\u4f7f\u7528 pillow \u529f\u80fd\r\n\r\n20210418 version 3.5.2\r\n- \u589e\u52a0 minicap \u622a\u56fe\r\n\r\n20210325 version 2.6\r\n- dump xml \u4f18\u5148\u4f7f\u7528 --compressed \u6a21\u5f0f\r\n\r\n20210325 version 2.4\r\n- \u4fee\u590dpython3.8\u4ee5\u4e0a\u7248\u672c\u627e\u63a7\u4ef6\u62a5\u9519 RuntimeError: dictionary keys changed during iteration\r\n\r\n20200402 version 1.0\r\n- \u4fee\u6539screenshot \u53c2\u6570\u60c5\u51b5\r\n- \u53bb\u6389 cmd out save \u51fd\u6570\r\n- init ocr\u652f\u6301keys\u4f20\u5165\u591a\u4e2akey\r\n\r\n20200328 version 0.40.1\r\n- \u4fee\u6539 push pull \u65b9\u6cd5\u7b49\u53c2\u6570\r\n- \u4f7f\u7528 timeout \u5e93\u63a7\u5236\u8d85\u65f6\r\n- get ui by orc \u53bb\u6389 min hit \u53c2\u6570\uff0c\u589e\u52a0 is contains \u53c2\u6570\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "adbui \u6240\u6709\u7684\u529f\u80fd\u90fd\u662f\u901a\u8fc7 adb \u547d\u4ee4\uff0cadbui \u7684\u7279\u8272\u662f\u53ef\u4ee5\u901a\u8fc7 xpath\uff0cocr \u83b7\u53d6 ui \u5143\u7d20\u3002",
"version": "4.5.22",
"project_urls": {
"Homepage": "https://github.com/hao1032/adbui"
},
"split_keywords": [
"testing",
"android",
"uiautomator",
"ocr",
"minicap"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "dbf015f00e1e1d80a3299ac77412ba2c223b6ad6eb86836d936efa0b6cc1f673",
"md5": "20c80059bd8b3eea5c758f75cce80786",
"sha256": "4c2d101b04b761e0fa863ede46cc463731feabb71bbda40950b221df6c87f374"
},
"downloads": -1,
"filename": "adbui-4.5.22.tar.gz",
"has_sig": false,
"md5_digest": "20c80059bd8b3eea5c758f75cce80786",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 34617,
"upload_time": "2024-05-31T08:52:49",
"upload_time_iso_8601": "2024-05-31T08:52:49.481847Z",
"url": "https://files.pythonhosted.org/packages/db/f0/15f00e1e1d80a3299ac77412ba2c223b6ad6eb86836d936efa0b6cc1f673/adbui-4.5.22.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-31 08:52:49",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "hao1032",
"github_project": "adbui",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "adbui"
}