分享一个好玩且有用的东西,遥想某人当年为了偷点懒,在不会爬虫和网页分析的时候,硬是熬夜整了个自动办公的脚本。
假设你需要不停地进行“刷新页面、识别按钮、点击、输入账号密码、提交”这样的重复劳动,那么或许你也可以利用这个脚本偷懒。
该脚本主要是通过“图像识别 + 键鼠模拟”实现的,因此非常好改成自己需要的亚子,当然了,这也意味着该脚本功能单一且很难zhuangbility。
首先,简单介绍一下功能实现思路和代码逻辑。在电脑上点击某个地方或按钮,需要1.识别点击内容;2.鼠标移过去并点击。
1、识别点击内容
从屏幕中识别是否有点击目标,利用“截图全屏 + 灰度模板匹配”,判断屏幕上是否存在指定按钮或弹窗,参数为预先截图保存的按钮图像,返回值包含匹配相似度最大值、坐标、图片宽高,当max_val >= 0.9时代表成功识别到对应按钮。
利用返回值max_val判断页面中是否存在目标按钮后,需要计算鼠标点击的位置。这里还是利用shibie_anniu()函数的返回值去计算的。计算逻辑是:按钮左上角坐标 + 图片一半宽 / 高 = 按钮正中心坐标。
# 计算按钮中心点位置函数def jisuan_center(max_val, min_loc, max_loc, twidth, theight): # 计算出中心点 top_left = max_loc bottom_right = (top_left[0] + twidth, top_left[1] + theight) tagHalfW=int(twidth/2) tagHalfH=int(theight/2) tagCenterX=top_left[0]+tagHalfW tagCenterY=top_left[1]+tagHalfH return tagCenterX, tagCenterY
2、鼠标移过去并点击
得到需要点击的位置后,操控鼠标移到该位置并左键点击。
#左键点击屏幕上的这个位置def dianji(tagCenterX,tagCenterY): pyautogui.click(tagCenterX,tagCenterY,button='left')
3、操控键盘输入内容
除了点击动作,假设要重复输入固定的内容,也是先识别到输入框,点击后,键盘输入内容。其中interval=0.1是字符输入时间间隔。
#输入内容def shuru(input_text):# pyautogui.keyDown('shift')#按下shift# pyautogui.typewrite(input_text.lower())#确保为英文小写# pyautogui.keyUp('shift') pyautogui.typewrite(input_text,interval=0.1)
接下来将上述函数进行组合封装,即可得到点击屏幕上指定按钮和在文本框输入指定内容两个功能函数。
4、点击屏幕上指定按钮
函数中sleep(3)表示等待3秒,防止网页未及时刷新导致后续无法识别;将鼠标移到屏幕某个角落,是为了防止因鼠标停留在待识别位置导致后续无法识别出目标按钮;
#点击屏幕按钮def dianji_anniu(anniu, ture_shuchu, fale_shuchu): target_1 = cv2.imread(anniu, cv2.IMREAD_GRAYSCALE) mn_val_1, max_val_1, min_loc_1, max_loc_1, twidth_1, theight_1 = shibie_anniu(target_1) if max_val_1 >= 0.9: tagCenterX_1, tagCenterY_1 = jisuan_center(max_val_1, min_loc_1, max_loc_1, twidth_1, theight_1) dianji(tagCenterX_1, tagCenterY_1) print(ture_shuchu) else: print(fale_shuchu)# 将鼠标移动到屏幕左上角 sleep(2) pyautogui.moveTo(5, 5,duration=0.25) sleep(3)
#点击登录dianji_anniu('登录.png', '点击登录', '未识别到')
其中,'登录.png'为需要点击位置的按钮截图保存位置,'点击登录'和'未识别到'为操作的提示信息,不需要可直接使用空格' '。
#点击并输入内容def dianji_and_shuru(wenbenkuang, inputL, true_shuchu, false_shuchu): target_4 = cv2.imread(wenbenkuang, cv2.IMREAD_GRAYSCALE) mn_val_4, max_val_4, min_loc_4, max_loc_4, twidth_4, theight_4 = shibie_anniu(target_4) if max_val_4 >= 0.9: tagCenterX_4, tagCenterY_4 = jisuan_center(max_val_4, min_loc_4, max_loc_4, twidth_4, theight_4) dianji(tagCenterX_4, tagCenterY_4) shuru(inputL) print(true_shuchu) else: print(false_shuchu) # 将鼠标移动到屏幕左上角 sleep(2) pyautogui.moveTo(5, 5,duration=0.25) sleep(3)
#输入账号dianji_and_shuru('账号.png','123456789','已输入账号','未识别到')
其中,'账号.png'为输入框截图保存位置,'123456789'为需要输入的内容,'已输入账号'和'未识别到'为操作的提示信息,不需要可直接使用空格' '。
6、判断页面是否存在某个按钮
这段代码和dianji_anniu()类似,不同点在于返回的是True或False,用于实现“某个按钮存在时才进行下一步操作”。
# 查询内容是否存在def whether_exists(target, true_shuchu, false_shuchu): targetL = cv2.imread(target, cv2.IMREAD_GRAYSCALE) mn_val, max_val, min_loc, max_loc, twidth, theight = shibie_anniu(targetL) if max_val >= 0.9: print(true_shuchu) returnTrue else: print(false_shuchu) returnFalse # 将鼠标移动到屏幕左上角 sleep(2) pyautogui.moveTo(5, 5,duration=0.25) sleep(3)
#检测账号是否在登陆状态zhanghao = whether_exists("账号在线.png", '账号在登陆状态', '账号已退出')
其中"账号在线.png"图片使用类似以下这种图片,纯模拟人眼判断账号是否在线hhh,想想那晚为自己的灵机一动还高兴半天hhh。
7、使用!!
核心功能实现后,接下来就是具体的流程功能模拟实现,假设要实现一个检测账号是否登录,如果未登录则登录的功能。
下面为脚本内容,将上述函数全部复制到脚本中对应位置,log_account()为实现的具体业务函数,在设置屏幕永不息屏后,在Python中运行该脚本,随后打开待操作页面,就可以美美玩手机去了嘿嘿。
from time import sleepimport pyautoguiimport pyscreezeimport cv2import schedule######################################################################################################################### 识别屏幕按钮函数# 计算按钮中心点位置函数# 左键点击屏幕上的这个位置# 输入内容# 查询内容是否存在# 点击屏幕按钮# 点击并输入内容######################################################################################################################### 具体业务1# 检测账号是否登出,若账号未登入则登录账号def log_account(): # 将鼠标移动到屏幕左上角 pyautogui.moveTo(5, 5, duration=0.25) sleep(2) #检测账号是否在登陆状态 zhanghao = whether_exists("账号在线.png", '账号在登陆状态', '账号已退出') if not zhanghao: #点击登录 dianji_anniu('登录.png', '点击登录', '未识别到') #输入账号,密码 dianji_and_shuru('账号.png','XXXXXX','已输入账号','未识别到') dianji_and_shuru('账号密码.png', 'XXXXXX', '已输入账号密码', '未识别到') #点击登录 dianji_anniu('登录账号.png', '点击登录账号', '未识别到')if __name__ == '__main__':# 先设置从不熄屏,输入法设置为英文# 运行程序后打开操作页面页面,将鼠标放在屏幕右下角的区域# 如果识别不到按钮,可能是屏幕大小的问题,将识别图片重新截图 schedule.every(10).minutes.do(log_account) # 每隔10分钟执行一次任务# schedule.every(10).minutes.do(task2) # 每隔10分钟执行一次任务# 无限循环,持续执行定时任务 whileTrue: schedule.run_pending()
一个简单的自动办公脚本到这里结束。
8、附言
贴心的我还考虑到假设是那种很多个相同选择按钮的该咋办(其实是我遇到了hhh),类似以下这种:
假设要选择蓝色色块对应的“选择”按钮,那黄色色块对应的“选择”按钮就是干扰。
问题不大,很好解决,就是先找到蓝色色块对应的选项,再在该范围内找到“选择”,最后鼠标点击时进行一波位置计算即可,函数代码如下:
#先匹配出"XX科目"在屏幕中的位置,再计算"查看详情"的位置def dianji_anniu_2(image1, image2, ture_shuchu, fale_shuchu): target1 = cv2.imread(image1, cv2.IMREAD_GRAYSCALE) target2 = cv2.imread(image2, cv2.IMREAD_GRAYSCALE) mn_val_f, max_val_f, min_loc_f, max_loc_f, twidth_f, theight_f = shibie_anniu(target1) tempheight, tempwidth = target1.shape[:2] theight, twidth = target2.shape[:2] scaleTemp = cv2.resize(target1, (int(tempwidth), int(tempheight))) res = cv2.matchTemplate(scaleTemp, target2, cv2.TM_CCOEFF_NORMED) mn_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) if max_val >= 0.9: tagCenterX, tagCenterY = jisuan_center(max_val, min_loc, max_loc, twidth, theight) tagCenterX += max_loc_f[0] tagCenterY += max_loc_f[1] dianji(tagCenterX, tagCenterY) print(ture_shuchu) else: print(fale_shuchu)
函数使用方式与dianji_anniu()类似,不同点在于多了一个图片位置参数。
dianji_anniu_2('蓝色色块.png', '选择.png', '点击选择', '未识别到')
其中'蓝色色块.png'和'选择.png'的图片如下:
虽然是为了偷懒写的,但是!熬夜写了这个代码后只用了不到两天就没那个需求了,一时不知该/(ㄒoㄒ)/~~还是该(*^_^*)。
我好像知道为啥都很少在公众号上发代码了,我好好的代码都给排版成啥样了/(ㄒoㄒ)/~~我看缩进没啥问题,字体颜色先凑合看吧,好像也没法发代码文件/(ㄒoㄒ)/~~