赞
踩
监听、操作鼠标、键盘是实现自动化的捷径,比如我实现自动化签到用到了模拟键盘操作。
pynput是监听、操控鼠标和键盘的跨平台第三方python库。
你可以通过pip insnall pynput
来安装。安装时会自动下载依赖库。
pypi链接在此。
接下来我会按
“鼠标按键”“监听鼠标”“控制鼠标”,“键盘按键”“监听键盘”“控制键盘”
的顺序介绍它的用法。
鼠标的按键在pynput.mouse.Button
中,
有lift
、right
、middle
还有unknown
四种。
每一个按键都有两个有意义的属性:name
和value
。
name是该按键的名称,比如 Button.left.name == 'left';
value是记录上一次点击位置的元组。
有两种方法,一种是函数式、非阻塞型,另一种是语句式、阻塞型。
先说第一种,这种是常见的教程所说的方法。
以下是官网的说明示例:
- 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语句。个人认为,这个方法比上一个更直观。
- 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。
pynput.mouse.Controller()
获取控件。 以下方法都是该控件的所属方法。如下:
- import pynput
-
- ctr = pynput.mouse.Controller()
动态属性position
返回鼠标位置坐标的元组(像这样: (x, y) ),
通过定义来改变鼠标位置,比如ctr.position = (500, 500)
。
当然,也有move
方法,用于移动鼠标,
用法是ctr.move(dx, dy)
。
使用方法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)
- #右键单击。
使用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)
- #释放左键。
模拟滚轮,使用的方法是scroll
,提供参数dx
和dy
。
例:
- import pynput
-
- ctr = pynput.mouse.Controller()
-
- ctr.scroll(0, 50)
- #向上滚动50单位。
-
- ctr.scroll(0, -50)
- #向下滚动50单位。
键盘的按键获取比鼠标的麻烦些,但是没有鼠标用得多。
因此我先说给常用的使用方法,再说获取。
首先,当获取事件后,要判断按键是“特殊按键”还是“普通按键”, 需判断其是否具有name
属性,有则是特殊按键。 这个属性记录属性的名称,比如ctrl
对应着'ctrl'
、'ctrl_l'
或是'ctrl_r'
。
普通按键中,取而代之的是.char
。
注:大写字母与小写字母有不同的按键。
还有其他功能。这里就不多说了。
首先,特殊按键在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
通过按键的映射码取得。
主要有两种方法,类似于鼠标的,我的讲述顺序同前文。
还有一种是对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语句。-
- 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键事件。')
(还有'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结束进程。
先获取控件 :ctr = pynput.keyboard.Controller()
。 以下所说的方法均是指该控件的方法。
通过方法press
来按下按键,
你需要提供一个“长度为1的字符”或是“前文所说的按键对象”。
温馨提示,此方法测试有风险,如果发现电脑打字、操作异常, 很可能是因为模拟按下了某个键未松开。
可以重启控制台或电脑。
通过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)
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
type
在英语中除了“类型”还有“打字”之意。
该方法接收字符串,然后打出每个字符。
据测试,向它提供一个“按键列表”也可以正常使用。
例:
- import pynput
-
- ctr = pynput.keyboard.Controller()
-
- ctr.type('Hello world!')
-
- ctr.type([pynput.keyboard.Key.esc])
- #按下esc再松开。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。