使用 pyautogui 进行跨平台的 GUI 自动化操作
有个朋友最近问我有没有推荐 GUI 桌面应用自动化的技术,我只能回答他:不好意思,这个真有,他是 pyautogui。主要有三大特征:
- 纯纯的 python, 源码一览无余;
- 跨平台,linux, windows, mac 他都能上;
- 操作简单,会代码就能上手。
pyautogui 进行 web 自动化文件上传不要太简单。熟悉 web 自动化测试的大佬应该都懂,当采用 js 调用原生控件进行文件上传的时候,最常用的是使用 pywin32 等系统交互库。
当看到 pywin32 那丑陋的 api 封装只能爆粗口。就为了输入一个文件地址,需要整这么多莫名其妙的代码(看不懂没关系,只需要看代码行数就够了):
我们来看看使用 pyautogui 多么简单:
#输入文件名
pyautogui.write(r'd:\demo.txt')
# 回车
pyautogui.press('enter', presses=2)
pyautogui 不支持中文输入。但是可以复制剪切板,间接实现中文输入:
import pyperclip
pyperclip.copy('D:\用户.html')
time.sleep(2)
pyautogui.hotkey('ctrl', 'v')
pyautogui.press('enter', presses=2)
跨平台的使用和安装
上面的代码在 mac ,linux 和 windows 上是通用的,只是在 mac 和 linux 下需要安装额外的依赖。
windows 安装不需要其他依赖,直接使用了 python 自带的 ctypes 模块:
pip install pyautogui
mac 安装需要 PyObjC 模块:
pip3 install pyobjc-core
pip3 install pyobjc
pip3 install pyautogui
linux 需要依赖 python3-Xlib 或者 python-xlib(python2):
pip3 install python3-xlib
pip3 install pyautogui
linux 如果没有安装相关 python 库可能会报错。 Debian 系发行版(其他发行版自行了解)你可能需要输入:
sudo apt-get install scrot
sudo apt-get install python3-tk
sudo apt-get install python3-dev
鼠标操作
pyautogui 并不需要去解析各平台的控件结构,他的元素定位都是基于坐标的。所以不论你是通过手工截图测量,还是通过自动化工具获取,只要你能拿到坐标,你就能进行元素操作。
获取坐标
import pyautogui as ui
# 获取屏幕大小
size = ui.size()
# 获取现在鼠标位置
p = ui.position()
# 坐标是否超出屏幕范围
if_on = ui.onScreen(*p)
鼠标移动
ui.moveTo(x/2, y/2, duration=2, tween=easeInCirc)
参数说明:
- x, y 坐标
- duration 持续秒数,默认是瞬间完成
- tween 特效,一般没什么用。
鼠标拖拽, 移动到指定的坐标
ui.dragTo(500, 500)
百发百中的射箭游戏
import random
import time
import pyautogui as ui
x, y = ui.position()
target = (800, 800)
for i in range(10):
rand_x = random.randint(0, x)
rand_y = random.randint(0, y)
# 随机生成位置
print(rand_x, rand_y)
ui.moveTo(rand_x, rand_y)
# 移动到目标位置
ui.dragTo(target, duration=0.2)
time.sleep(1)
效果:
相对移动
ui.move(-500, duration=1)
ui.move(yOffset=-400, duration=1)
ui.move(500, duration=1)
ui.move(yOffset=400, duration=1)
相对移动的小游戏
start = 20
add_point = 10
duration = 0.5
for i in range(10):
if i % 2 == 0:
ui.drag(start, duration=duration)
ui.drag(yOffset=start, duration=duration)
else:
ui.drag(-start, duration=duration)
ui.drag(yOffset=-start, duration=duration)
start += add_point
效果:
点击操作
ui.click(x=None,
y=None,
clicks=1, # 点击次数
interval=0.0, # 间隔时间
button='right', # 右键
duration=0.0) # 持续时间
通过 click 进一步封装了 leftClick, rightClick, middleClick, doubleClick, tripleClick
scroll 窗口滚动操作
窗口滚动,但是封装的滚动感觉比较鸡肋,他是以鼠标点击次数为单位的,所以不知道会滚动到什么位置。
pyautogui.scroll(10) # 向上滚动 10 个 clicks
>>> pyautogui.scroll(-10) # # 向下滚动 10 个 clicks
>>> pyautogui.scroll(10, x=100, y=100) # 移动到位置再滚动
使用 drag 和 dragTo 会更加方便一点,还是以坐标为依据,通过操作鼠标中键来实现窗口滚动,比如这个例子是 scroll 和 drag 的对比:
x, y = ui.size()
ui.scroll(-100)
time.sleep(1)
ui.scroll(100)
time.sleep(1)
ui.dragTo(y=y, button='middle') # 滚动到窗口底部
效果:
键盘操作
输入框输入
# 输入yuz, 每个字母时间间隔 0.2 s
pyautogui.write("yuz",interval=0.2)
注意:pyautogui 并不支持输入框自动聚焦,所有输入之前先要点击输入框位置。
按下键盘 press
press('enter', presses=1, interval=0.0)
相当于鼠标操作的 click, 可以输入键盘上的按键, 比如 shift 键,enter 键。所有的按键可以查看源码当中的 KEYBOARD_KEYS 或者 KEY_NAMES。
参数:
- presses, 操作按键次数
- interval, 每次按键的间隔时间
所有按键列表:
热键 hotkey
ui.hotkey('ctrl', 'shift', 'esc')
keyUp, keyDown
这是 press 的分解动作,相当于鼠标的 mouseUp 和 mouseDown。上面热键的操作方式可以分解成:
ui.keyDown('ctrl') # 按下 ctrl
ui.keyDown('shift') # 按下 shift
ui.keyDown('esc') # 按下 esc
ui.keyUp('esc') # 释放 ctrl
ui.keyUp('shift') # 释放 shift
ui.keyUp('ctrl') # 释放 esc
图像识别
坐标定位这种方式为通用性打下了基础,让 pyautogui 可以轻松做到跨平台。但是实际操作过程中很难清除的知道某个要操作的控件的确切位置,因为每次打开相同的页面都有可能是变动的。pyautogui 给出的解决方案非常简单粗暴,使用图像识别,返回在屏幕中的坐标位置,在通过坐标进行处理。
locateCenterOnScreen
返回被识别图像的中心坐标。参数说明:
- 必传参数,图片路径;
- confidence, 识别精度,需要安装 opencv 才能使用;
- grayscale, 灰度级别,能够提升识别速度。
locateCenterOnScreen('img/seven.png', confidence=0.7, grayscale=True)
现阶段图像识别的结果并不理想,基于图像识别的使用还存在以下问题:
识别不到指定元素;
识别精度不够;
查找速度比较慢
需要用到重型的 opencv 库, 或许可以尝试换用其他库。
需要提前准备被识别的图片,如果操作元素多,手动处理素材会怀疑人生。
所以 uiautogui 适合的场景是跨平台的少量原生控件交互,如果要对原生应用控件大量操作,还是换用其他工具比较合适。
基于图像识别的具体例子:
import time
import pyautogui as ui
time.sleep(3)
seven = ui.locateCenterOnScreen('img/seven.png', confidence=0.7, grayscale=True)
mult = ui.locateCenterOnScreen('img/multipy.png', confidence=0.7, grayscale=True)
two = ui.locateCenterOnScreen('img/two.png', confidence=0.7, grayscale=True)
equal = ui.locateCenterOnScreen('img/equal.png', confidence=0.7, grayscale=True)
ui.click(*seven)
ui.click(*mult)
ui.click(*two)
ui.click(*equal)
效果:
后期可以期待的
pyautogui 现阶段最欠缺的是无法获取窗口。但是可以通过 PyGetWindow 等工具进行集成。你可以通过官网 roadmap 和 常见问答 查看今后的发展路径。
使用 pyautogui 进行跨平台的 GUI 自动化操作的更多相关文章
- AutoIt 软件自动化操作
AutoIt 目前最新是v3版本,这是一个使用类似BASIC脚本语言的免费软件,它设计用于Windows GUI(图形用户界面)中进行自动化操作. 它利用模拟键盘按键,鼠标移动和窗口/控件的组合来实现 ...
- Python 编程快速上手 第十八章 用 GUI 自动化控制键盘和鼠标
前言 这一章节讲述了如何实现 GUI 自动化,首先讲了一些处理异常状况的方法,然后是关于 GUI 自动化的内容,主要有三个部分: 控制鼠标 图像识别 控制键盘 下面引用一段话: 请将 GUI 自动化看 ...
- 操作 AutoIT:界面与自动化操作结合来简化日常劳动: .Net Reactor验证License,设置License,创建License,截图AutoIt自动化实现。(六)
自动化操作的稳定性,便利性虽然已经满足了要求,但是页面上呈现的按钮太多了,可以做的更加简单一些. 1. 简化页面的按钮,把5个按钮减少至3个,把Display HID按钮功能整合到create lic ...
- AutoIt脚本在做自动化操作的时候,如何进行错误捕获?
我的自动化脚本在运行的时候,会生成一个界面,点击该页面上的按钮能够进行自动化操作. 经常遇到的一个问题是: 脚本运行一半,GUI程序出现了异常情况,这个时候,再次点击生成的界面上的按钮,不会有任何反应 ...
- splinter python浏览器自动化操作,模拟浏览器的行为
Splinter可以非常棒的模拟浏览器的行为,Splinter提供了丰富的API,可以获取页面的信息判断当前的行为所产生的结果 最近在研究网站自动登录的问题,涉及到需要实现浏览器自动化操作,网上有 ...
- Python实现浏览器自动化操作
Python实现浏览器自动化操作 (2012-08-02 17:35:43) 转载▼ 最近在研究网站自动登录的问题,涉及到需要实现浏览器自动化操作,网上有不少介绍,例如使用pamie,但是只是 ...
- [转载]Python实现浏览器自动化操作
原文地址:Python实现浏览器自动化操作作者:rayment 最近在研究网站自动登录的问题,涉及到需要实现浏览器自动化操作,网上有不少介绍,例如使用pamie,但是只是支持IE,而且项目也较久没 ...
- Saltstack自动化操作记录(2)-配置使用 【转】
之前梳理了Saltstack自动化操作记录(1)-环境部署,下面说说saltstack配置及模块使用: 为了试验效果,再追加一台被控制端minion机器192.168.1.118需要在master控制 ...
- Saltstack自动化操作记录(1)-环境部署【转】
早期运维工作中用过稍微复杂的Puppet,下面介绍下更为简单实用的Saltstack自动化运维的使用. Saltstack知多少Saltstack是一种全新的基础设施管理方式,是一个服务器基础架构集中 ...
随机推荐
- TortoiseSVN的使用,以及冲突解决办法
接下来,试试用TortoiseSVN修改文件,添加文件,删除文件,以及如何解决冲突等. 添加文件 在检出的工作副本中添加一个Readme.txt文本文件,这时候这个文本文件会显示为没有版本控制的状态, ...
- 5. iphone 的:active样式
如果给按钮定义 :hover 样式,在 iPhone 上按钮点击一次是 hover 态,再点击一次 hover 态才会消失,这不是我们想要的,继而想通过定义 :active 样式来实现按钮按下时的效果 ...
- Mysql使用终端操作数据库
使用终端操作数据库 1.如何查看有什么数据库? show databases; 2.如何选择数据库? use databasesName; 3. ...
- Springboot:员工管理之公共页面提取 高亮显示(十(5))
把顶部和左侧的公共代码分别放到header.html和left.html中 顶部代码:resources\templates\header.html 主内容展示: <!DOCTYPE html& ...
- 详解数组分段和最大值最小问题(最小m段和问题)
数组分段和最大值最小问题(最小m段和问题) 问题描述 给定n个整数组成的序列,现在要求将序列分割为m段,每段子序列中的数在原序列中连续排列.如何分割才能使这m段子序列的和的最大值达到最小? 清洁工:假 ...
- PE文件学习(2)导入表导出表
转自:evil.eagle https://blog.csdn.net/evileagle/article/details/12176797 导出表是用来描述模块中的导出函数的结构,如果一个模块导出了 ...
- linux下批量删除文件
1. 在linux批量删除多级目录下同一格式的文件,可采用find + exec命令组合: 如在删除old目录下的,所有子目录中,后缀为.l的文件方法为: find old -type f -name ...
- ajax轮询思路
以我个人理解 ,ajax短轮询就是用定时器,定时请求数据库,然后把有用的数据做处理 ajax长轮询恩 就是在 ajax回调函数,继续调用ajax请求
- java 8中构建无限的stream
目录 简介 基本使用 自定义类型 总结 java 8中构建无限的stream 简介 在java中,我们可以将特定的集合转换成为stream,那么在有些情况下,比如测试环境中,我们需要构造一定数量元素的 ...
- 【已解决】React项目中按需引入ant-design报错TypeError: injectBabelPlugin is not a function
react项目中ant-design按需加载,使用react-app-rewired的时候报错 运行npm start或者yarn start报如下错误: TypeError: injectBabel ...