zoukankan      html  css  js  c++  java
  • 自动化键盘,python

    国际惯例先上源
    https://github.com/boppreh/keyboard
    #
    键盘输入 from pynput.keyboard import Key,Controller,Listener keyboard = Controller() keyboard.press("a") #按下a keyboard.release("a") #松开a keyboard.press("A") #按下A keyboard.release("A") #松开A with keyboard.pressed(Key.shift): #按下shift keyboard.press("a") #shift + a keyboard.type("Hello World") #输出文字 #-------------------------------------------------- # 键盘监听 from pynput.keyboard import Key,Listener def on_press(key): if key == Key.enter: print('you press Enter') else: return False #按键不是enter,停止监视 def on_release(key): if key == Key.enter: print('you release Enter') #监听键盘按键 with Listener(on_press=on_press,on_release=on_release) as listener: listener.join() #停止监视 Listener.stop()

    § 0.0.0 前言

    监听、操作鼠标、键盘是实现自动化的捷径,比如我实现自动化签到用到了模拟键盘操作。

    pynput是监听、操控鼠标和键盘的跨平台第三方python库。
    你可以通过pip insnall pynput来安装。安装时会自动下载依赖库。

    pypi链接在此。

    接下来我会按
    “鼠标按键”“监听鼠标”“控制鼠标”,“键盘按键”“监听键盘”“控制键盘”
    的顺序介绍它的用法。



    • 以下为正文。


    §1.0.0 鼠标按键

    鼠标的按键在pynput.mouse.Button中,
    liftrightmiddle还有unknown四种。

    每一个按键都有两个有意义的属性:namevalue
    name是该按键的名称,比如 Button.left.name == 'left';
    value是记录上一次点击位置的元组。



    §1.1.0 监听鼠标

    有两种方法,一种是函数式、非阻塞型,另一种是语句式、阻塞型。

    先说第一种,这种是常见的教程所说的方法。

    §1.1.1 pynput.mouse.Listener

    以下是官网的说明示例:

    import pynput, time
    
    def on_move(x, y):
        print('Pointer moved to {0}'.format((x, y)))
    
    def on_click(x, y, button, pressed):
        print('{0} at {1}'.format(
            'Pressed' if pressed else 'Released',
            (x, y)))
        if not pressed:
            # Stop listener
            return False
    
    def on_scroll(x, y, dx, dy):
        print('Scrolled {0} at {1}'.format(
            'down' if dy < 0 else 'up',
            (x, y)))
    
    # Collect events until released
    with pynput.mouse.Listener(
            on_move=on_move,
            on_click=on_click,
            on_scroll=on_scroll) as listener:
        listener.join()
    

    运行这段代码时,移动鼠标会显示其坐标,
    按下鼠标按键并松开后,程序结束。

    • 当三个函数任意一个返回False((还有就是释放Exception或继承自Exception的异常)时,就会结束进程。
    • 可以用listener.start()listener.stop()代替with语句。

    §1.1.2 pynput.mouse.Events

    个人认为,这个方法比上一个更直观。

    import pynput
    
    with pynput.mouse.Events() as event:
    
        for i in event:
        #迭代用法。
            if isinstance(i, pynput.mouse.Events.Move):
                #鼠标移动事件。
                print(i.x, i.y)
                #不要直接打印`i`,模块这里有问题,会报错。
    
            elif isinstance(i, pynput.mouse.Events.Click):
                #鼠标点击事件。
                print(i.x, i.y, i.button, i.pressed)
                #这个i.button就是上文所说的“鼠标按键”中的一个,用is语句判断即可。
    
            elif isinstance(i, pynput.mouse.Events.Scroll):
                #鼠标滚轮。
                print(i.x, i.y, i.dx, i.dy)
    
    
            break
        
        i = event.get(1)
        #另一种用法。
        #默认值是None。
        #这个`1`就是最长等待时间,超过这个时间没有事件,
        #就会报错。错误类型是queue模块的Empty,而非TimeoutError。
    


    §1.2.0 控制鼠标

    • § 1.2.1
      先执行pynput.mouse.Controller()获取控件。
      以下方法都是该控件的所属方法。

    如下:

    import pynput
    
    ctr = pynput.mouse.Controller()
    

    • § 1.2.2

    动态属性position返回鼠标位置坐标的元组(像这样: (x, y) ),
    通过定义来改变鼠标位置,比如ctr.position = (500, 500)


    • § 1.2.3

    当然,也有move方法,用于移动鼠标
    用法是ctr.move(dx, dy)


    • § 1.2.4

    使用方法click进行模拟点击,需提供点击的按钮,
    按钮在pynput.mouse.Button里,有leftrightmiddle
    还有可选参数count,是点击次数,默认为1。

    示例:

    import pynput
    
    ctr = pynput.mouse.Controller()
    
    ctr.click(pynput.mouse.Button.left)
    #左键单击。
    
    ctr.click(pynput.mouse.Button.left, 2)
    #左键双击。
    
    ctr.click(pynput.mouse.Button.right)
    #右键单击。
    

    • § 1.2.5

    使用press(button)按下button键;
    方法release(button)释放键,如果操作时按键并没有被按下,也不会报错。

    示例:

    import pynput
    
    ctr = pynput.mouse.Controller()
    
    ctr.press(pynput.mouse.Button.left)
    #按下左键。
    
    ctr.move(50, 0)
    #右移50单位。
    
    ctr.move(0, 50)
    #下移50单位。
    
    ctr.release(pynput.mouse.Button.left)
    #释放左键。
    

    • § 1.2.6

    模拟滚轮,使用的方法是scroll,提供参数dxdy

    例:

    import pynput
    
    ctr = pynput.mouse.Controller()
    
    ctr.scroll(0, 50)
    #向上滚动50单位。
    
    ctr.scroll(0, -50)
    #向下滚动50单位。
    


    • 以上是鼠标操作,
    • 以下是键盘操作。


    § 2.0.0 键盘按键

    键盘的按键获取比鼠标的麻烦些,但是没有鼠标用得多。
    因此我先说给常用的使用方法,再说获取


    § 2.0.1 使用方法

    首先,当获取事件后,要判断按键是“特殊按键”还是“普通按键”,
    需判断其是否具有name属性,有则是特殊按键
    这个属性记录属性的名称,比如ctrl对应着'ctrl''ctrl_l'或是'ctrl_r'
    普通按键中,取而代之的是.char

    注:大写字母与小写字母有不同的按键。

    还有其他功能。这里就不多说了。

    § 2.0.2 获取

    首先,特殊按键pynput.keyboard.Key“模块”中可以直接找到。
    比如ctrl对应pynput.keyboard.Key.ctrl还有.ctrl_l以及.ctrl_r

    然后,普通按键可以通过pynput.keyboard.KeyCode.from_char取得(特殊按键不可以,使用时会出现ArgumentError)。
    a可以运行pynput.keyboard.KeyCode.from_char('a')获得。

    二者都可以用pynput.keyboard.KeyCode.from_vk通过按键的映射码取得。



    § 2.1.0 监听键盘

    主要有两种方法,类似于鼠标的,我的讲述顺序同前文。
    还有一种是对Listener的封装,用于快捷键,我放在最后一个说。

    § 2.1.1 pynput.keyboard.Listener

    注:如果你只想关注个别按键而非所有事件,可以使用GlobalHotKeys。我会在后文说。

    官网示例:

    from pynput import keyboard
    
    def on_press(key):
        '按下按键时执行。'
        try:
            print('alphanumeric key {0} pressed'.format(
                key.char))
        except AttributeError:
            print('special key {0} pressed'.format(
                key))
        #通过属性判断按键类型。
    
    def on_release(key):
        '松开按键时执行。'
        print('{0} released'.format(
            key))
        if key == keyboard.Key.esc:
            # Stop listener
            return False
    
    # Collect events until released
    with keyboard.Listener(
            on_press=on_press,
            on_release=on_release) as listener:
        listener.join()
    
    • 当两个函数中任意一个返回False(还有就是释放Exception或继承自Exception的异常)时,就会结束进程。
    • 可以用listener.start()listener.stop()代替with语句。

    § 2.1.2 pynput.keyboard.Events

    
    import pynput
    
    with pynput.keyboard.Events() as event:
    
        for i in event:
        #迭代用法。
            key_event = i
            break
        
        key_event = event.get()
        #get用法。
        #可以提供一个实数作为最长等待时间(单位秒),超过这个时间没有事件,
        #就会报错。错误类型是queue模块的Empty,而非TimeoutError。
    
    #判断事件情况:
    
    if isinstance(key_event, pynput.keyboard.Events.Press):
        print('按下按键', end = '')
    elif isinstance(key_event, pynput.keyboard.Events.Release):
        print('松开按键', end = '')
    
    #判断按键:
    
    #*这个事件的`key`属性*对应才是*Listener方法获得的按键`'key'`*。
    
    try:
        print(key_event.key.name)
    except AttributeError:
        #说明这个是普通按键。
        print(key_event.key.char)
    else:
        #两种判断方式,第一种是我自创的,第二种是官网上的。
        if (key_event.key.name).startswith('ctrl'):
            #通过名称判断。
            print('发生了ctrl键事件。')
        elif key_event.key is pynput.keyboard.Key.esc:
            print('发生了esc键事件。')
    

    § 2.1.3 pynput.keyboard.GlobalHotKeys

    (还有'pynput.keyboard.HotKey'可以实现相似功能,但很麻烦)

    官网示例,esc那个是我写的。

    from pynput import keyboard
    
    def on_activate_h():
        print('<ctrl>+<alt>+h pressed')
    
    def on_activate_i():
        print('<ctrl>+<alt>+i pressed')
    
    def esc():
        print('<esc> pressed')
        return False
    
    def esc_shift():
        print('<esc>+<shift> pressed')
        raise Exception
    
    with keyboard.GlobalHotKeys({
            '<ctrl>+<alt>+h': on_activate_h,
            '<ctrl>+<alt>+i': on_activate_i,
            '<esc>':          esc,
            '<esc>+<shift>':  esc_shift}) as h:
        h.join()
    

    当按下esc键时,函数被触发,但运行未停止。
    观察源码,发现虽然该类继承自Listener,但会对执行的函数有封装,封装后只返回None。
    所以无法通过return False结束进程。

    设置单个普通按键(比如“a”)也是可以的。

    不能分辨按键顺序如“<ctrl>+a”与“a+<ctrl>”。



    § 2.2.0 控制键盘

    • § 2.2.1

    先获取控件 :ctr = pynput.keyboard.Controller()
    以下所说的方法均是指该控件的方法。


    • § 2.2.2

    通过方法press按下按键
    你需要提供一个“长度为1的字符”或是“前文所说的按键对象”。

    温馨提示,此方法测试有风险,如果发现电脑打字、操作异常,
    很可能是因为模拟按下了某个键未松开。
    可以重启控制台或电脑。


    • § 2.2.3

    通过release释放按键
    和press方法一样,需要提供一个“长度为1的字符”或是“前文所说的按键对象”。

    示例:

    '''
    这段程序会按“下ctrl+shilf+s”快捷键,停顿3秒后按下esc键。
    简单模拟了“另存为”操作。
    '''
    
    import pynput, time
    
    ctr = pynput.keyboard.Controller()
    
    ctr.press(pynput.keyboard.KeyCode.from_vk(17))
    #通过按键的映射码 按下ctrl键。
    
    ctr.press(pynput.keyboard.Key.shift)
    #通过按键对象 按下shift键。
    
    ctr.press('s')
    #通过长度为1的字符 按下s键。
    
    
    #扫尾,释放刚才按下的键。后面我会说更简单、优雅的办法。
    ctr.release(pynput.keyboard.Key.ctrl)
    ctr.release(pynput.keyboard.Key.shift)
    ctr.release('s')
    
    time.sleep(0.3)
    
    ctr.press(pynput.keyboard.Key.esc)
    ctr.release(pynput.keyboard.Key.esc)
    

    • § 2.2.4

    pressed方法就是我说的“更简单、优雅”的方法。
    使用时提供要按下的键,再用with语句“封装”上。
    效果是进入语句块时顺序按下提供按键,退出语句块时逆序释放按键。

    如下:

    import pynput, time
    
    ctr = pynput.keyboard.Controller()
    
    with ctr.pressed(
            pynput.keyboard.Key.ctrl,
            pynput.keyboard.Key.shift,
            's'):
        pass
    
    time.sleep(0.3)
    
    with ctr.pressed(pynput.keyboard.Key.esc):
        pass
    

    • § 2.2.5

    type在英语中除了“类型”还有“打字”之意。
    该方法接收字符串,然后打出每个字符。
    据测试,向它提供一个“按键列表”也可以正常使用。

    例:

    import pynput
    
    ctr = pynput.keyboard.Controller()
    
    ctr.type('Hello world!')
    
    ctr.type([pynput.keyboard.Key.esc])
    #按下esc再松开。
    


    • 以上是正文。


    一些建议

    该模块鼠标、键盘的监听操作均由多线程实现。
    所以,可以利用多线程共享内存的特征编程;二要注意不要频繁启动监听,这样对系统开支极大。

    还有就是对鼠标位置监听要求不是很高时(比如实时向用户显示鼠标位置),可以每次循环sleep一下。
    如果向Listener提供的函数会执行很久(比如含有sleep),会导致电脑变卡。

    闲谈

    之前和别人聊天,他说他在不需要时把电脑的麦拔下来、摄像头挡上。
    我说用Fn快捷键禁掉麦克风更方便。
    现在想想,黑客可以通过模拟按键解禁麦克风啊。
    虽然这个模块没有Fn键,但别的呢?

    最后

    这份算是最全的了。原创不易,纯手打。

    转载请注明作者和链接哦。

    感谢阅读!

     
  • 相关阅读:
    .net core读取appsettings.config中文乱码问题
    vs2017错误:当前页面的脚本发生错误
    VS Code中无法识别npm命令
    Visual Studio报错/plugin.vs.js,行:1074,错误:缺少标识符、字符串或数字
    记录一次在生成数据库服务器上出现The timeout period elapsed prior to completion of the operation or the server is not responding.和Exception has been thrown by the target of an invocation的解决办法
    Java集合框架
    java hash表
    Java Dictionary 类存储键值
    java数据结构 栈stack
    java封装
  • 原文地址:https://www.cnblogs.com/vip136510786/p/14680040.html
Copyright © 2011-2022 走看看