基于Pyautogui的自动脚本执行开发流程

基于Pyautogui的自动脚本执行开发流程
Photo by Markus Winkler / Unsplash

问题:

  • 如何不手动插入光标,而是自动选择输入位置输入特定的字符串?
  • 如何自动点击位置,并选择锁定?
  • 如何实现两个小的组合案例?

学习纲要:

1.鼠标移动操作

2.鼠标点击操作

3.鼠标拖动操作

4.鼠标滚动操作

5.屏幕快照与图像识别基础

6.图像识别opencv介绍

7.图像识别具体案例

9.键盘控制1

10.键盘控制2

1.鼠标移动操作

使用这个代码可以获取屏幕的高和宽像素参数。

import pyautogui
width,height=pyautogui.size()
print(width,height)

目前的屏幕像素是:宽2560,高1440.

1701870499851.png

从设置中打开屏幕查看分辨率,显示为2560*1440,显示一致。

1701870579101.png

下面学习鼠标移动到指定的屏幕位置,使用下面的代码:

import pyautogui
for i in range(3):
    pyautogui.moveTo(100,100,duration=0.1)
    pyautogui.moveTo(200,100,duration=0.2)
    pyautogui.moveTo(300,100,duration=0.3)
    pyautogui.moveTo(400,100,duration=0.4)
    pyautogui.moveTo(500,100,duration=0.5)

执行效果如下:

029.gif

pyautogui.moveTo()函数会将鼠标移动到屏幕的指定位置,函数的包含3传入参数,第一个参数和第二个参数为x和y,表示某位置在屏幕上的坐标值,函数的第三个参数为duration,表示移动鼠标到指定位置花费的时间,3个参数类型分别为整数,整数,浮点数。下面是一个1920*1080屏幕的坐标表格显示:

1701871167606.png

下面一种移动鼠标的方法是相对移动,即相对当前的位置进行移动,而上面的则对应的是鼠标的绝对移动。相对移动的方法是使用moveRel函数,使用代码如下:

import pyautogui
for i in range(3):
    pyautogui.moveRel(100,0,duration=1)
    pyautogui.moveRel(0,100,duration=1)
    pyautogui.moveRel(-100,0,duration=1)
    pyautogui.moveRel(100,100,duration=1)
    pyautogui.moveRel(-100,-100,duration=1)

执行效果如下:

028.gif

moveRel函数需要传入3个参数,第一个参数代表鼠标向右移动的像素值,第二个参数代表鼠标向下移动的像素值。分别执行的动作是:

  • 向右移动100个像素值,向下不移动。
  • 向右不移动,向下移动100个像素值。
  • 向左移动100个像素值,向下不移动。
  • 向右移动100个像素值,向下移动100个像素值。
  • 向左移动100个像素值,向上移动100个像素值。

下面我们使用一个函数来获取当前鼠标所在的坐标位置,使用如下代码:

import pyautogui
location=pyautogui.position()
print(location)

当我把鼠标放在编辑器的文件菜单按钮时,显示位置为x为304,y为325。

1701874700610.png

2.鼠标点击操作

使用pyautogui中的click函数可以执行点击特定的位置,所以需要传入点击的坐标参数,使用如下代码:

import pyautogui
pyautogui.click(x=500,y=600,button='right')

button参数是代表使用鼠标右键点击还是鼠标左键点击,右键点击则使用button='right',左键点击则使用button='left'。上面代码的意思是点击屏幕位置的坐标为(500,600)的位置,并且使用鼠标右击。默认button参数值为left,也就是默认左击。当运行程序时,鼠标移动到指定位置并且右击,执行效果如下:

030.gif

鼠标操作分解,包括每一步鼠标的操作,比如鼠标的按下与释放,鼠标左键双击,鼠标右键双击,按下鼠标中键,双击鼠标中键。分别使用如下函数:

pyautogui.mouseDown() 按下鼠标键,不释放。

pyautogui.mouseUp() 释放鼠标键。

pyautogui.doubleClick() 双击鼠标左键

pyautogui.rightClick() 双击鼠标右键

pyautogui.leftClick() 双击鼠标左键

pyautogui.middleClick() 双击鼠标中键

下面比如实现一个开启一键匹配模式的方式。

play键位置在:x=600,y=255,鼠标左键

1701949278948.png

默认是在云顶之弈模式,但是不影响我们主动点击想要的模式,然后选择召唤师峡谷:

1701949377719.png

选择步骤如下:

1701949460971.png

确认之后选择寻找对局就可以了。

1701949532360.png
import pyautogui
import time
pyautogui.click(x=600,y=255,button='left')
time.sleep(1)
pyautogui.click(x=600,y=527,button='left')
time.sleep(1)
pyautogui.click(x=530,y=909,button='left')
pyautogui.click(x=1221,y=1228,button='left')
time.sleep(3)
pyautogui.click(x=1221,y=1228,button='left')

代码,第一个click点击play按钮,然后等待程序反应,下面点击召唤师峡谷5v5模式,下面选择自选模式,然后点击确认,等待程序反应3秒,跳转到排队界面,然后点击寻找对局按钮,全程使用鼠标左键即可执行,整个程序等待时间花费5秒。执行效果如下:

在实现过程中,在最后寻找对局的时候,3秒的时候还没有出现寻找对局的按钮,此时点击就会没有作用,有可能可以加上多次点击,或者识别图像,然后来判断是否执行点击动作,这是后面可能会使用到的。目前使用的是,先等1秒,然后点击1次,如果没有效果,等待两秒,再点击一次,增加的代码如下:

import pyautogui
import time
pyautogui.click(x=600,y=255,button='left')
time.sleep(1)
pyautogui.click(x=600,y=527,button='left')
time.sleep(1)
pyautogui.click(x=530,y=909,button='left')
pyautogui.click(x=1221,y=1228,button='left')
time.sleep(1)
pyautogui.click(x=1221,y=1228,button='left')
time.sleep(2)
pyautogui.click(x=1221,y=1228,button='left')

3.鼠标拖动操作

可以实现滚动进度条和网页进度条的调整都可以滚动,使用pyautogui的函数dragTo()和dragRel()。使用方法如下:

import pyautogui
pyautogui.dragTo(x=,y=,button='left',duration=)
pyautogui.dragRel(xOffest=,yOffest=,button='left',dration=)

首先这两个函数的区别是第一个函数为绝对拖拽,第二个函数为相对拖拽。意思就是dragTo()函数传入坐标位置的值,拖动到指定的位置。而使用dragRel()函数则是拖拽到相对当前位置的其他位置,传入的参数也不同,后者传入的参数为xOffest和yOffest。参数解释如下:

  • x - 拖动的目标位置x坐标
  • y - 拖动的目标位置y坐标
  • duration - 拖动的持续时间,默认1秒
  • tween - 是否使用渐变效果,默认是匀速拖动
  • button - 鼠标按钮,默认是主鼠标按键
  • mouseDownUp - 是否在拖动前后发送鼠标按下和抬起事件

一个常见的用法示例如下:

pyautogui.dragTo(100, 200, duration=0.5, button='left')

这会使用左键拖动当前鼠标位置到坐标(100, 200),拖动时间为0.5秒。在不清楚完整上下文的情况下,建议使用类似这样的用法,指定目标位置坐标、拖动时间等参数来使用该函数。

下面实现选中文本的操作,不用手动拖鼠标,即可一致拖动。

使用代码如下:

import pyautogui
pyautogui.dragTo(x=1140,y=515,button='left',duration=2)
033.gif

下面使用dragRel()函数使用相对于当前位置进行鼠标拖拽,就是以当前鼠标在的位置为(0,0),然后相对向左下移动,所以使用负数,就会往向反的方向移动。

使用代码如下:

import pyautogui
pyautogui.dragRel(xOffset=500,yOffset=500,button='left',duration=2)

显示向左下方向拖拽,使用效果如下:

034.gif

4.鼠标滚动操作

与上面的操作相比,实际上这个操作类似于网页使用鼠标滚轮进行下滑操作,上面的操作则是使用拖拽网页右边的进度条,这个操作可以实现更多的操作。使用scroll()函数进行向上和向下滚动,传入正整数参数代表鼠标滚轮向上滚动,传入负整数嗲表鼠标滚轮向下滚动。

import pyautogui
pyautogui.scroll(200)
pyautogui.scroll(-400)

实现鼠标向上滚动200像素值,然后向下滚动400像素值,实现效果如下:

5.屏幕截图和指定图像定位操作

在pyautogui库中使用到的核心函数是,保存全屏函数,screenshot()函数会保存当前屏幕截图,然后使用save()指定保存的图片名字,第二步是使用cv2将需要点击位置的截图和全屏截图做对比,找出这个截图在全屏中的位置,然后得到坐标值x和y。

import cv2
import pyautogui
import time
time.sleep(2)
im =pyautogui.screenshot()
im.save('screen.png')

# 设置全屏截图的位置,设置需要比较图片的位置
screen=cv2.imread('./screen.png')
joinMeeting=cv2.imread('./joinmetting.png')

# 将全屏与目标图片进行匹配,result代表比较的结果,其中最大的代表最准确的位置
result=cv2.matchTemplate(joinMeeting,screen,cv2.TM_CCOEFF_NORMED)
pos_start=cv2.minMaxLoc(result)[3]

# 设置点击位置为最中间的位置。
x=int(pos_start[0]) + int(joinMeeting.shape[1] / 2)
y=int(pos_start[1]) + int(joinMeeting.shape[0] / 2)

print('找到位置,开始点击',x,y)
pyautogui.click(x,y,duration=0.25,button='left')

最后使用pyautogui库的click点击函数,并且指定使用时间0.25秒,使用左键点击。然后下一步是封装这个为一个函数,一般的场景的目的是得到x与y的值,并进行点击,所以封装了一个函数,需要传入的参数为需要点击位置的截图。

import cv2
import pyautogui
import time
def PictureClick(TargetPicture): # 如:'./joinmetting.png'
    im =pyautogui.screenshot()
    im.save('screen.png')

    # 设置全屏截图的位置,设置需要比较图片的位置
    screen=cv2.imread('./screen.png')
    joinMeeting=cv2.imread(TargetPicture)

    # 将全屏与目标图片进行匹配,result代表比较的结果,其中最大的代表最准确的位置
    result=cv2.matchTemplate(joinMeeting,screen,cv2.TM_CCOEFF_NORMED)
    pos_start=cv2.minMaxLoc(result)[3]

    # 设置点击位置为最中间的位置。
    x=int(pos_start[0]) + int(joinMeeting.shape[1] / 2)
    y=int(pos_start[1]) + int(joinMeeting.shape[0] / 2)

    print('找到位置,开始点击',x,y)
    pyautogui.click(x,y,duration=0.25,button='left')

图标是文件资源查看图标,只需要传入这个截图就可以了。

1702032573054.png

实现效果会自动点击vscode的侧边栏资源管理器图标,下面是执行效果:

035.gif

6.键盘控制1

第一个键盘控制包含两个动作,第一个动作是输入英文字符,使用函数typewrite(),会在当前光标的位置输入特定的字符;第二个动作是press()函数,代表按下键盘上的某个键,比如按下空格或者ESC键,则使用press('space')和press('esc')函数。

输入英文字符的函数不仅包括需要输入的字符,还可以控制输入单个字符的间隙时间,使用参数interval控制,如下:

import pyautogui
import time
time.sleep(2)
pyautogui.typewrite('youttype',interval=0.05)
036.gif

可以发现的是,在这里面仍然可以使用\n表示换行,也就是说可以使用字符串最后加上\n可以代替press('enter'),代表回车确认,因为换行和回车确认都是使用同一个Enter键。

然后我们使用press函数来代表按下键盘上的操作,使用如下代码:

import pyautogui
import time
time.sleep(2)
pyautogui.press('n')
pyautogui.press('i')
pyautogui.press('h')
pyautogui.press('a')
pyautogui.press('o')
pyautogui.press('1')

实现自动打字,实现效果如下所示:

037.gif

7.键盘控制2

如果我们想要组合使用热键,也就是快捷键,那么可以使用两种方法。pyautogui提供了两个函数,分别是hotkey()函数和键盘按下和释放的组合方法。

先使用hotkey函数,使用如下代码:

import pyautogui
pyautogui.hotkey('alt','space')
pyautogui.hotkey('ctrl','v')

实现将当前剪切板内的内容使用快捷键alt+空格,呼出utools工具,然后自动复制剪切板内的内容。实现效果如下:

038.gif

还可以实现视频的自动滑动。

对于键盘的控制还可以把这个过程进行分解为按下和释放,使用的函数是keyDown()和keyUp()。如果我们想要输出一个大写的字母或者美元符号,那么先使用keyDown('shirf')代表按下Shift键不释放,然后使用press('s')或者press('4')函数,代表按下小写的s或4数字键,得到的然后再使用keyUp('shift')释放Shift键,像这样,就可以完成任意种组合输入了。

使用下面的代码:

import pyautogui
import time
time.sleep(2)
pyautogui.keyDown('shift')
pyautogui.press('s')
pyautogui.press('4')
pyautogui.keyUp('shift')

实现的效果如下:

039.gif

案例演示一

到目前为止,所需要的特定坐标选择,点击,输入,快捷键组合的代码都有了,可以做很多的自动化流程了,先来做一个简单案例来学习一下,以方便以后有更多的操作空间。

得到拼多多图标按钮

1702049230169.png

然后点击多多视频

1702049321620.png

然后找到评论按钮,目标是屏幕中间,计算左边向上的坐标位置。

1702049432378.png

下一步是使用鼠标左键按住不动,然后向上拖动几个像素的单位,然后释放鼠标左键。接下来就是不断地重复这个动作,也就是使用一个while(true)循环来保持不变。可以提前将该设备所有声音关闭,方便调试,后续的流程就不增加更多工作量了。

案例演示二

改进方案:采用外部定位