§ 0.0.0 前言
监听、操做鼠标、键盘是实现自动化的捷径,好比我实现自动化签到用到了模拟键盘操做。html
pynput是监听、操控鼠标和键盘的跨平台第三方python库。
你能够经过pip insnall pynput
来安装。安装时会自动下载依赖库。
python
接下来我会按“鼠标按键”“监听鼠标”“控制鼠标”,
“键盘按键”“监听键盘”“控制键盘”的顺序介绍它的用法。
多线程
- 如下为正文。
§1.0.0 鼠标按键
鼠标的按键在pynput.mouse.Button
中,
有lift
、right
、middle
还有unknown
四种。
函数
每个按键都有两个有意义的属性:name
和value
。
name是该按键的名称,好比 Button.left.name == 'left';
value是记录上一次点击位置的元组。
测试
§1.1.0 监听鼠标
有两种方法,一种是函数式、非阻塞型,另外一种是语句式、非阻塞型。spa
先说第一种,这种是常见的教程所说的方法。线程
§1.1.1 pynput.mouse.Listener
如下是官网的说明示例:code
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()
运行这段代码时,移动鼠标会显示其坐标,
按下鼠标按键并松开后,程序结束。
orm
- 当三个函数任意一个返回
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
里,有left
、right
和middle
。
还有可选参数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
,提供参数dx
和dy
。
例:
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
官网示例:
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结束进程。
§ 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一下。
闲谈
以前和别人聊天,他说他在不须要时把电脑的麦拔下来、摄像头挡上。
我说用Fn快捷键禁掉麦克风更方便。
如今想一想,黑客能够经过模拟按键解禁麦克风啊。
虽然这个模块没有Fn键,但别的呢?
最后
这份算是最全的了。原创不易,纯手打。
转载请注明做者和连接哦。
感谢阅读!