现在不让篇幅太长了,分开写
5、屏幕截取
我们平时点鼠标肯定都是先看到要打开的文件才去操作的,但我们怎么让程序知道要打开的文件在哪里呢,就需要屏幕截取的功能
pyautogui.screenshot() | 截取全屏 |
pyautogui.position() | 获取鼠标当前坐标 |
getpixel((100, 500)) | 获取指定坐标rpg值(颜色) |
pyautogui.pixelMatchesColor(100,500,(12,120,400)) | 基于坐标匹配颜色 |
案例 指定截图
import pyautogui
print(pyautogui.position()) #获取鼠标当前坐标
im=pyautogui.screenshot() #截取整个屏幕
im.save("123.png") #图片保存
om=im.crop((284,416,302,438)) #选择性截取一段位置的图片
om.save("456.png") #保存截图
我们如果拿到上面的代码直接跑你会发现456.png 的截图是一个莫名其妙的位置,我们需要先给他一个准确的坐标,利用pyautogui.position()获取到准确的坐标后,再去设置截图的位置
技巧:将鼠标放到截图的位置中间最下面ctrl + F5 运行程序
说明 im.crop(())
im.crop((188,360,288,460))
刚开始不太明白这个值是要怎么写,记录一下
前面两个值是188,360指的是坐标,我们上面不是截图全屏吗,im.crop是基于全屏截图去截取的
这种在这里前两个值(鼠标位置)就是起点,而后面两个值可以理解为我们截图要先点住起点
然后向右下角拖动的过程,我上面的案例就是在前面的坐标 加了100得到 100*100大小的截图
6、屏幕识别
我们现在拿到了图片,剩下的就是从全屏来获取这个图片在那里了
方法 | 作用 |
pyautogui.locateOnScreen('1.png') | 识别单个图片坐标 |
pyautogui.locateAllOnScreen('1.png') | 识别多个图片坐标 |
案例
import pyautogui
# 图像识别(一个)
oneLocation = pyautogui.locateOnScreen('456.png')
print(oneLocation)
# 图像识别(多个)
allLocation = pyautogui.locateAllOnScreen('456.png')
print(list(allLocation))
这里我们直接用上面案例截图出来的456.png图片
返回
Box(left=188, top=360, width=100, height=100)
[Box(left=188, top=360, width=100, height=100)]
可以看到和我们上面截图的坐标、大小是一致的
7、好用的图片坐标识别
pyautogui自带的识别有时候不准,而且用截图工具的图片有时候也不好使,在网上找了个好使的备份一下
装模块
pip install numpy
pip install opencv-python
pip install opencv-contrib-python
案例
import cv2
import pyautogui
#定义主类,
class ImageMatch:
def __init__(self,Src,Srctempl):
self.src = Src
self.srctempl = Srctempl
#当前类的入口函数
def main(self):
result, imagebase, imagetempl = self.match(self.src, self.srctempl)
X,Y=self.GetPoint(result,imagebase,imagetempl)
return X,Y
#获取匹配结果
def match(self,src,srctempl):
method=5#cv::TM_CCOEFF_NORMED = 5 标准相关匹配
imagebase=cv2.imread(src)
#self.show(imagebase ,"imagebase")
# imagetempl = imagebase[15:137,134:183].copy()
imagetempl=cv2.imread(srctempl)
#self.show(imagetempl ,"imagetempl")
print('imagetempl.shape:',imagetempl.shape)
shape=imagetempl.shape
result=cv2.matchTemplate(imagebase,imagetempl,method)
print('result.shape:',result.shape)
print('result.dtype:',result.dtype)
return result,imagebase,imagetempl
#获取匹配结果2
#计算中心点位置
def GetPoint(self,result,imagebase,imagetempl):
method=5
min_max = cv2.minMaxLoc(result)
if method == 0 or method == 1: #根据不同的模式最佳匹配位置取值方法不同
match_loc = min_max[2]
else:
match_loc = min_max[3]
right_bottom = (match_loc[0] + imagetempl.shape[1], match_loc[1] + imagetempl.shape[0])
print('result.min_max:',min_max,'method=',method)
X=int(match_loc[0])+int((right_bottom[0]-match_loc[0])/2)
Y=int(match_loc[1])+int((right_bottom[1]-match_loc[1])/2)
print(X,Y)
if method==5 and float(min_max[1])< 0.5:
X=0
Y=0
#标注位置
img_disp = imagebase.copy()
cv2.rectangle(img_disp, match_loc,right_bottom, (0,255,0), 5, 8, 0 )
cv2.normalize( result, result, 0, 255, cv2.NORM_MINMAX, -1 )
cv2.circle(result, match_loc, 10, (255,0,0), 2 )
return X,Y
def jietu(select_image):
#截图是先截取当前页面的一张大图
im = pyautogui.screenshot()
im.save("global.png")
src="./global.png"
srctempl=select_image
imageMatch= ImageMatch(src,srctempl) #需要获取的小图
X,Y = ImageMatch.main(imageMatch)
return X,Y
if __name__ == '__main__':
#上面所有的东西都不用管,直接调用截图的方法 传入要检查的图片即可
#返回图片的坐标
addr = ImageMatch.jietu("1.png")
pyautogui.doubleClick(addr)
因为平时跑idea的时候笔记本噪音太大,我是用腾讯云windows server2019 跑程序的,但是相同的程序,在做笔记之前是能识别到的,现在怎么都会识别错误,打包好的程序在自己电脑上是可以的,服务器上不行,理解不得。。
server跑的
我自己电脑跑的
额,有谁碰上了一起唠唠
8、配合xlrd模块实现的快速编辑步骤
这段程序是取自B站水哥(不高兴就喝水)的案例,但我这边用的时候有很多卡住的地方,这里稍稍做点改变
import xlrd
import cv2
import pyautogui
import pyperclip
import time
#定义主类,
class ImageMatch:
def __init__(self,Src,Srctempl):
self.src = Src
self.srctempl = Srctempl
#当前类的入口函数
def main(self):
result, imagebase, imagetempl = self.match(self.src, self.srctempl)
X,Y=self.GetPoint(result,imagebase,imagetempl)
return X,Y
#获取匹配结果
def match(self,src,srctempl):
method=5#cv::TM_CCOEFF_NORMED = 5 标准相关匹配
imagebase=cv2.imread(src)
#self.show(imagebase ,"imagebase")
# imagetempl = imagebase[15:137,134:183].copy()
imagetempl=cv2.imread(srctempl)
#self.show(imagetempl ,"imagetempl")
print('imagetempl.shape:',imagetempl.shape)
shape=imagetempl.shape
result=cv2.matchTemplate(imagebase,imagetempl,method)
print('result.shape:',result.shape)
print('result.dtype:',result.dtype)
return result,imagebase,imagetempl
#获取匹配结果2
#计算中心点位置
def GetPoint(self,result,imagebase,imagetempl):
method=5
min_max = cv2.minMaxLoc(result)
if method == 0 or method == 1: #根据不同的模式最佳匹配位置取值方法不同
match_loc = min_max[2]
else:
match_loc = min_max[3]
right_bottom = (match_loc[0] + imagetempl.shape[1], match_loc[1] + imagetempl.shape[0])
print('result.min_max:',min_max,'method=',method)
X=int(match_loc[0])+int((right_bottom[0]-match_loc[0])/2)
Y=int(match_loc[1])+int((right_bottom[1]-match_loc[1])/2)
print(X,Y)
if method==5 and float(min_max[1])< 0.5:
X=0
Y=0
#标注位置
img_disp = imagebase.copy()
cv2.rectangle(img_disp, match_loc,right_bottom, (0,255,0), 5, 8, 0 )
cv2.normalize( result, result, 0, 255, cv2.NORM_MINMAX, -1 )
cv2.circle(result, match_loc, 10, (255,0,0), 2 )
return X,Y
def jietu(select_image):
#截图是先截取当前页面的一张大图
im = pyautogui.screenshot()
im.save("global.png")
src="./global.png"
srctempl=select_image
imageMatch= ImageMatch(src,srctempl) #需要获取的小图
X,Y = ImageMatch.main(imageMatch)
return X,Y
def dataCheck(sheet1):
#1、默认认为他们都是有数据的
checkCmd = True
#2、通过sheet1.nrows 来获取有效的行数
#因为我们给定的标是有标题的,所以不能小于2,最小也是要等于2
if sheet1.nrows < 2:
print("没数据啊哥")
checkCmd = False
#3、循环有效的行
i = 1
while i < sheet1.nrows:
#获取第i行,第一列的值
cmdType = sheet1.row(i)[0]
#4、多层判断,检查每一行的第二列是否合法(1-6)
#cmdType.ctype 是判断(1-6)第一列是不是数字,如果不是数字就直接报错
if cmdType.ctype != 2 or (cmdType.value != 1.0 and cmdType.value != 2.0 and cmdType.value != 3.0
and cmdType.value != 4.0 and cmdType.value != 5.0 and cmdType.value != 6.0):
print('第',i+1,"行,第1列数据有毛病")
checkCmd = False
#5、多层判断,检查第二列的数据是否匹配第一列的类型
cmdValue = sheet1.row(i)[1]
if cmdType.value ==1.0 or cmdType.value == 2.0 or cmdType.value == 3.0:
#(0 空 1 字符串 2 数字 3 日期 4 布尔值 5 error)
#6、当选项为1-3时,判断是否第二列为字符串
if cmdValue.ctype != 1:
print('第',i+1,"行,第2列数据有毛病")
checkCmd = False
#7、当模式为输入时,第二列值不能为空
if cmdType.value == 4.0:
if cmdValue.ctype == 0:
print('第',i+1,"行,第2列数据有毛病")
checkCmd = False
#8 等待模式,必须为数字才可用
if cmdType.value == 5.0:
if cmdValue.ctype != 2:
print('第',i+1,"行,第2列数据有毛病")
checkCmd = False
#9、滚轮事件,内容必须为数字
if cmdType.value == 6.0:
if cmdValue.ctype != 2:
print('第',i+1,"行,第2列数据有毛病")
checkCmd = False
i += 1
return checkCmd
def mainWork(sheet1):
pyautogui.FAILSAFE=False #防止故障
pyautogui.PAUSE = 2 #每步操作停顿时间
#循环获取有效的行
i = 1
while i < sheet1.nrows:
cmdType = sheet1.row(i)[0]
#当输入1-3时,因为都是点击,获取图片坐标,直接操作即可
if cmdType.value == 1.0 or cmdType.value == 2.0 or cmdType.value == 3.0:
#取图片名称
img = sheet1.row(i)[1].value
#获取图片在当前页面的坐标
X,Y = ImageMatch.jietu(img)
if cmdType.value == 1.0:
pyautogui.click(X,Y)
elif cmdType.value == 2.0:
pyautogui.doubleClick(X,Y)
elif cmdType.value == 3.0:
pyautogui.rightclick(X,Y)
#4 输入
elif cmdType.value == 4.0:
inputValue = sheet1.row(i)[1].value
pyperclip.copy(inputValue)
pyautogui.hotkey("ctrl","v")
pyautogui.hotkey("enter")
#5等待
elif cmdType.value == 5.0:
waitTime = sheet1.row(i)[1].value
time.sleep(waitTime)
#6 滚轮
elif cmdType.value == 6.0:
scroll = sheet1.row(i)[1].value
pyautogui.scroll(int(scroll))
i += 1
if __name__ == '__main__':
#打开execl表
file = "test.xlsx"
##打开表
wb = xlrd.open_workbook(file)
#获取文件的某一个sheet页面
sheet1 = wb.sheet_by_name("Sheet1")
#数据检查
checkCmd = dataCheck(sheet1)
#主体程序
mainWork(sheet1)
excel表模板
存在的缺陷
后面的步骤并不会等待前面的步骤执行成功,而是随着时间自动进行,没有错误修复机制,并且因为本身是模拟鼠标操作的,会占用鼠标不能做其他事情