记录你的操作——pynput模拟和监听键盘鼠标操作

我们可能经常会用到一些功能,比如说,记录我们的操作,并在合适的时候复现,或者每天定时实现我们预先定义的一套操作.当然,我们可以直接ctypes调用windows的原生api,用钩子函数实现,但在一般情况下,我们可以使用pynput完成这个工作.

首先,我们要安装它,它虽然不是原生的,但借助pip还是可以很方便安装的.

pip install pynput

接下来,让我们熟悉一下接口和这个框架常用的接口(看图说明一切):


pynput常用功能.png

知道了相关的功能,我们就可以着手开发相关的程序了,由于觉得容易不需要,我没有开发GUI用户界面,分为两个程序,第一个记录用户的操作,按esc终止,终止后以json格式保存,第二个读取第一个导出的json,并进行执行.
我实现这个项目是因为想做自动签到,所以考虑到需求,就没有监听鼠标移动和滚动的事件,而只是监听了点击事件.为了让每个事件之间有一定的间隔,我们需要使用time库记录操作的时间.
代码如下:


用于记录的程序


#一个记录用户操作,并保存到json文件的程序

import time    #用于记录每一项操作的时间
import json    #用于保存导出我们记录的操作
import threading    #由于键盘和鼠标事件的监听都是阻塞的,所以用两个线程实现
import pynput    #用于记录用户事件
command_list=[]    #用来存储用户的操作
isRunning=True    #是否在运行,用于实现在按esc后退出的功能
startTime=0    #开始时间,会在之后main函数中进行初始化
def on_key_press(key):    #当按键按下时记录
    if key==pynput.keyboard.Key.esc:    #如果是esc
        global isRunning
        isRunning=False    #通知监听鼠标的线程
        mouse=pynput.mouse.Controller()    #获取鼠标的控制器
        mouse.click(pynput.mouse.Button.left)    #通过模拟点击鼠标以执行鼠标的线程,然后退出监听.
        return False    #监听函数return False表示退出监听
    command_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):
    if not isRunning:    #如果已经不在运行了
        return False    #退出监听
    if not pressed:    #如果是松开事件
        return True    #不记录
    command_list.append((
        "click",    #操作模式
        (x,y,str(button)),    #分别是鼠标的坐标和按下的按键
        time.time()-startTime    #操作距离程序开始运行的秒数
    ))
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格式写入

def main():    #主函数
    global startTime
    startTime=time.time()    #初始化开始时间
    t1=threading.Thread(target=start_key_listen)    #创建用于监听按键的线程
    t2=threading.Thread(target=start_mouse_listen)    #创建用于监听鼠标的线程
    #运行线程
    t1.start()
    t2.start()
    #等待线程结束,也就是等待用户按下esc
    t1.join()
    t2.join()
    #保存文件
    toFile(command_list,"./commands.json")

if __name__=="__main__":
    main()

用于执行的程序:


#一个运行使用"记录宏.py"记录的json的程序

import os    #用于文件操作
import json    #用于记录下来的操作
import time    #用于按照记录下来的时间间隔操作
import sys    #用于获取命令行传入的参数
import pynput    #用于模拟鼠标键盘操作
# 如果命令行传入了参数,则使用命令行参数,否则提示用户输入,此变量表示操作记录文件的路径
path = (sys.argv[1] if len(sys.argv)!=1 else input("请输入操作记录文件路径(相对路径从本文件位置开始)"))

# 第二个不是:,也就代表路径是相对路径
if path[2] != ":":
    #将其解析为从本文件开始的路径
    path = os.path.join(os.path.dirname(__file__), path)

#打开文件
with open(path) as f:
    #将记录的命令写入命令列表
    command_list = json.loads(f.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_list:
    #如果是点击记录
    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] == "press":
        #如果是特殊按键,会记录成Key.xxx,这里判断是不是特殊按键
        if command[1][0][:3]=="Key":
            #按下按键
            keyboard.press(eval(command[1][0],{},{
                "Key":pynput.keyboard.Key
            }))
        else:
            #如果是普通按键,直接按下
            keyboard.press(command[1][0])
    #如果是按键释放
    elif command[0] == "release":

        #如果是特殊按键
        if command[1][0][:3]=="Key":
            #按下按键
            keyboard.press(eval(command[1][0],{},{
                "Key":pynput.keyboard.Key
            }))
        else:
            #普通按键直接按下
            keyboard.release(command[1][0])
    #command[2]代表此操作距离开始操作所经过的时间,用它减去已经经过的时间就是距离下一次操作的时间
    time.sleep(command[2]-sTime)
    #更新时间
    sTime = command[2]



欢迎大家在评论区探讨.


以上是这篇文章的全部,错误的地方恳请指正.
QQ:8955859,希望能和大家一起学习.
最后,都看到这了,赞赏一下呗!(^ ~ ^||).

你可能感兴趣的:(记录你的操作——pynput模拟和监听键盘鼠标操作)