Idea
作为一个每天有一半时间都在电脑旁的人,无时无刻不在敲击着键盘,点击着鼠标。有一天,我突然很想知道在一天的时间内,在我轻盈的指法下面,键盘被我狂敲了多少下,鼠标又被我点击了多少次。甚至更具体一些,键盘上哪些键挨的敲击次数更多呢?想想也觉得挺有意思的。
Learing
有了想法,接着就是上(寻)网(找)学(代)习(码)了。既然要记录键盘敲击和鼠标点击的次数,那就得监听键盘和鼠标的事件。在搜索过程中,了解到了钩子函数这个概念。想要学习的同学可以看下这篇博客
毕竟我只是想实现一下功能,也就没太深入学习。对比了一些各种语言对于监听事件的实现代码,发现Python简直不能再简洁了,果断使用Python。
Coding(Copying)
现在想法、概念知识和所用工具都具备了,剩下的就是用代码去实现。Python环境自然不用多说,除此之外还需要几个第三方的库。主要参考这篇博客,自己的想法其实别人早就已经实现了。
当然别人的代码并不完全符合自己的需求,我不需要记录键盘、鼠标点击事件过于详细的信息,我需要记录的仅仅是次数。在前人的代码基础上修改一番即可。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pythoncom
import pyHook
import time
import win32api
"""
def onMouseEvent(event):
"处理鼠标事件"
fobj.writelines(\'-\' * 20 + \'MouseEvent Begin\' + \'-\' * 20 + \'\n\')
fobj.writelines("Current Time:%s\n" % time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime()))
fobj.writelines("MessageName:%s\n" % str(event.MessageName))
fobj.writelines("Message:%d\n" % event.Message)
fobj.writelines("Time_sec:%d\n" % event.Time)
fobj.writelines("Window:%s\n" % str(event.Window))
fobj.writelines("WindowName:%s\n" % str(event.WindowName))
fobj.writelines("Position:%s\n" % str(event.Position))
fobj.writelines(\'-\' * 20 + \'MouseEvent End\' + \'-\' * 20 + \'\n\')
return True
"""
def onMouse_rightup(event):
# 监听鼠标左键按下事件 次数加1
global right_up_num
right_up_num += 1
return True
def onMouse_leftup(event):
# 监听鼠标左键弹起事件 次数加1
global left_up_num
left_up_num += 1
return True
def onKeyboardEvent(event):
# 处理键盘事件 定义各个键位全局变量,记录敲击次数
global key_a_num
global key_b_num
global key_c_num
global key_d_num
global key_e_num
global key_f_num
global key_g_num
global key_h_num
global key_i_num
global key_j_num
global key_k_num
global key_l_num
global key_m_num
global key_n_num
global key_o_num
global key_p_num
global key_q_num
global key_r_num
global key_s_num
global key_t_num
global key_u_num
global key_v_num
global key_w_num
global key_x_num
global key_y_num
global key_z_num
global key_enter_num
global key_back_num
global key_1_num
global key_2_num
global key_3_num
global key_4_num
global key_5_num
global key_6_num
global key_7_num
global key_8_num
global key_9_num
global key_0_num
global key_oem_3_num #~
global key_oem_minus_num #-
global key_oem_plus_num #+
global key_tab_num #tab
global key_cap_num #caps
global key_lshift_num #left shift
global key_lctrl_num #left ctrl
global key_lwin_num
global key_lalt_num
global key_space_num
global key_rshift_num #left shift
global key_rctrl_num #left ctrl
global key_rwin_num
global key_ralt_num
global key_oem_comma_num #,
global key_oem_period_num #.
global key_oem_2_num #/
global key_oem_1_num #;
global key_oem_7_num #\'
global key_oem_4_num #[
global key_oem_5_num #]
global key_oem_6_num #\
global key_left_num #左
global key_right_num #右
global key_up_num #上
global key_down_num #下
global key_delete_num #delete
global key_end_num #end
global key_next_num #page down
global key_insert_num #insert
global key_home_num #home
global key_prior_num #page up
global key_snapshot_num #print screen
global key_scroll_num #scroll lock
global key_pause_num #pause
global key_escape_num #esc
global key_f1_num
global key_f2_num
global key_f3_num
global key_f4_num
global key_f5_num
global key_f6_num
global key_f7_num
global key_f8_num
global key_f9_num
global key_f10_num
global key_f11_num
global key_f12_num
global key_numpad0_num
global key_numpad1_num
global key_numpad2_num
global key_numpad3_num
global key_numpad4_num
global key_numpad5_num
global key_numpad6_num
global key_numpad7_num
global key_numpad8_num
global key_numpad9_num
global key_numlock_num
global key_divide_num
global key_multiply_num
global key_subtract_num
global key_add_num
global key_decimal_num
global key_total_num #总敲击次数
fobj.write("%s" % str(event.Key)+" ")
s=str(event.Key)
if s==\'A\':
key_a_num+=1
key_total_num+=1
elif s==\'B\':
key_b_num+=1
key_total_num+=1
elif s==\'C\':
key_c_num+=1
key_total_num+=1
elif s==\'D\':
key_d_num+=1
key_total_num+=1
elif s==\'E\':
key_e_num+=1
key_total_num+=1
elif s==\'F\':
key_f_num+=1
key_total_num+=1
elif s==\'G\':
key_g_num+=1
key_total_num+=1
elif s==\'H\':
key_h_num+=1
key_total_num+=1
elif s==\'I\':
key_i_num+=1
key_total_num+=1
elif s==\'J\':
key_j_num+=1
key_total_num+=1
elif s==\'K\':
key_k_num+=1
key_total_num+=1
elif s==\'L\':
key_l_num+=1
key_total_num+=1
elif s==\'M\':
key_m_num+=1
key_total_num+=1
elif s==\'N\':
key_n_num+=1
key_total_num+=1
elif s==\'O\':
key_o_num+=1
key_total_num+=1
elif s==\'P\':
key_p_num+=1
key_total_num+=1
elif s==\'Q\':
key_q_num+=1
key_total_num+=1
elif s==\'R\':
key_r_num+=1
key_total_num+=1
elif s==\'S\':
key_s_num+=1
key_total_num+=1
elif s==\'T\':
key_t_num+=1
key_total_num+=1
elif s==\'U\':
key_u_num+=1
key_total_num+=1
elif s==\'V\':
key_v_num+=1
key_total_num+=1
elif s==\'W\':
key_w_num+=1
key_total_num+=1
elif s==\'X\':
key_x_num+=1
key_total_num+=1
elif s==\'Y\':
key_y_num+=1
key_total_num+=1
elif s==\'Z\':
key_z_num+=1
key_total_num+=1
elif s==\'Return\':
key_enter_num+=1
key_total_num+=1
elif s==\'Back\':
key_back_num+=1
key_total_num+=1
elif s==\'1\':
key_1_num+=1
key_total_num+=1
elif s==\'2\':
key_2_num+=1
key_total_num+=1
elif s==\'3\':
key_3_num+=1
key_total_num+=1
elif s==\'4\':
key_4_num+=1
key_total_num+=1
elif s==\'5\':
key_5_num+=1
key_total_num+=1
elif s==\'6\':
key_6_num+=1
key_total_num+=1
elif s==\'7\':
key_7_num+=1
key_total_num+=1
elif s==\'8\':
key_8_num+=1
key_total_num+=1
elif s==\'9\':
key_9_num+=1
key_total_num+=1
elif s==\'0\':
key_0_num+=1
key_total_num+=1
elif s==\'Oem_3\':
key_oem_3_num+=1
key_total_num+=1
elif s==\'Oem_Minus\':
key_oem_minus_num+=1
key_total_num+=1
elif s==\'Oem_Plus\':
key_oem_plus_num+=1
key_total_num+=1
elif s==\'Tab\':
key_tab_num+=1
key_total_num+=1
elif s==\'Capital\':
key_cap_num+=1
key_total_num+=1
elif s==\'Lshift\':
key_lshift_num+=1
key_total_num+=1
elif s==\'Lcontrol\':
key_lctrl_num+=1
key_total_num+=1
elif s==\'Lwin\':
key_lwin_num+=1
key_total_num+=1
elif s==\'Lmenu\':
key_lalt_num+=1
key_total_num+=1
elif s==\'Space\':
key_space_num+=1
key_total_num+=1
elif s==\'Rshift\':
key_rshift_num+=1
key_total_num+=1
elif s==\'Rcontrol\':
key_rctrl_num+=1
key_total_num+=1
elif s==\'Rwin\':
key_rwin_num+=1
key_total_num+=1
elif s==\'Rmenu\':
key_ralt_num+=1
key_total_num+=1
elif s==\'Oem_Comma\':
key_oem_comma_num+=1
key_total_num+=1
elif s==\'Oem_Period\':
key_oem_period_num+=1
key_total_num+=1
elif s==\'Oem_2\':
key_oem_2_num+=1
key_total_num+=1
elif s==\'Oem_1\':
key_oem_1_num+=1
key_total_num+=1
elif s==\'Oem_7\':
key_oem_7_num+=1
key_total_num+=1
elif s==\'Oem_4\':
key_oem_4_num+=1
key_total_num+=1
elif s==\'Oem_5\':
key_oem_5_num+=1
key_total_num+=1
elif s==\'Oem_6\':
key_oem_6_num+=1
key_total_num+=1
elif s==\'Left\':
key_left_num+=1
key_total_num+=1
elif s==\'Right\':
key_right_num+=1
key_total_num+=1
elif s==\'Up\':
key_up_num+=1
key_total_num+=1
elif s==\'Down\':
key_down_num+=1
key_total_num+=1
elif s==\'Delete\':
key_delete_num+=1
key_total_num+=1
elif s==\'End\':
key_end_num+=1
key_total_num+=1
elif s==\'Next\':
key_next_num+=1
key_total_num+=1
elif s==\'Insert\':
key_insert_num+=1
key_total_num+=1
elif s==\'Home\':
key_home_num+=1
key_total_num+=1
elif s==\'Prior\':
key_prior_num+=1
key_total_num+=1
elif s==\'Snapshot\':
key_snapshot_num+=1
key_total_num+=1
elif s==\'Scroll\':
key_scroll_num+=1
key_total_num+=1
elif s==\'Pause\':
key_pause_num+=1
key_total_num+=1
elif s==\'Escape\':
key_escape_num+=1
key_total_num+=1
elif s==\'F1\':
key_f1_num+=1
key_total_num+=1
elif s==\'F2\':
key_f2_num+=1
key_total_num+=1
elif s==\'F3\':
key_f3_num+=1
key_total_num+=1
elif s==\'F4\':
key_f4_num+=1
key_total_num+=1
elif s==\'F5\':
key_f5_num+=1
key_total_num+=1
elif s==\'F6\':
key_f6_num+=1
key_total_num+=1
elif s==\'F7\':
key_f7_num+=1
key_total_num+=1
elif s==\'F8\':
key_f8_num+=1
key_total_num+=1
elif s==\'F9\':
key_f9_num+=1
key_total_num+=1
elif s==\'F10\':
key_f10_num+=1
key_total_num+=1
elif s==\'F11\':
key_f11_num+=1
key_total_num+=1
elif s==\'F12\':
key_f12_num+=1
key_total_num+=1
elif s==\'Numpad0\':
key_numpad0_num+=1
key_total_num+=1
elif s==\'Numpad1\':
key_numpad1_num+=1
key_total_num+=1
elif s==\'Numpad2\':
key_numpad2_num+=1
key_total_num+=1
elif s==\'Numpad3\':
key_numpad3_num+=1
key_total_num+=1
elif s==\'Numpad4\':
key_numpad4_num+=1
key_total_num+=1
elif s==\'Numpad5\':
key_numpad5_num+=1
key_total_num+=1
elif s==\'Numpad6\':
key_numpad6_num+=1
key_total_num+=1
elif s==\'Numpad7\':
key_numpad7_num+=1
key_total_num+=1
elif s==\'Numpad8\':
key_numpad8_num+=1
key_total_num+=1
elif s==\'Numpad9\':
key_numpad9_num+=1
key_total_num+=1
elif s==\'Numlock\':
key_numlock_num+=1
key_total_num+=1
elif s==\'Divide\':
key_divide_num+=1
key_total_num+=1
elif s==\'Multiply\':
key_multiply_num+=1
key_total_num+=1
elif s==\'Subtract\':
key_subtract_num+=1
key_total_num+=1
elif s==\'Add\':
key_add_num+=1
key_total_num+=1
elif s==\'Decimal\':
key_decimal_num+=1
key_total_num+=1
#定义一个退出的按键,并将记录的信息写入txt
if str(event.Key)==\'Pause\':
fobj.write("\n")
fobj.write("鼠标右键点击量: %d\n" % right_up_num)
fobj.write("鼠标左键点击量: %d\n" % left_up_num)
fobj.write("键盘总点击量: %d\n" % key_total_num)
fobj.write("a: %d\n" % key_a_num)
fobj.write("b: %d\n" % key_b_num)
fobj.write("c: %d\n" % key_c_num)
fobj.write("d: %d\n" % key_d_num)
fobj.write("e: %d\n" % key_e_num)
fobj.write("f: %d\n" % key_f_num)
fobj.write("g: %d\n" % key_g_num)
fobj.write("h: %d\n" % key_h_num)
fobj.write("i: %d\n" % key_i_num)
fobj.write("j: %d\n" % key_j_num)
fobj.write("k: %d\n" % key_k_num)
fobj.write("l: %d\n" % key_l_num)
fobj.write("m: %d\n" % key_m_num)
fobj.write("n: %d\n" % key_n_num)
fobj.write("o: %d\n" % key_o_num)
fobj.write("p: %d\n" % key_p_num)
fobj.write("q: %d\n" % key_q_num)
fobj.write("r: %d\n" % key_r_num)
fobj.write("s: %d\n" % key_s_num)
fobj.write("t: %d\n" % key_t_num)
fobj.write("u: %d\n" % key_u_num)
fobj.write("v: %d\n" % key_v_num)
fobj.write("w: %d\n" % key_w_num)
fobj.write("x: %d\n" % key_x_num)
fobj.write("y: %d\n" % key_y_num)
fobj.write("z: %d\n" % key_z_num)
fobj.write("enter: %d\n" % key_enter_num)
fobj.write("back: %d\n" % key_back_num)
fobj.write("0: %d\n" % key_0_num)
fobj.write("1: %d\n" % key_1_num)
fobj.write("2: %d\n" % key_2_num)
fobj.write("3: %d\n" % key_3_num)
fobj.write("4: %d\n" % key_4_num)
fobj.write("5: %d\n" % key_5_num)
fobj.write("6: %d\n" % key_6_num)
fobj.write("7: %d\n" % key_7_num)
fobj.write("8: %d\n" % key_8_num)
fobj.write("9: %d\n" % key_9_num)
fobj.write("~: %d\n" % key_oem_3_num)
fobj.write("r-: %d\n" % key_oem_minus_num)
fobj.write("r+: %d\n" % key_oem_plus_num)
fobj.write("tab: %d\n" % key_tab_num)
fobj.write("caps: %d\n" % key_cap_num)
fobj.write("Lshift: %d\n" % key_lshift_num)
fobj.write("Lctrl: %d\n" % key_lctrl_num)
fobj.write("Lwin: %d\n" % key_lwin_num)
fobj.write("Lalt: %d\n" % key_lalt_num)
fobj.write("space: %d\n" % key_space_num)
fobj.write("Rshift: %d\n" % key_rshift_num)
fobj.write("Rctrl: %d\n" % key_rctrl_num)
fobj.write("Rwin: %d\n" % key_rwin_num)
fobj.write("Ralt: %d\n" % key_ralt_num)
fobj.write(",<: %d\n" % key_oem_comma_num)
fobj.write(".>: %d\n" % key_oem_period_num)
fobj.write("/?: %d\n" % key_oem_2_num)
fobj.write(";: %d\n" % key_oem_1_num)
fobj.write("双引号: %d\n" % key_oem_7_num)
fobj.write("[{: %d\n" % key_oem_4_num)
fobj.write("]}: %d\n" % key_oem_5_num)
fobj.write("\|: %d\n" % key_oem_6_num)
fobj.write("左: %d\n" % key_left_num)
fobj.write("右: %d\n" % key_right_num)
fobj.write("上: %d\n" % key_up_num)
fobj.write("下: %d\n" % key_right_num)
fobj.write("delete: %d\n" % key_delete_num)
fobj.write("end: %d\n" % key_end_num)
fobj.write("pagedown: %d\n" % key_next_num)
fobj.write("insert: %d\n" % key_insert_num)
fobj.write("pageup: %d\n" % key_prior_num)
fobj.write("home: %d\n" % key_home_num)
fobj.write("print screen: %d\n" % key_snapshot_num)
fobj.write("scroll lock: %d\n" % key_scroll_num)
fobj.write("pause: %d\n" % key_pause_num)
fobj.write("esc: %d\n" % key_escape_num)
fobj.write("f1: %d\n" % key_f1_num)
fobj.write("f2: %d\n" % key_f2_num)
fobj.write("f3: %d\n" % key_f3_num)
fobj.write("f4: %d\n" % key_f4_num)
fobj.write("f5: %d\n" % key_f5_num)
fobj.write("f6: %d\n" % key_f6_num)
fobj.write("f7: %d\n" % key_f7_num)
fobj.write("f8: %d\n" % key_f8_num)
fobj.write("f9: %d\n" % key_f9_num)
fobj.write("f10: %d\n" % key_f10_num)
fobj.write("f11: %d\n" % key_f11_num)
fobj.write("f12: %d\n" % key_f12_num)
fobj.write("numpad0: %d\n" % key_numpad0_num)
fobj.write("numpad1: %d\n" % key_numpad1_num)
fobj.write("numpad2: %d\n" % key_numpad2_num)
fobj.write("numpad3: %d\n" % key_numpad3_num)
fobj.write("numpad4: %d\n" % key_numpad4_num)
fobj.write("numpad5: %d\n" % key_numpad5_num)
fobj.write("numpad6: %d\n" % key_numpad6_num)
fobj.write("numpad7: %d\n" % key_numpad7_num)
fobj.write("numpad8: %d\n" % key_numpad8_num)
fobj.write("numpad9: %d\n" % key_numpad9_num)
fobj.write("numlock: %d\n" % key_numlock_num)
fobj.write("divide: %d\n" % key_divide_num)
fobj.write("multiply: %d\n" % key_multiply_num)
fobj.write("subtract: %d\n" % key_subtract_num)
fobj.write("add: %d\n" % key_add_num)
fobj.write("decimal: %d\n" % key_decimal_num)
fobj.close()
win32api.PostQuitMessage()
return True
#主函数
if __name__ == "__main__":
key_a_num=0
key_b_num=0
key_c_num=0
key_d_num=0
key_e_num=0
key_f_num=0
key_g_num=0
key_h_num=0
key_i_num=0
key_j_num=0
key_k_num=0
key_l_num=0
key_m_num=0
key_n_num=0
key_o_num=0
key_p_num=0
key_q_num=0
key_r_num=0
key_s_num=0
key_t_num=0
key_u_num=0
key_v_num=0
key_w_num=0
key_x_num=0
key_y_num=0
key_z_num=0
key_enter_num=0
key_back_num=0
key_1_num=0
key_2_num=0
key_3_num=0
key_4_num=0
key_5_num=0
key_6_num=0
key_7_num=0
key_8_num=0
key_9_num=0
key_0_num=0
key_oem_3_num=0
key_oem_minus_num=0
key_oem_plus_num=0
key_tab_num=0
key_cap_num=0
key_lshift_num=0
key_lctrl_num=0
key_lwin_num=0
key_lalt_num=0
key_space_num=0
key_rshift_num=0
key_rctrl_num=0
key_rwin_num=0
key_ralt_num=0
key_oem_comma_num=0
key_oem_period_num=0
key_oem_2_num=0
key_oem_1_num=0
key_oem_7_num=0
key_oem_4_num=0
key_oem_5_num=0
key_oem_6_num=0
key_left_num=0
key_right_num=0
key_up_num=0
key_down_num=0
key_delete_num=0 #delete
key_end_num=0 #end
key_next_num=0 #page down
key_insert_num=0 #insert
key_home_num=0 #home
key_prior_num=0 #page up
key_snapshot_num=0 #print screen
key_scroll_num=0 #scroll lock
key_pause_num=0 #pause
key_escape_num=0
key_f1_num=0
key_f2_num=0
key_f3_num=0
key_f4_num=0
key_f5_num=0
key_f6_num=0
key_f7_num=0
key_f8_num=0
key_f9_num=0
key_f10_num=0
key_f11_num=0
key_f12_num=0
key_numpad0_num=0
key_numpad1_num=0
key_numpad2_num=0
key_numpad3_num=0
key_numpad4_num=0
key_numpad5_num=0
key_numpad6_num=0
key_numpad7_num=0
key_numpad8_num=0
key_numpad9_num=0
key_numlock_num=0
key_divide_num=0
key_multiply_num=0
key_subtract_num=0
key_add_num=0
key_decimal_num=0
key_total_num=0
right_up_num=0
left_up_num=0
#打开日志文件
file_name = "D:\\keyboard_recoder\\2018-01-26.txt"
fobj = open(file_name, \'w\')
#创建hook句柄
hm = pyHook.HookManager()
#监控鼠标
hm.MouseRightUp=onMouse_rightup
hm.MouseLeftUp=onMouse_leftup
hm.HookMouse()
#监控键盘
hm.KeyUp = onKeyboardEvent
hm.HookKeyboard()
#循环获取消息
pythoncom.PumpMessages()
#关闭日志文件
fobj.close()
上述代码记录了键盘上的每一个按钮敲击的次数,当然不同的键盘所包含的键数不同,还得根据实际情况进行改进。将这段代码保存为.py文件,这样每天在打开电脑后双击运行。在结束使用电脑后按下Pause键退出,即可看到一天的键盘和鼠标点击次数。
data visualization
利用上述程序,我记录了20天鼠标和键盘的敲击的次数,并对数据进行稍微的处理,得到一个Excel表格。
20天内鼠标左键点击了44035下,右键点击了1228下,键盘总共敲击了91960次。Excel表格数据看起来不是很直观,为了更加直观地展示数据,采用Echarts对数据进行简单的可视化处理,即用图表来表示数据。这里选择层叠柱状图来展现20天内每个键位点击的数量,同时也能展现总体的数量。
最后利用热力图最直观地展现敲击次数的键位。
热力图的制作首先从网上找到高清的键盘图作为热力图的地图,然后用像素横纵坐标定义每个键位大概的位置,但是最后结果不是特别好。这里推荐一个网址,可以在线根据文本实时生成键盘键位图,但是似乎只能记录能在屏幕上能打出符号的键位,空格、换行等都无法记录,不过效果的确不错。代码是开源的,大家可以去GitHub下载。实现键盘热力图的大神还有许多有意思的项目,有兴趣的同学可以研究下。
- https://www.patrick-wied.at/
我的Backspace敲击次数排在第三位,看来准确率有些低呀。大家快去记录一下自己每天要狂敲多少次键盘吧。