前幾天看PHP的架構的時候,發現了一個強大的叫Hook(鉤子)的東西,可以掛在系統的掛鈎點上由系統自動運行鉤子函數。搞懂PHP的鉤子怎麼用後,馬上google了一下Python是不是也有類似Hook的功能庫(哎,誰叫咱對Python情有獨鐘呢,學PHP時都不忘Python),結果不出所料,Python真的有Hook庫唉~
--------------------------------我是分割線-------------------------------------
閑話少敘,趕緊切入正題吧。Python的Hook叫pyHook,另外這個庫還要搭配上另一個叫pywin32的庫,其實從這個搭配可以猜出來目前Python的Hook庫還只支援Windows作業系統。這點還是比較遺憾的,一點不像Python一貫的跨平台作風啊。這兩個庫的話,在PyPI上可以下載到,這裡給個連結pyhook,pywin32。我安裝的是pyHook-1.5.1.win32-py2.7和pywin32-218.win32-py2.7這兩個版本的庫。這裡再給個pyHook的官方教程。你會發現這是很簡單實用的一個庫,只要你有創意可以拿它來做很多事。另外這兩個庫配置要求Python2.4及windows2000以上。這兩個庫下載下來後,都帶有exe檔案,運行按預設直接安裝就行了。安裝完成後,可以測試回合import
pyHook, pythoncom,如果沒有報錯,那麼恭喜你安裝成功,可以開始code啦!
程式的思路很簡單 ,先用pyHook的HookManager方法建立一個鉤子物件,然後在鍵盤和滑鼠的掛鈎點掛上自己定製的回呼函數,開啟鉤子,最後利用pythoncom(pywin32安裝後內建)的PumpMessages方法開啟一個windows訊息就行了。這個監聽狀態可以通過kill掉進程結束。在回呼函數裡,我在根目錄下建了log/keyboard/和log/mouse/兩個路徑,分別存放鍵盤和滑鼠的日誌。鍵盤日誌裡,按時間順序記錄了對應時間的鍵盤輸入、視窗名字等資訊,滑鼠日誌裡,按時間順序記錄了視窗名字資訊。另外,還增加了快速鍵功能,F7鍵用於關閉日誌功能(進程仍監聽只是不記錄資訊),F4鍵用於再次開啟。其實這個程式本身算是個樣本程式,比較清楚,但是這個功能還是很有意義的,可以作為後續統計或者機器學習的未經處理資料,背後的結論應該是很有代表性的。比如可以分析自己,在開電腦的時候各個活動所佔的時間比例,或者鍵盤上哪些鍵甚至哪些按鍵組合使用頻率比較高等等。
這裡直接貼源碼好啦。讀源碼神馬的最有愛了。
#!/usr/bin/env python#encoding=utf-8import pythoncomimport pyHookimport time, osdef onMouseEvent(event):# """監聽滑鼠事件"""global preWindowName, switchif not os.path.exists(mouseFilepath):os.makedirs(mouseFilepath)if switch:localTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())datafileName = localTime[:localTime.find(" ")] + ".txt"#time WindowNameif not os.path.exists(mouseFilepath + datafileName):f = open(mouseFilepath + datafileName, "w")f.write("localTimewindowname\n")f.close()if type(event.WindowName) == str: if event.WindowName != preWindowName:datafileContent = localTime + ',' + event.WindowName + '\n'f = open(mouseFilepath + datafileName, "a")f.write(datafileContent)f.close()preWindowName = event.WindowName#返回True以便將事件傳給其他處理常式return Truedef onKeyboardEvent(event):"""監聽鍵盤事件"""global switchif not os.path.exists(keyboardFilepath):os.makedirs(keyboardFilepath)if switch:localTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())datafileName = localTime[:localTime.find(" ")] + ".txt"#time keyvalue Key WindowNameif not os.path.exists(keyboardFilepath + datafileName):f = open(keyboardFilepath + datafileName, "w")f.write("localTimekeyvaluekeywindowname\n")f.close()if type(event.WindowName) == str:datafileContent = localTime + ',' + chr(event.Ascii) + ',' \+ event.Key + ',' + event.WindowName + '\n'f = open(keyboardFilepath + datafileName, "a")f.write(datafileContent)f.close()if event.KeyID == 118:#Key=F7switch = Falseif event.KeyID == 115:#Key=F4switch = True# print event.KeyID#同滑鼠監聽事件函數的傳回值return Truedef main():"""建立一個'鉤子'管理對象"""hm = pyHook.HookManager()#監聽所有鍵盤事件hm.KeyDown = onKeyboardEvent#設定鍵盤'鉤子'hm.HookKeyboard()#監聽所有滑鼠事件hm.MouseAll = onMouseEvent#設定滑鼠'鉤子'hm.HookMouse()#進入迴圈,如不手動關閉,程式將一直處於監聽狀態pythoncom.PumpMessages()if __name__ == '__main__':keyboardFilepath = "./log/keyboard/"mouseFilepath = "./log/mouse/"preWindowName = ''switch = True #控制是否開啟日誌功能main()