自动化测试之桌面自动化(PyAutoGUI)
1、PyAutoGUI介绍
- pyautogui是用来做GUI桌面应用自动化的Python包,功能类似于按键精灵:可以实现控制鼠标、键盘、消息框、截图、定位功能
- 官方文档: https://pyautogui.readthedocs.io/en/latest/
- pyautogui的特点:
- 纯python实现, 源码清晰可见
- 跨平台,支持linux、windows、mac
- 操作简单,会Python就行
- 需要特别注意的是:pyautogui不支持中文输入,但是可以配合pyperclip模块进行复制粘贴
安装:
# Windows安装pyautogui pip install pyautogui -i https://pypi.tuna.tsinghua.edu.cn/simple # mac安装pyautogui pip install pyobjc-core pip install pyobjc pip install pyautogui # Linux安装pyautogui #sudo apt-get install scrot python3-tk python3-dev pip install python3-xlib pip install pyautogui
2、鼠标操作
2.1、屏幕和鼠标的位置
屏幕上的位置由X和Y直角坐标表示。X坐标从左侧的0开始,向右增加。与数学不同,Y坐标从顶部的0开始,向下增加。
+---------------------------+ | | Y increases | | | | 1920 x 1080 screen | | | | V | | | | +---------------------------+ 1919, 1079
- 左上角的像素位于坐标0、0。如果屏幕的分辨率为1920 x 1080,则右下角的像素将为1919、1079(因为坐标始于0,而不是1)。
屏幕分辨率大小由该
size()函数作为两个整数的元组返回。该position()函数返回鼠标光标的当前X和Y坐标。在Python交互模式下,运行如下代码:
import os import time import pyautogui print(pyautogui.size()) # 屏幕分辨率 try: while True: x, y = pyautogui.position() # 返回鼠标的坐标 # 打印当前鼠标位置坐标 print(f\'鼠标坐标:x={x}, y={y}\') time.sleep(1) # 捕获异常 KeyboardInterrupt:用户中断执行(通常是输入^C) except KeyboardInterrupt: print(\'已退出\')
- 要检查XY坐标是否在屏幕上,请将它们(作为两个整数参数或带有两个整数的单个元组/列表参数)传递给
onScreen()函数,True如果它们在屏幕边界之内,则返回该函数False。
>>> pyautogui.onScreen(0, 0) True >>> pyautogui.onScreen(0, -1) False
2.2、鼠标移动
该moveTo()函数会将鼠标光标移至您传递的X和Y整数坐标。例如:
import pyautogui # 在每次PyAutoGUI调用(具体的操作)后就会有2秒的暂停 pyautogui.PAUSE = 2 pyautogui.moveTo(100, 200) # moves mouse to X of 100, Y of 200. pyautogui.rightClick() # 鼠标原地右键单击 pyautogui.moveTo(800, 800) # moves mouse to X of 800, Y of 800. pyautogui.rightClick() # 鼠标原地右键单击
通常,鼠标光标会立即移动到新坐标。如果您希望鼠标逐渐移动到新位置,请在移动所需的持续时间(以秒为单位)中传递第三个参数。例如:
import pyautogui pyautogui.moveTo(100, 200) # moves mouse to X of 100, Y of 200 pyautogui.rightClick() # 鼠标原地右键单击 pyautogui.moveTo(800, 800, 2) # moves mouse to X of 800, Y of 800 over 2 seconds pyautogui.rightClick() # 鼠标原地右键单击
如果要将鼠标光标相对于其当前位置(相对位置)移动几个像素,请使用该move()功能。此函数的参数与相似moveTo()。例如:
import pyautogui # 在每次PyAutoGUI调用(具体的操作)后就会有2秒的暂停 pyautogui.PAUSE = 2 pyautogui.moveTo(140*2, 80*2) # moves mouse to X of 140*2, Y of 80*2. pyautogui.rightClick() # 鼠标原地右键单击 # 从当前位置移动鼠标 pyautogui.move(188*2, 155*2) # move the mouse left 188*2, down 155*2 pixels. pyautogui.rightClick() # 鼠标原地右键单击
2.3、鼠标拖拽
PyAutoGUI dragTo()和drag()函数的参数与moveTo()和move()函数的参数相似。此外,它们还有一个button可以设置为\'left\',的关键字\'middle\',并且\'right\'在拖动时按住该鼠标键不放。例如:
import pyautogui # 在每次PyAutoGUI调用(具体的操作)后就会有2秒的暂停 pyautogui.PAUSE = 2 # button可以设为 left, middle和right pyautogui.dragTo(35*2, 35*2, button=\'left\') # drag mouse to X of 35*2, Y of 35*2 while holding down left mouse button pyautogui.drag(500, 0, 5) # 按住鼠标左键,用5秒钟把鼠标相对于(35*2, 35*2)往右移动500
2.4、鼠标点击
该click()功能模拟在鼠标的当前位置单击鼠标左键。“点击”的定义是按下按钮然后将其释放。例如:
pyautogui.click() # click the mouse
要moveTo()在点击之前合并调用,请为xand y关键字参数传递整数:
pyautogui.click(x=100, y=200) # move to 100, 200, then click the left mouse button.
要指定不同的鼠标键点击,传递\'left\',\'middle\'或 \'right\'为button关键字参数:
pyautogui.click(button=\'right\') # right-click the mouse
要进行多次点击,请将整数传递给clicks关键字参数。(可选)您可以将float或integer传递给interval关键字参数,以指定两次点击之间的暂停时间(以秒为单位)。例如:
pyautogui.click(clicks=2) # double-click the left mouse button pyautogui.click(clicks=2, interval=0.25) # double-click the left mouse button, but with a quarter second pause in between clicks pyautogui.click(button=\'right\', clicks=3, interval=0.25) ## triple-click the right mouse button with a quarter second pause in between clicks
作为便捷的快捷方式,该doubleClick()功能将双击鼠标左键。它还具有可选x,y,interval,和button关键字参数。例如:
pyautogui.doubleClick() # perform a left-button double click
import pyautogui # 在每次PyAutoGUI调用(具体的操作)后就会有2秒的暂停 pyautogui.PAUSE = 2 # pyautogui.moveTo(40*2, 130*2) # moves mouse to X of 40*2, Y of 40*2. # pyautogui.doubleClick() # perform a left-button double click # pyautogui.doubleClick(40*2, 130*2) # 等价于上面2步 pyautogui.click(40 * 2, 130 * 2, 2, button=\'left\') # 和上面等价
2.5、mouseDown()、mouseUp()
鼠标单击和拖动包括按下鼠标按钮并向上释放鼠标按钮。如果要单独执行这些操作,请调用mouseDown()和mouseUp()函数。它们具有相同的x,y和button。例如:
pyautogui.mouseDown(); pyautogui.mouseUp() # does the same thing as a left-button mouse click pyautogui.mouseDown(button=\'right\') # press the right button down pyautogui.mouseUp(button=\'right\', x=100, y=200) # move the mouse to 100, 200, then release the right button up.
2.6、鼠标滚动
可以通过调用该scroll()函数并传递整数个“单击”来滚动鼠标滚轮。在不同平台上,“单击”中的滚动量会有所不同。例如:
import pyautogui # 在每次PyAutoGUI调用(具体的操作)后就会有2秒的暂停 pyautogui.PAUSE = 2 pyautogui.click(300 * 2, 100 * 2) # 移动到(300*2, 100*2)位置 pyautogui.scroll(-1000) # 向下滚动1000格 pyautogui.scroll(1000) # 向上滚动1000格
2.7、保护措施
Python移动鼠标、点击键盘非常快,有可以导致其他应用出现问题。在这种情况下,程序可能会失控(即使是按照你的意思执行的),那时就需要中断。如果鼠标还在自动操作,就很难在程序窗口关闭它。
为了能够及时中断,PyAutoGUI提供了一个保护措施。当pyautogui.FAILSAFE = True时,如果把鼠标光标在屏幕左上角,PyAutoGUI函数就会产生pyautogui.FailSafeException异常。如果失控了,需要中断PyAutoGUI函数,就把鼠标光标在屏幕左上角。要禁用这个特性,就把FAILSAFE设置成False:
import pyautogui # 建议PAUSE和FAILSAFE一起使用 # 在每次PyAutoGUI调用(具体的操作)后就会有2秒的暂停 pyautogui.PAUSE = 2 # 将鼠标移动到左上角将引发pyautogui.FailSafeException,可终止程序,设置False禁用此特性 pyautogui.FAILSAFE = False
2.8、方法、属性汇总
| 方法或属性 | 作用 |
| pyautogui.PAUSE=2 | 操作间隔2秒 |
pyautogui.FAILSAFE = True |
开启故障安全模式 |
| pyautogui.position() | 获取当前鼠标坐标,单位为像素 |
| pyautogui.size() | 获取当前屏幕分辨率,单位为像素 |
pyautogui.onScreen(x, y) |
判断坐标是否在当前屏幕中,返回值为True和False |
| pyautogui.moveTo(x, y, duration) | 将鼠标移动到指定的 x、y 坐标 (屏幕以左上角为原点(0,0),向下y增加,向右x增加),使用duration值设置几秒后移动鼠标到指定的 x、y 坐标 |
| pyautogui.move(x, y, duration) | 相对于当前的鼠标位置移动鼠标 |
| pyautogui.dragTo(x, y, duration, button) | 默认按下左键,移动鼠标,button可设置为left, middle和right |
| pyautogui.drag(x, y, duration, button) | 默认按下左键,相对于当前位置移动鼠标 |
| pyautogui.click( x, y, clicks=1,button) | 模拟点击(默认是左键),clicks=1,2,3(单击、双击、三击) |
| pyautogui.rightClick() | 模拟右键点击 |
| pyautogui.middleClick() | 模拟中键点击 |
| pyautogui.leftClick() | 模拟左键点击 |
| pyautogui.doubleClick() | 模拟左键双击 |
| pyautogui.mouseDown(x, y, button) | 模拟在 x、y 处按下指定鼠标按键 |
| pyautogui.mouseUp(x, y, button) | 模拟在 x、y 处释放指定键 |
| pyautogui.scroll(units) | 模拟滚动滚轮。正参数表示向上滚动,负参数表示向下滚动。 |
3、键盘操作
3.1、write()
主要键盘功能是write()。此函数将在所传递的字符串中键入字符。要在按下每个字符键之间添加延迟间隔,请为interval关键字参数传递一个int或float值。pyautogui不支持中文输入,但是可以配合pyperclip模块进行复制粘贴。
import pyautogui import pyperclip # 在每次PyAutoGUI调用(具体的操作)后就会有1秒的暂停 pyautogui.PAUSE = 1 pyautogui.write(\'Hello world!\') # prints out "Hello world!" instantly pyautogui.write(\'Hello world!\') pyautogui.write(\'传智播客\') # 不支持中文,不显示 # 显示中文的操作 pyperclip.copy(\'黑马程序员\') pyautogui.hotkey(\'ctrl\', \'v\') # 按下ctrl+v快捷键 # 建议 鼠标要放在这行注释下方的代码区 再右键运行
3.2、press()、keyDown()、keyUp()
- 要按下这些键,调用
press()函数,从它传递一个字符串pyautogui.KEYBOARD_KEYS,例如enter,esc,f1。 - 该
press()函数实际上只是keyDown()和keyUp()函数的包装,它们模拟按下一个键然后释放它。这些功能可以自己调用。 - 要按类似的方式按多个键
write(),请将字符串列表传递给press()
import pyautogui # 在每次PyAutoGUI调用(具体的操作)后就会有1秒的暂停 pyautogui.PAUSE = 1 pyautogui.press(\'enter\', presses=3) # 按下并松开(轻敲)回车键(共3次) pyautogui.write([\'enter\', \'enter\', \'enter\']) # 和上面等价 pyautogui.write(\'123\') pyautogui.press(\'enter\') # 回车 # 输出 $ 或 ¥ 符号的按键 pyautogui.keyDown(\'shift\') # 按下`shift`键 pyautogui.press(\'4\') pyautogui.keyUp(\'shift\') # 松开`shift`键 # 建议 鼠标要放在这行注释下方的代码区 再右键运行
3.3、hotkey()
为了方便快捷地按下热键或键盘快捷键,hotkey()可以传递几个键字符串,这些字符串将按顺序按下,然后以相反的顺序释放。
pyautogui.hotkey(\'ctrl\', \'shift\', \'esc\')
# 等效于以下代码:
pyautogui.keyDown(\'ctrl\')
pyautogui.keyDown(\'shift\')
pyautogui.keyDown(\'esc\')
pyautogui.keyUp(\'esc\')
pyautogui.keyUp(\'shift\')
pyautogui.keyUp(\'ctrl\')
3.4、KEYBOARD_KEYS
以下是有效字符串传递给press(),keyDown(),keyUp(),和hotkey()功能:
[\'\t\', \'\n\', \'\r\', \' \', \'!\', \'"\', \'#\', \'$\', \'%\', \'&\', "\'", \'(\', \')\', \'*\', \'+\', \',\', \'-\', \'.\', \'/\', \'0\', \'1\', \'2\', \'3\', \'4\', \'5\', \'6\', \'7\', \'8\', \'9\', \':\', \';\', \'<\', \'=\', \'>\', \'?\', \'@\', \'[\', \'\\\', \']\', \'^\', \'_\', \'`\', \'a\', \'b\', \'c\', \'d\', \'e\', \'f\', \'g\', \'h\', \'i\', \'j\', \'k\', \'l\', \'m\', \'n\', \'o\', \'p\', \'q\', \'r\', \'s\', \'t\', \'u\', \'v\', \'w\', \'x\', \'y\', \'z\', \'{\', \'|\', \'}\', \'~\', \'accept\', \'add\', \'alt\', \'altleft\', \'altright\', \'apps\', \'backspace\', \'browserback\', \'browserfavorites\', \'browserforward\', \'browserhome\', \'browserrefresh\', \'browsersearch\', \'browserstop\', \'capslock\', \'clear\', \'convert\', \'ctrl\', \'ctrlleft\', \'ctrlright\', \'decimal\', \'del\', \'delete\', \'divide\', \'down\', \'end\', \'enter\', \'esc\', \'escape\', \'execute\', \'f1\', \'f10\', \'f11\', \'f12\', \'f13\', \'f14\', \'f15\', \'f16\', \'f17\', \'f18\', \'f19\', \'f2\', \'f20\', \'f21\', \'f22\', \'f23\', \'f24\', \'f3\', \'f4\', \'f5\', \'f6\', \'f7\', \'f8\', \'f9\', \'final\', \'fn\', \'hanguel\', \'hangul\', \'hanja\', \'help\', \'home\', \'insert\', \'junja\', \'kana\', \'kanji\', \'launchapp1\', \'launchapp2\', \'launchmail\', \'launchmediaselect\', \'left\', \'modechange\', \'multiply\', \'nexttrack\', \'nonconvert\', \'num0\', \'num1\', \'num2\', \'num3\', \'num4\', \'num5\', \'num6\', \'num7\', \'num8\', \'num9\', \'numlock\', \'pagedown\', \'pageup\', \'pause\', \'pgdn\', \'pgup\', \'playpause\', \'prevtrack\', \'print\', \'printscreen\', \'prntscrn\', \'prtsc\', \'prtscr\', \'return\', \'right\', \'scrolllock\', \'select\', \'separator\', \'shift\', \'shiftleft\', \'shiftright\', \'sleep\', \'space\', \'stop\', \'subtract\', \'tab\', \'up\', \'volumedown\', \'volumemute\', \'volumeup\', \'win\', \'winleft\', \'winright\', \'yen\', \'command\', \'option\', \'optionleft\', \'optionright\']
3.5、方法、属性汇总
| 方法或属性 | 作用 |
pyautogui.KEYBOARD_KEYS |
可以控制的按键名称 |
| pyautogui.write(msg) | 输入字符,不支持中文 |
| pyperclip.copy(msg) | 复制内容msg,内容可设置为中文等 |
| pyautogui.write([key1,key2]) | 键入给定键字符串,只能是英文 |
| pyautogui.press(key) | 按下并释放给定键 |
| pyautogui.keyDown(key) | 按住按键 |
pyautogui.keyUp(key) |
松开按键 |
| pyautogui.hotkey(\'ctrl\', \'v\') | 模拟按顺序按下给定键字符串,然后以相反的顺序释放 |
4、信息框操作
4.1、简介
PyAutoGUI利用PyMsgBox中的消息框功能提供了一种跨平台的纯Python方式来显示JavaScript样式的消息框,所有弹窗都会阻塞程序。
4.2、alert()
pyautogui.alert(text=\'\', title=\'\', button=\'OK\')
显示带有文本和单个“确定”按钮的简单消息框。返回单击的按钮的文本。
4.3、confirm()
pyautogui.confirm(text=\'\', title=\'\', buttons=[\'OK\', \'Cancel\'])
显示带有“确定”和“取消”按钮的消息框。可以自定义按钮的数量和文本。返回单击的按钮的文本。
4.4、prompt()
pyautogui.prompt(text=\'\', title=\'\' , default=\'\')
显示带有文本输入以及“确定”和“取消”按钮的消息框。返回输入的文本,如果单击“取消”,则返回“无”。
4.5、password()
pyautogui.password(text=\'\', title=\'\', default=\'\', mask=\'*\')
显示带有文本输入以及“确定”和“取消”按钮的消息框。输入的字符显示为*。返回输入的文本,如果单击“取消”,则返回“无”。
4.6、消息框方法汇总
| 方法 | 作用 |
pyautogui.alert() |
简单提示消息框 |
| pyautogui.confirm() | 多按钮消息框 |
| pyautogui.prompt() | 明文输入消息框 |
| pyautogui.password() | 密文输入消息框 |
5、截图定位操作
5.1、简介
- PyAutoGUI可以截取屏幕截图,将其保存到文件中,并在屏幕上定位图像。如果您有一个很小的图像,例如需要单击一个按钮并想在屏幕上找到它的按钮,这很有用。
这些功能由PyScreeze模块提供,该模块随PyAutoGUI一起安装。
-
屏幕截图功能需要Pillow模块。
- OS X使用操作系统
screencapture随附的命令。 - Linux使用该
scrot命令,可以通过运行进行安装:sudo apt-get install scrot
- OS X使用操作系统
5.2、screenshot()
- 调用
screenshot()将返回一个Image对象。传递文件名字符串将把屏幕截图保存到文件中,并将其作为Image对象返回。 -
region如果您不需要整个屏幕的屏幕截图,则还有一个可选的关键字参数。您可以传递区域的左侧,顶部,宽度和高度的四整数元组来捕获。
import pyautogui # 截全屏并设置保存图片的位置和名称 im1 = pyautogui.screenshot(\'./images/screenshot1.png\') print(im1) # 打印图片的属性 # 不截全屏,截取区域图片。截取区域region参数为:左上角XY坐标值、宽度和高度 pyautogui.screenshot(\'./images/screenshot2.png\', region=(0, 0, 300, 400))
5.3、定位功能
5.3.1、locateOnScreen
- PyAutoGUI可以通过图片,在屏幕上定位图像所在的位置。
- 调用
locateOnScreen(图片路径)函数以获取屏幕图像坐标,返回值为4整数元组:(左,上,宽度,高度),可以传递此元组center()以获取该区域中心的X和Y坐标。如果没有找到,返回None
import pyautogui # 可以通过图片,在屏幕上定位图像所在的位置 # 找到返回的是一个4边距元组 (top, left, width, height),没有找到返回None # 全屏幕搜素 rect = pyautogui.locateOnScreen(\'./images/computer.png\') print(rect) # Box(left=36, top=222, width=84, height=120) if rect: # rect不为None才往下操作 print(rect[0], rect[1], rect[2], rect[3]) # 36 222 84 120 x, y = pyautogui.center(rect) # 获取rect该区域中心的X和Y坐标 print(x, y)
5.3.2、locateCenterOnScreen
locateCenterOnScreen()函数结合locateOnScreen()和center()
import pyautogui # 可以通过图片,在屏幕上定位图像所在的位置,该区域中心的X和Y坐标 point = pyautogui.locateCenterOnScreen(\'./images/computer.png\') print(point) if point: # point不为None才往下操作 x, y = point print(x, y)
5.4、提高定位精度
可选的confidence关键字参数指定函数在屏幕上定位图像的精度
- 这个参数范围和环境有关,需要在0~1之间调试最佳参数
- 需要安装OpenCV才能使
confidence关键字起作用:pip install opencv-python
import pyautogui # 可以通过图片,在屏幕上定位图像所在的位置 # 找到返回的是一个4边距元组 (top, left, width, height),没有找到返回None # 全屏幕搜素 rect = pyautogui.locateOnScreen(\'./images/x3.png\', confidence=0.6) print(rect)
5.5、加速定位
- 指定搜索区域
pyautogui.locateOnScreen(\'./images/computer.png\', region=(0, 0, 400, 400))
- (可选)可以传递
grayscale=True给locate函数以略微加快速度(大约30%-ish)。这会使图像和屏幕截图的颜色降低饱和度,从而加快定位速度。
pyautogui.locateOnScreen(\'./images/computer.png\', grayscale=True)
5.6、方法汇总
| 方法 | 汇总 |
| pyautogui.screenshot() | 截屏 |
| pyautogui.locateOnScreen() | 从屏幕寻找图片位置,返回一个4边距坐标 |
| pyautogui.locateCenterOnScreen() | 从屏幕寻找图片位置,返回中心点坐标 |
6、案例:自动写字表白
- 自动打开记事本
- 自动写字
如花,今晚看电影如何?今晚刚好敲完代码!!,每隔0.3秒写一个字 - 自动保存文件
- 自动关闭记事本
参考代码:
import pyautogui import os import multiprocessing import time import pyperclip # 进程处理函数 def start_notepad(): os.system(\'notepad\') # 阻塞,不按关闭,不会往下执行 def write_word(words, t=0.1): for v in words: pyperclip.copy(v) pyautogui.hotkey(\'ctrl\', \'v\') time.sleep(t) def main(): # 1. 创建进程 p = multiprocessing.Process(target=start_notepad) # 2. 进程启动 p.start() time.sleep(1) # 2.1 定位软件 point = pyautogui.locateCenterOnScreen(\'./love_imgs/note2.png\', confidence=0.6) print(point) pyautogui.click(point.x, point.y) time.sleep(0.5) # 3. 写字 write_word(\'如花,今晚看电影如何?今晚刚好敲完代码!!\', 0.3) # 4. 保存文件 pyautogui.hotkey(\'ctrl\', \'s\') time.sleep(1) # 5. 写字,保存文件的文件名 write_word(\'表白记录.txt\', 0.2) # 6. 回车 pyautogui.press(\'enter\') # 7. 按个y确定保存 pyautogui.press(\'y\') time.sleep(1) # 8. 关闭当前的pycharm pyautogui.hotkey(\'alt\', \'f4\') time.sleep(1) # 9. 关闭记事本软件 pyautogui.hotkey(\'alt\', \'f4\') if __name__ == \'__main__\': main()