§ 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鍵,但別的呢?
最後
這份算是最全的了。原創不易,純手打。
轉載請註明做者和連接哦。
感謝閱讀!