【Python】实现键盘鼠标动作录制和执行的小工具

news/2024/11/17 7:48:28/

        突发奇想做一个可以实现鼠标键盘操作录制,并可以回放操作的小工具。依托于pynput模块来实现鼠标键盘的控制,tkinter来实现图形界面的绘制。分为以下几个步骤:

一 录制(记录过程,并将用户的操作保存为json文件)

def on_key_press(key):    #当按键按下时记录if key==pynput.keyboard.Key.esc:    #如果是escglobal isRunningisRunning=False    #通知监听鼠标的线程mouse=pynput.mouse.Controller()    #获取鼠标的控制器mouse.click(pynput.mouse.Button.left)    #通过模拟点击鼠标以执行鼠标的线程,然后退出监听.return False    #监听函数return False表示退出监听12command_list.append(("press",    #操作模式(str(key).strip("'"),),    #具体按下的键,传进来的参数并不是一个字符串,而是一个对象,如果按下的是普通的键,会记录下键对应的字符,否则会使一个"Key.xx"的字符串time.time()-startTime    #操作距离程序开始运行的秒数))
def on_key_release(key):    #但按键松开时记录command_list.append(("release",    #操作模式(str(key).strip("'"),),    #键信息,参见on_key_press中的相同部分time.time()-startTime    #操作距离程序开始运行的秒数))
def on_mouse_click(x,y,button,pressed):global mouse_x_oldglobal mouse_y_oldglobal mouse_t_oldif not isRunning:    #如果已经不在运行了return False    #退出监听if not pressed:    #如果是松开事件return True    #不记录if mouse_x_old == x and mouse_y_old == y:if time.time() - mouse_t_old > 0.3: #如果两次点击时间小于0.3秒就会判断为双击 否则就是单击command_list.append(("click",  # 操作模式(x, y, str(button)),  # 分别是鼠标的坐标和按下的按键time.time() - startTime  # 操作距离程序开始运行的秒数))else:command_list.pop(0)  #删除前一个command_list.append(("double-click",  # 操作模式(x, y, str(button)),  # 分别是鼠标的坐标和按下的按键time.time() - startTime  # 操作距离程序开始运行的秒数))else:command_list.append(("click",  # 操作模式(x, y, str(button)),  # 分别是鼠标的坐标和按下的按键time.time() - startTime  # 操作距离程序开始运行的秒数))mouse_x_old = xmouse_y_old = ymouse_t_old = time.time()
def start_key_listen():    #用于开始按键的监听# 进行监听with pynput.keyboard.Listener(on_press=on_key_press,on_release=on_key_release) as listener:listener.join()def start_mouse_listen():    #用于开始鼠标的监听# 进行监听with pynput.mouse.Listener(on_click=on_mouse_click) as listener:listener.join()def toFile(command_list,path):    #保存为文件,参数分别为操作记录和保存位置with open(path,"w") as f:f.write(json.dumps(command_list))    #使用json格式写入

二 回放(解析之前记录的json文件,并通过pynput模块控制操作)

def unicode_convert(input_data):#将unicode转换成strif isinstance(input_data, dict):return {unicode_convert(key): unicode_convert(value) for key, value in input_data.iteritems()}elif isinstance(input_data, list):return [unicode_convert(element) for element in input_data]elif isinstance(input_data, str):return input_dataelse:return input_datadef ExecuteCommandsFile(path):# 如果命令行传入了参数,则使用命令行参数,否则提示用户输入,此变量表示操作记录文件的路径# 第二个不是:,也就代表路径是相对路径path = unicode_convert(path)if path[2] != ":":# 将其解析为从本文件开始的路径path = os.path.join(os.path.dirname(__file__), path)# 打开文件with open(path) as f:# 将记录的命令写入命令列表command_read = json.loads(f.read())command_read = unicode_convert(command_read)# 创建鼠标和键盘的执行器,用于模拟键盘和鼠标的操作mouse = pynput.mouse.Controller()keyboard = pynput.keyboard.Controller()# 鼠标的两个按钮buttons = {"Button.left": pynput.mouse.Button.left,"Button.right": pynput.mouse.Button.right}# 开始后已经经过的时间sTime = 0# 执行每一条记录for command in command_read:# 如果是点击记录print(command[0])print(command[1])print(command[2])# 如果是单击if command[0] == "click":# 将鼠标移动到记录中的位置mouse.position = (command[1][0], command[1][1])# 等待一下time.sleep(0.1)# 点击mouse.click(buttons[command[1][2]])# 如果是双击elif command[0] == "double-click":# 将鼠标移动到记录中的位置mouse.position = (command[1][0], command[1][1])# 等待一下time.sleep(0.1)# 双击mouse.click(buttons[command[1][2]], 2)# 如果是按键按下elif command[0] == "press":# 如果是特殊按键,会记录成Key.xxx,这里判断是不是特殊按键if command[1][0][:3] == "Key":# 按下按键keyboard.press(eval(command[1][0], {}, {"Key": pynput.keyboard.Key}))else:# 如果是普通按键,直接按下if "<255>" == command[1][0]:continueprint(command[1][0])# print(command[1][0].split("'")[1])# keyboard.press(command[1][0].split("'")[1])keyboard.press(command[1][0])# 如果是按键释放elif command[0] == "release":# 如果是特殊按键if command[1][0][:3] == "Key":# 按下按键keyboard.release(eval(command[1][0], {}, {"Key": pynput.keyboard.Key}))else:# 普通按键直接按下if "<255>" == command[1][0]:continueprint(command[1][0])# print(command[1][0].split("'")[1])# keyboard.release(command[1][0].split("'")[1])keyboard.release(command[1][0])# command[2]代表此操作距离开始操作所经过的时间,用它减去已经经过的时间就是距离下一次操作的时间time.sleep(command[2] - sTime)# 更新时间sTime = command[2]

【3】图形界面(通过tkinter绘制简易的操作界面)

import os  # 用于文件操作
import time    #用于记录每一项操作的时间
import json    #用于保存导出我们记录的操作
import threading    #由于键盘和鼠标事件的监听都是阻塞的,所以用两个线程实现
import tkinter  #绘制操作界面
from tkinter import messagebox
import pynput    #用于记录用户事件
import ctypesPROCESS_PER_MONITOR_DPI_AWARE = 2  #解决由于屏幕分辨率缩放导致的,pynput监听鼠标位置不准的问题
ctypes.windll.shcore.SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE)command_list=[]    #用来存储用户的操作
command_read=[]    #用来读取录制的操作
isRunning=True    #是否在运行,用于实现在按esc后退出的功能
startTime=0    #开始时间,会在之后main函数中进行初始化
mouse_x_old = 0
mouse_y_old = 0
mouse_t_old = 0#插入录制部分代码#插入执行部分代码class TKDemo:def __init__(self):self.top = tkinter.Tk()self.top.title('鼠标宏录制工具')self.top.geometry('500x250')frame1 = tkinter.Frame(self.top)frame1.pack(side='top')l1 = tkinter.Label(frame1,text='【1----录制操作】\n注意:按Esc退出录制,暂不支持键盘组合键')l1.pack()b1 = tkinter.Button(frame1,text='录制',width=15, height=2,command=self.recordOp)b1.pack()frame2 = tkinter.Frame(self.top)frame2.pack(side='bottom')l2 = tkinter.Label(frame2,text='【2----执行操作】')l2.pack()b2 = tkinter.Button(frame2,text='执行',width=15, height=2,command=self.execOp)b2.pack()l3 = tkinter.Label(frame2,text='请输入执行次数,默认为1次')l3.pack()self.count = tkinter.StringVar()e1= tkinter.Entry(frame2, textvariable=self.count)e1.pack()self.top.mainloop()def recordOp(self):self.top.iconify()  #窗口隐藏global startTimestartTime = time.time()  # 初始化开始时间key_listen_thread = threading.Thread(target=start_key_listen)  # 创建用于监听按键的线程mouse_listen_thread = threading.Thread(target=start_mouse_listen)  # 创建用于监听鼠标的线程# 运行线程key_listen_thread.start()mouse_listen_thread.start()# 等待线程结束,也就是等待用户按下esckey_listen_thread.join()mouse_listen_thread.join()# 记录成功之后执行下列操作toFile(command_list, "./commands.json")# 保存文件global isRunningisRunning = True  # 初始化记录状态command_list.clear()  # 清空列表self.top.deiconify()  # 窗口显现print("记录成功!")tkinter.messagebox.showinfo('提示', '记录成功!')def execOp(self):self.top.iconify()  # 窗口隐藏path = 'commands.json'count = self.count.get()if count.isdigit():for i in range(int(count)):ExecuteCommandsFile(path)print("执行成功%d次!" % (int(count)))tkinter.messagebox.showinfo('提示', "执行完毕!\n共%d次!" % (int(count)))elif len(count) == 0:ExecuteCommandsFile(path)print("执行成功1次!")tkinter.messagebox.showinfo('提示', '执行完毕!\n共1次!')else:print("执行失败!请键入数字")tkinter.messagebox.showerror('提示', '执行失败!\n请键入数字!')self.top.deiconify()  # 窗口显现def main():    #主函数TKDemo()if __name__=="__main__":main()

        综上,即可实现该简单的功能。

四 附录

【1】开源库地址:Python_MouseClick: 通过python tkinter构建界面,录制鼠标和键盘的操作,并执行n次操作回放

【2】参考文章地址:

python3实现鼠标键盘动作录制,并还原执行过程_momo131422的博客-CSDN博客_python录制鼠标动作


http://www.ppmy.cn/news/533399.html

相关文章

如何克服录制回放模式的弊端

Web浏览器的可视化界面及交互操作屏蔽了与服务器端交互的请求响应的复杂性。例如&#xff0c;我们随便打开一个网页或者触发一次交互操作&#xff0c;就可能在后端触发了成百上千的HTTP请求响应的处理&#xff0c;这些过程对使用者来说是不可见的&#xff0c;也是不需要关心的。…

web页面录制与回放全栈小项目

web页面录制与回放全栈小项目 技术栈相关文档项目代码项目效果本地启动前端后端node 推荐阅读 你越是认真生活&#xff0c;你的生活就会越美好——弗兰克劳埃德莱特 《人生果实》经典语录 技术栈 前端 Vue 后端 Node Egg 数据库 mongo 录制与回访实现 rrweb websocket …

rosbag录制和回放

rosbag录制和回放 1. 录制2. 回放3. 参考 本博客参照一位大佬YongqiangGao的博客实现仿真环境中一个 7 轴机械臂画圆时的 joint_states 数据&#xff0c;在此记录以供自己加深印象以及回顾&#xff0c;主要总结了如何通过rosbag将ROS系统运行过程中的数据录制到 .bag 文件中&am…

15-bag的录制,回放与解析

本教程教你如何使用rosbag record工具来录制ros通信数据。之后在通过rosbag play形式回放录制的数据包 此教程不详细解读&#xff0c;仅将rosbag record对应的help文档列出&#xff0c;并给出具体录制例子 rosbag bag包是存储ROS消息数据的文件格式&#xff0c;rosbag命令可以…

C++用钩子模仿按键精灵录制键盘鼠标的功能

最近需要做个跟按键精灵类似的软件&#xff0c;模仿键盘鼠标的动作&#xff0c;然后重播一次&#xff0c;最开时候的时候用键盘钩子和鼠标钩子做的&#xff0c;虽然实现了功能&#xff0c;但是鼠标移动速度非常快&#xff0c;所以换成WH_JOURNALPLAYBACK 和WH_JOURNALRECORD 钩…

LR11录制回放HTTPS时的问题

背景&#xff1a;使用LoadRunner11录制HTTPS网页&#xff0c;测试性能 环境&#xff1a;LoadRunner11 Patch4 Win7 Firefox45 问题&#xff1a;录制时&#xff0c;出现启动了浏览器但地址栏无URL&#xff0c;页面空白&#xff1b;或者能打开页面但无event的情况。 目录 目…

selenium+java如何录制脚本及回放

本文以百度网址搜索信息为例&#xff0c;用Katalon Automation Recorder进行简单的脚本录制。1&#xff09;首先下载火狐浏览器&#xff0c;我用的是56.0版本的。对应的驱动 geckodriver-v0.20.1-win64.zip&#xff08;48版本及以上均可用&#xff09;&#xff0c;下载地址参考…

JMeter录制与回放脚本问题

1、JMeter录制脚本 由于JMeter和Badboy安装比较简单&#xff0c;可以直接百度&#xff0c;这里不记录 。 JMeter录制脚本有两种方式&#xff1a;Badboy和JMeter使用Http代理服务器录制。 &#xff08;1&#xff09;使用Badboy录制脚本时&#xff0c;由于各个浏览器的内置编码…