PyAutoGUI简介
PyAutoGUI是什么
PyAutoGUI 是一个纯 Python 的 GUI 自动化工具,其目的是可以用程序自动控制鼠标和键盘操作,多平台支持(Windows,macOS,Linux),并在 Python 2 和 3 上运行。
PyAutoGUI 可以模拟鼠标的移动、点击、拖拽,键盘按键输入、按住操作,以及鼠标+键盘的热键同时按住等操作,可以说手能动的都可以。
PyAutoGUI 有几个特点:
1、移动鼠标并单击其他应用程序的窗口。
2、向应用程序发送点击输入(例如,填写表格)。
3、截取屏幕截图,并给出一个图像(例如,一个按钮或复选框),然后在屏幕上找到它。
4、找到应用程序的窗口,然后移动、调整大小、最大化、最小化或关闭它(目前仅限 Windows)。
5、显示警报和消息框。
PyAutoGUI适用场景
PyAutoGUI
的思路是接管鼠标、键盘使用权,可以给GUI程序自动化测试用,产生点击鼠标、敲击键盘的行为,用来控制GUI程序批量完成文件编辑、保存工作。
通过PyAutoGUI可以将手工多次重复的操作图形界面进行同样的编辑、保存的工作将其自动化。
PyAutoGUI使用
官网地址
github: https://github.com/asweigart/pyautogui
安装
windows:
python -m pip install -U pyautogui
PyAutoGUI 没有任何平台依赖,因为它用 Python 的 ctypes 模块,所以不需要 pywin32。
PyAutoGUI
依赖于pyscreeze
、pymsgbox
、pytweening
,执行后会自动安装这3个库。
macOS:
PyAutoGUI 需要 PyObjC 运行 AppKit 和 Quartz 模块。
sudo pip3 install pyobjc-core
sudo pip3 install pyobjc
sudo pip3 install pyautogui
Linux:
PyAutoGUI 需要 python-xlib(Python 2)、python3-Xlib(Python 3)
sudo pip3 install python3-xlib
sudo apt-get scrot
sudo apt-get install python-tk
sudo apt-get install python3-dev
sudo pip3 install pyautogui
快速上手
PyAutoGUI
全部操作被封装在pyautogui
单个模块中,程序中只要import pyautogui
之后便可使用。
PyAutoGUI
中函数大致分为通用功能、鼠标控制、键盘控制、消息窗口、截图5大类。
获取坐标
In [1]: import pyautogui
In [2]: pyautogui.size() # 获取屏幕尺寸(分辨率×分辨率)
Out[2]: Size(width=1920, height=1080)
In [3]: pyautogui.position() # 获取鼠标当前位置
Out[3]: Point(x=846, y=437)
In [4]: pyautogui.onScreen(100,200) # 判断坐标是否在屏幕范围内
Out[4]: True
In [5]: pyautogui.onScreen(100,2000) # 判断坐标是否在屏幕范围内
Out[5]: False
获取坐标体系后续鼠标位置、图片大小都根据这套体系定义。
PyAutoGUI
的坐标体系如下:x的取值范围是[0, 宽度分辨率-1],y的取值范围是[0, 高度分辨率-1]
移动鼠标
鼠标移动包括相对位置和绝对位置
In [7]: sizex,sizey=pyautogui.size() # 保存屏幕尺寸
# 绝对位置移动,移动至屏幕正中心,鼠标移动过渡时间duration设为1秒
In [9]: pyautogui.moveTo(sizex/2,sizey/2,duration=1)
# 相对位置移动,向右100、向上200,鼠标移动过渡时间duration设为0.5秒
In [10]: pyautogui.moveRel(100, -200, duration=0.5)
鼠标点击
鼠标点击click()
函数,可分为:mouseDown()
、mouseUp()
,另外还有rightClick()
、middleClick()
、doubleClick()
、tripleClick()
。
# 移动至屏幕中心点击一下左键,过渡时间0.5秒
In [16]: pyautogui.click(sizex/2,sizey/2, duration=0.5)
# 不指定x、y,在当前位置点击一下右键
In [17]: pyautogui.click(button='right')
# 移动至(100,100)点击3次左键,点击间隔0.1s,鼠标移动过渡时间0.5秒
In [18]: pyautogui.click(100,100, clicks=3,interval=0.1,duration=0.5)
# 移动至(100,100)点击2次右键,点击间隔0.5s,鼠标移动过渡时间0.2秒
In [19]: pyautogui.click(100,100, clicks=2,interval=0.5,button='right',duration=0.2)
滚动鼠标滚轮
# 鼠标位置不动,向上回滚2个单位,项目文档对滚动量参数说明不详
In [22]: pyautogui.scroll(2)
# 鼠标移动至(1000,700),前下滚动10个单位
# 运行发现鼠标并没有动
In [26]: pyautogui.scroll(-10,1000,700)
鼠标拖曳
指从当前位置按下鼠标,移动至目标位置再释放的过程,指定目标位置同样有绝对位置和相对位置两种方式,和移动鼠标函数很像。
drag()
函数和dragRel()
的差异待验证。
# 将鼠标从当前位置拖至屏幕中心,默认左键
In [32]: pyautogui.dragTo(sizex/2,sizey/2)
# 将鼠标从当前位置向左100像素、向右200像素拖动,过渡时间0.5秒,指定右键
In [33]: pyautogui.dragRel(-100,200,duration=0.5,button='right')
键盘控制
控制按键,也是一个press()
函数基本把活包干,按键动作往细分解包含keyDown()
和keyUp()
两个过程;在此基础上封装,有typewrite()
和hotkey()
两个高阶一点的函数,分别用于输入字符串和按快捷键。
# 键名用字符串表示,支持的所有键名,存在pyautogui.KEYBOARD_KEYS变量中,包括26个字母、数字、符号、F1~F20、方向等等所有按键
In [4]: pyautogui.press('a') # 按字母A键,字母支持大小写
# 程序向终端输入了字符a,若程序运行时输入法为中文状态,由于没有继续输入空格或回车,输入法仅列出候选字,并不会输入到终端
In [5]: a
# 传入键名列表(按键p、按键y、空格),按键之间间隔0.1秒(默认0)
In [6]: pyautogui.press(['p','y','space'], interval=0.1)
# 运行前将输入法切换到中文状态,往终端直接输入了“培养”
In [7]: 培养
# typewrite方式一:传入字符串,不支持中文字符,因为函数无法知道输入法需要什么按键才能得到中文字符
In [9]: pyautogui.typewrite('hello, PyAutoGUI!\n')
# 程序把字符串"'hello, PyAutoGUI!"和换行符输入到了终端
In [10]: hello, PyAutoGUI!
...:
# typewrite方式二:传入键名列表,按键之间间隔0.1秒(默认0)
In [11]: pyautogui.typewrite(['s','r','f','space'], interval=0.1)
# 运行前将输入法切换到中文状态,往终端直接输入了“输入法”3个字
In [12]: 输入法
# 大小写字母是自动支持的,仍然尝试一次切换到大写
In [13]: pyautogui.typewrite(['capslock','p','y'])
# CapsLock按键灯被点亮,程序往终端输入了"PY"
In [14]: PY
# hotkey屏蔽了需要反复keyDown、keyUp的细节,参数是任意个键名,而非列表
In [18]: pyautogui.hotkey('ctrl', 'shift', 'esc') #调出任务管理器
In [19]:pyautogui.hotkey('alt','ctrl','delete') # 并未调出重启界面
消息窗口
PyAutoGUI
利用pymsgbox
的功能,以JavaScript风格函数提供消息框功能,包括alert()
、confirm()
、prompt()
、password()
In [24]: pyautogui.alert(text='警告',title='PyAutoGUI消息框',button='OK')
Out[24]: 'OK' # 点击的按键被返回
In [28]: pyautogui.confirm(text='请选择',title='PyAutoGUI消息框',buttons=['1','2'
...: ,'3'])
Out[28]: '2' # 点击的按键被返回
In [30]: pyautogui.prompt(text='请输入',title='PyAutoGUI消息框',default='请输入')
Out[30]: 'input by 伪码人' # 点OK按钮后返回输入内容
In [32]: pyautogui.password(text='输入密码',title='PyAutoGUI消息框',default='',mask='*')
Out[32]: 'We_Coder' # 点OK按钮后返回输入内容
截图
PyAutoGUI
提供了screenshot()
函数进行屏幕截图,返回是Image
对象,这是在Pillow
库中定义的,因此需要安装Pillow
库才能正常工作。
# imageFilename参数,截图要保存的文件全路径名,默认`None`,不保存;
# region参数,截图区域,由左上角坐标、宽度、高度4个值确定,如果指定区域超出了屏幕范围,超出部分会被黑色填充,默认`None`,截全屏
In [41]: pyautogui.screenshot('shot.png',region=(1000,600,600,400))
Out[41]: <PIL.Image.Image image mode=RGB size=600x400 at 0x20C87497390>
PyAutoGUI
还有个图片匹配功能,它是在屏幕按像素匹配,定位图片在屏幕上的坐标位置,locateOnScreen()
函数返回region
对象,即左上角坐标、宽度、高度4个值组成的元组,再用center()
函数计算出中心坐标,locateCenterOnScreen()
函数则一步到位,返回中心坐标。如果把需要点击的菜单、按钮事先保存成图片,可以用来自动查找菜单、按钮位置,再交由click()
函数控制鼠标去点击。
loc = pyautogui.locateCenterOnScreen("icon_xx.png", region=(0, 0,sizex/2, sizey/10) ) # region参数限制查找范围,加快查找速度
pyautogui.moveTo(*loc, duration=0.5) # 移动鼠标
pyautogui.click(clicks=1) #点击
实战
假设有成千上万个图分布在几十个文件夹中,需要对每个图进行编辑操作,假使这个操作就是简单旋转下视角,再保存。
实现思路
- 找到另一个轻量看图软件,支持简单的编辑功能,正好包括旋转视角;
- 手工操作键盘鼠标,利用这个看图软件完成1个文件的编辑、保存流程;
- 将涉及操作的菜单、按钮等截图保存起来备用,将上述流程代码化,落地成果就是1个操作函数;
- 由于看图软件应需要时间,移动、点击鼠标等操作的过渡时间需要调试确定;
- 完成1个文件的操作流程后,在主函数编写文件匹配、循环等功能,在循环中调用操作函数,初期只拿10个文件批量操作,调试无误后,主函数的文件匹配修改为整个文件夹,包含成千上万个文件。
代码
import os
import pyautogui as pag
__sizex__, __sizey__ = pag.size() #获得屏幕尺寸
def cad_turn(cad_file, outd):
'''
cad_file : 要操作的CAD文件
outd : 文件输出路径
'''
c = pag.locateCenterOnScreen(__icon_open__, region=(0,0,__sizex__/10,__sizey__/20) ) # 打开图标,图标事先截图保存
pag.moveTo(*c, duration=0.05)
pag.click( button="left") # 点击打开按钮
pag.moveRel(__sizex__/4, __sizey__/4) # 确保文件打开窗口获得焦点
pag.typewrite(message=cad_file,interval=0.1) # 输入文件路径
pag.press('enter')
c = pag.locateCenterOnScreen(__icon_view__, region=(__sizex__/4, 0,__sizex__/2, __sizey__/10) ) # 旋转视图图标
pag.moveTo(*c, duration=2)
pag.click(clicks=7, interval=1, button="left") # 点击旋转视角按钮
c = pag.locateCenterOnScreen(__icon_saveas__, region=(0, 0, __sizex__/10, __sizey__/20) ) # 另存为图标
pag.moveTo(*c, duration=0.2)
pag.click( button="left") # 点击另存为按钮
pag.moveRel(__sizex__/4, __sizey__/4) # 确保文件打开窗口获得焦点
pag.typewrite(message=os.path.join(out, fbase+'-se'), interval=0.1) # 输入保存路径
pag.press('enter')
# 关闭所有可能存在的窗口,避免占用太多内存
while( True ):
try :
pag.moveTo(__sizex__/2, __sizey__/2, duration=0.3) # 延时
c = pag.locateCenterOnScreen(__icon_close__, region=(__sizex__/5, 0, __sizex__*3/5, __sizey__/20) )
pag.moveTo(*c, duration=0.1) # 移到“x”按钮
pag.click( button="left") # 点击“x”按钮
except TypeError:
break
主函数
if __name__ == "__main__":
p = r'x/y/z/CAD文件所在路径'
cad_src = glob_file_list( p, r"*.DXF") # 匹配出要操作的文件
total = len(cad_src)
if(total == 0):
print('无文件需处理,退出...')
try:
for idx,x in enumerate(cad_src, start=1):
print("[{}/{}] 处理{}...".format(idx, total, x))
cad_turn(x, "out")
except Exception as e:
print("错误:{}".format(e))
开启看图软件,输入法切换到英文状态,再运行Python程序,愉快的工作吧。