浅谈如何使用Python控制手机(二)
作者:苏苏与阿言 发布时间:2022-05-01 20:16:28
1. 序言
每年淘宝双十一的时候,总是要刷各种各样的浏览页面,收集能量或者喵币或者什么。
那既然如此,我就总想着,能否通过Python自动调用的方式来刷网页。
2. 前置工作
本文是基于使用Python控制手机(一),默认已经安装了ADB并配置了环境变量,安装了Python环境,且在Python中安装了uiautomator2和weditor等包。
3. 打开APP
当我们使用uiautomator2包来打开某个APP时,可以通过点击屏幕特殊位置的方式来实现。但是其中存在的问题便是,可能由于我们APP图标的移动,而使得程序无法运行。健壮性和通用性不高。
其实在uiautomator2这个包中,提供了一种可以通过APP包名就可以打开特定APP的方式,例如打开和关闭淘宝。
import uiautomator2 as u2
import time
d = u2.connect() # 连接设备
d.app_start("com.taobao.taobao") # 打开淘宝
time.sleep(10) # 等待10秒钟
d.app_stop("com.taobao.taobao") # 关闭淘宝
再比如打开和关闭微信:
import uiautomator2 as u2
import time
d = u2.connect() # 连接设备
d.app_start("com.tencent.mm") # 打开微信
time.sleep(10) # 等待10秒钟
d.app_stop("com.tencent.mm") # 关闭微信
4. 获取APP的包名
有的时候,我们是不太清楚一个APP的包名的,这时我们可以通过打印设备当前信息的方式来获取APP的包名。首先我们需要将要获取的APP打开,并且保持在手机最前台
执行代码:
import uiautomator2 as u2
import time
d = u2.connect() # 连接设备
print(d.info) # 打印设备信息
输出结果如下:
{'currentPackageName': 'com.taobao.taobao', 'displayHeight': 2111, 'displayRotation': 0, 'displaySizeDpX': 393, 'displaySizeDpY': 851, 'displayWidth': 1080, 'productName': 'cannon', 'screenOn': True, 'sdkInt': 29, 'naturalOrientation': True}
Process finished with exit code 0
在所打印的Json键值对中,键currentPackageName对应的值,即为此时正在最前台的APP的包名,上述结果操作时,正在最前的APP为淘宝。
5. 打开特定页面
一般来说,如果页面切换按钮含有特定文字,我们直接通过文字进行定位是最方便的,也是最准确的,比如打开微信朋友圈:
import uiautomator2 as u2
import time
d = u2.connect() # 连接设备
d.app_start("com.tencent.mm") # 打开微信
time.sleep(2) # 等待2秒钟
d(text='发现').click() # 点击文字为“发现”的控件
time.sleep(2) # 等待2秒钟
d(text='朋友圈').click() # 点击文字为“朋友圈”的控件
因为可能存在的,APP的加载时间和对点击操作的响应时间,尽量在每次点击操作之后,为APP和手机留有足够的反应时间。值得注意的是,如果打开微信之后,恰好有个常用联系人的昵称叫做“发现”,那就可能会被误点,这种情况下我们需要使用别的定位方式来定位特定控件。
需要点击的文字如果是固定的,就可以使用d(text="XXX")来选择控件元素,其中XXX为特定的文字。如果部分文字是固定的,比如第一次元素显示文字为“我是第11932位访客”,第二次显示文字为“我是第12111位访客”,那我们可以通过d(textContains="我是第").click()来点击这个控件,或者通过d(textContains="位访客").click()来点击这个控件,这种方式就可以通过子字符串来定位特定的元素控件。
还是使用进入朋友圈举例:
import uiautomator2 as u2
import time
d = u2.connect() # 连接设备
d.app_start("com.tencent.mm") # 打开微信
time.sleep(2) # 等待2秒钟
# 点击“发现”,三选一
d(text='发现').click() # 点击文字为“发现”控件
d(textContains='发').click() # 点击带“发”的控件
# 通过WEditor获得的xpath定位
d.xpath('//*[@resource-id="com.tencent.mm:id/e8y"]/android.widget.LinearLayout[1]/android.widget.RelativeLayout[3]/android.widget.LinearLayout[1]').click()
time.sleep(2) # 等待2秒钟
# 点击“朋友圈”,三选一
d(text='朋友圈').click() # 点击文字为“朋友圈”控件
d(textContains='朋').click() # 点击带“朋”的控件
# 通过WEditor获得的xpath定位
d.xpath('//*[@resource-id="android:id/list"]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]').click()
其实还有很多各不相同的定位方式,只要能定位到唯一的特定的控件进行点击即可。例如在双十一时,我在淘宝中切换到收集喵币页面的点击事件:
import uiautomator2 as u2
import time
d = u2.connect() # 连接设备
d.app_start("com.taobao.taobao") # 打开淘宝
time.sleep(5) # 等待5秒钟
d.xpath('//*[@content-desc="双11超级喵糖"]').click() # 打开喵糖页面
6. 其它细节
在双十一淘宝活动中,打开喵糖页面,会先弹出提示是否将此页面加入收藏的弹框,点击文字为“我再想想”的按钮。注意要判断此控件是否存在,点击不存在的控件将会报错。如果不确定一个控件是否存在,又不想判断的情况下,则需要使用 try......catch...... 来将其包裹。
if len(d(textContains='我再想想')) > 0: # 如果存在此控件
d(textContains='我再想想').click() # 点击“我再想想”
点击“赚糖”控件,因为这个控件经常会被屏幕上出现的手指动画所挡住,因此需要等待:
while len(d(textContains='赚糖')) <= 0:
time.sleep(1)
d(textContains='赚糖').click()
然后点击完后等会儿,再点击“去浏览”按钮:
while len(d(textContains='去浏览')) > 0:
print("检测到浏览按钮...")
d(textContains='去浏览').click()
等待15秒(算上反应时间,需要多等一会儿)返回即可:
d.press("back") # 相当于手机返回键
7. 总结
其实具体的部分实现起来比较简单,在此总结一下uiautomator2 的其它一些功能。
关于按键:
d.press("home") # 点击home键
d.press("back") # 点击back键
d.press("left") # 点击左键
d.press("right") # 点击右键
d.press("up") # 点击上键
d.press("down") # 点击下键
d.press("center") # 点击选中
d.press("menu") # 点击menu按键
d.press("search") # 点击搜索按键
d.press("enter") # 点击enter键
d.press("delete") # 点击删除按键
d.press("recent") # 点击近期活动按键
d.press("volume_up") # 音量+
d.press("volume_down") # 音量-
d.press("volume_mute") # 静音
d.press("camera") # 相机
d.press("power") # 电源键
关于锁屏与解锁:
# 一个设备信息字典中的布尔值,为true时代表当前屏幕亮起,为false代表当前屏幕熄灭
d.info.get('screenOn')
# 仅点亮屏幕
d.screen_on()
# 点亮屏幕并解锁,注意如果有密码,则只能进入密码输入页面,需要输入密码才能解锁
d.unlock()
# 关闭屏幕
d.screen_off()
关于点击等操作(支持百分比):
# 单击屏幕
d.click(x,y) # x,y为点击坐标
# 双击屏幕
d.double_click(x, y)
d.double_click(x, y, 0.1) # 默认两个单击之间间隔时间为0.1秒
# 长按
d.long_click(x, y)
d.long_click(x, y, 0.5) # 长按0.5秒(默认)
# 滑动
d.swipe(sx, sy, ex, ey)
d.swipe(sx, sy, ex, ey, 0.5) # 滑动0.5秒(默认)
#拖动
d.drag(sx, sy, ex, ey)
d.drag(sx, sy, ex, ey, 0.5) # 拖动0.5秒(默认)
# 滑动点 多用于九宫格解锁,提前获取到每个点的相对坐标(这里支持百分比)
# 从点(x0, y0)滑到点(x1, y1)再滑到点(x2, y2)
# 两点之间的滑动速度是0.2秒
d.swipe((x0, y0), (x1, y1), (x2, y2), 0.2)
# 注意:单击,滑动,拖动操作支持百分比位置值。例:
d.long_click(0.5, 0.5) 表示长按屏幕中心
当然还有其它的一些功能,例如向上滑动屏幕,直到指定文字出现为止:
d(scrollable=True).scroll.to(text="3年级2班")
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!
来源:https://blog.csdn.net/weixin_40901068/article/details/121242489


猜你喜欢
- 01. 应用场景及定义方式应用场景在实际开发中,对象 的 某些属性或方法 可能只希望 在对象的内部被使用,而 不希望在外部被访问到私有属性
- 如何同时处理数据库和页面错误? If Err.Number = 0 And ob
- openpyxl是一个第三方库,可以处理xlsx格式的Excel文件。pip install openpyxl安装。读取Excel文件需要导
- 1 简介关键词抽取就是从文本里面把跟这篇文档意义最相关的一些词抽取出来。这个可以追溯到文献检索初期,当时还不支持全文搜索的时候,关键词就可以
- golang用来序列化的模块有很多,我们来介绍3个。json首先登场的是json,这个几乎毋庸置疑。序列化package mainimpor
- 一、ZeroMQ概述 ZeroMQ(又名ØMQ,MQ,或zmq)像一个可嵌入的网络库,但其作用就像一个并发框
- 一个小需求---实现车牌识别。目前有两个想法1. 调云在线的接口或者使用SDK做开发(配置环境和编译第三方库很麻烦,当然使用python可以
- <?php //包含一个计数器,一个提醒语句,用户ip以及自己的广告图片。 //给浏览器发送头,说我是张图片 Header
- 新建项目时,选择新建虚拟环境项目打开后,启动终端,却经常发现,并没有开启虚拟环境,导致一些包都被安装到全局环境中。一种解决办法是手动开启虚拟
- 我就废话不多说了,大家还是直接看代码吧~//isSymbol表示有无符号func BytesToInt(b []byte, isSymbol
- 1. 前言Docker在开发中使用的越来越多了,最近搞了一个Spring Boot应用,为了方便部署将Mysql也放在Docker中运行。那
- 在图书馆的检索系统中,关于图书的信息里面有一个是图书相关借阅关系图。跟这个社交网络图是一样的,反映了不同对象间的关联性。利用python画社
- 本文实例讲述了Python实现查找数组中任意第k大的数字算法。分享给大家供大家参考,具体如下:模仿partion方法,当high=low小于
- 一. 背景介绍当集团的MySQL数据库实例数达到2000+、MHA集群规模数百个时,对MHA的及时、高效管理是DBA必须面对的一个挑战。MH
- 几个星期前,SQL Server 2016的最新CTP版本已经发布了:CTP 2.4(目前已经是CTP 3.0)。这个预览版相比以前的CTP
- 前言金融行业的Python学习,不同于IT系统开发,我们并不需要达到程序员的水平。然而,学会Python可以让你实现一个人写完一个交易系统的
- 在 MySQL 查询中,可能会包含重复值。这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值。关键词 DISTINCT
- 双指数函数待拟合曲线为 y(x) = bepx + ceqximport matplotlib.pyplot as pltx = ([0.0
- 一般来说一个系统最先出现瓶颈的点很可能是数据库。比如我们的生产系统并发量很高在跑一段时间后,数据库中某些表的数据量会越来越大。海量的数据会严
- 本文实例讲述了Python多线程通信queue队列用法。分享给大家供大家参考,具体如下:queue:什么是队列:是一种特殊的结构,类似于列表