【python项目推荐】键盘监控--统计打字频率

2024-04-22 19:20

本文主要是介绍【python项目推荐】键盘监控--统计打字频率,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文:https://greptime.com/blogs/2024-03-19-keyboard-monitoring
代码:https://github.com/GreptimeTeam/demo-scene/tree/main/keyboard-monitor

项目简介

该项目实现了打字频率统计及可视化功能。
在这里插入图片描述

主要使用的库

pynput:允许您控制和监视输入设备。 这里我们用来获取键盘输入。
SQLAlchemy:数据库操作。 这里我们用来保存键盘输入。
streamlit:提供可视化界面。

项目组成

agent.py :获得键盘输入
display.py:可视化

补充说明

如果你不想用原文的数据库,也可以替换为本地的数据库,如免安装的sqlite

agent.py

# agent.py
from dotenv import load_dotenv
from pynput import keyboard
from pynput.keyboard import Keyimport concurrent.futures
import logging
import os
import queue
import sqlalchemy
import sqlalchemy.exc
import sys
import timeMODIFIERS = {Key.shift, Key.shift_l, Key.shift_r,Key.alt, Key.alt_l, Key.alt_r, Key.alt_gr,Key.ctrl, Key.ctrl_l, Key.ctrl_r,Key.cmd, Key.cmd_l, Key.cmd_r,
}TABLE = sqlalchemy.Table('keyboard_monitor',sqlalchemy.MetaData(),sqlalchemy.Column('hits', sqlalchemy.String),sqlalchemy.Column('ts', sqlalchemy.DateTime),
)if __name__ == '__main__':load_dotenv()log = logging.getLogger("agent")log.setLevel(logging.DEBUG)formatter = logging.Formatter('%(asctime)s %(levelname)s %(funcName)s %(message)s')file_handler = logging.FileHandler(f'agent-{time.time_ns()}.log', encoding='utf-8')file_handler.setLevel(logging.DEBUG)file_handler.setFormatter(formatter)stdout_handler = logging.StreamHandler(sys.stdout)stdout_handler.setLevel(logging.INFO)stdout_handler.setFormatter(formatter)log.addHandler(file_handler)log.addHandler(stdout_handler)#engine = sqlalchemy.create_engine(os.environ['DATABASE_URL'], #                                  echo_pool=True, #                                  isolation_level='AUTOCOMMIT')engine = sqlalchemy.create_engine("sqlite:///keyboard.db")current_modifiers = set()pending_hits = queue.Queue()cancel_signal = queue.Queue()def on_press(key):if key in MODIFIERS:current_modifiers.add(key)else:hits = sorted([ str(key) for key in current_modifiers ]) + [ str(key) ]hits = '+'.join(hits)pending_hits.put(hits)log.debug(f'{key} pressed, current_modifiers: {current_modifiers}')def on_release(key):if key in MODIFIERS:try:current_modifiers.remove(key)except KeyError:log.warning(f'Key {key} not in current_modifiers {current_modifiers}')log.debug(f'{key} released, current_modifiers: {current_modifiers}')#with engine.connect() as connection:#    connection.execute(sqlalchemy.sql.text("""#        CREATE TABLE IF NOT EXISTS keyboard_monitor (#            hits STRING NULL,#            ts TIMESTAMP(3) NOT NULL,#            TIME INDEX ("ts")#        ) ENGINE=mito WITH( regions = 1, ttl = '3months')#    """))# ...from sqlalchemy import create_engine, Table, Column, String, TIMESTAMP, MetaData, Indexmetadata = MetaData()keyboard_monitor = Table('keyboard_monitor', metadata,Column('hits', String, nullable=True),Column('ts', TIMESTAMP, nullable=False),)metadata.create_all(engine)def sender_thread():retries = 0while True:hits = pending_hits.get()log.debug(f'got: {hits}')if hits is None:log.info("Exiting...")breakwith engine.connect() as connection:try:log.debug(f'sending: {hits}')connection.execute(TABLE.insert().values(hits=hits, ts=sqlalchemy.func.now()))connection.commit()# ...log.info(f'sent: {hits}')retries = 0except sqlalchemy.exc.OperationalError as e:if retries >= 10:log.error(f'Retry exceeds. Operational error: {e}')pending_hits.put(hits)continueif e.connection_invalidated:log.warning(f'Connection invalidated: {e}')pending_hits.put(hits)continuemsg = str(e)if "(1815, 'Internal error: 1000')" in msg:# TODO 1815 - should not handle internal error;# see https://github.com/GreptimeTeam/greptimedb/issues/3447log.warning(f'Known operational error: {e}')pending_hits.put(hits)continueelif '2005' in msg and 'Unknown MySQL server host' in msg:log.warning(f'DNS temporary unresolved: {e}')pending_hits.put(hits)continueraise efinally:retries += 1def listener_thread():with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:log.info("Listening...")cancel_signal.get()pending_hits.put(None)log.info("Exiting...")with concurrent.futures.ThreadPoolExecutor() as executor:sender = executor.submit(sender_thread)listener = executor.submit(listener_thread)try:f = concurrent.futures.wait([sender, listener], return_when=concurrent.futures.FIRST_EXCEPTION)for fut in f.done:log.error(f'Unhandled exception for futures: {fut.exception(timeout=0)}')except KeyboardInterrupt as e:log.info("KeyboardInterrupt. Exiting...")except Exception as e:log.error(f'Unhandled exception: {e}')finally:cancel_signal.put(True)

display.py

# display.py
import datetime
import os
from dotenv import load_dotenv
import pytz
import streamlit as st
import tzlocal
import pandasst.title("Keyboard Monitor")load_dotenv()
#conn = st.connection(
##    type="sql",
#    url="sqlite:///keyboard.db",
#)conn = st.connection('keyboard', type='sql', url="sqlite:///keyboard.db")df = conn.query("SELECT COUNT(*) AS total_hits FROM keyboard_monitor")
st.metric("Total hits", df.total_hits[0])most_frequent_key, most_frequent_combo = st.columns(2)
df = conn.query("""
SELECT hits, COUNT(*) as times
FROM keyboard_monitor
WHERE hits NOT LIKE '%+%'
GROUP BY hits
ORDER BY times DESC limit 1;
""")
most_frequent_key.metric("Most frequent key", df.hits[0])
df = conn.query("""
SELECT hits, COUNT(*) as times
FROM keyboard_monitor
WHERE hits LIKE '%+%'
GROUP BY hits
ORDER BY times DESC limit 1;
""")
most_frequent_combo.metric("Most frequent combo", df.hits[0])top_frequent_keys, top_frequent_combos = st.columns(2)
df = conn.query("""
SELECT hits, COUNT(*) as times
FROM keyboard_monitor
WHERE hits NOT LIKE '%+%'
GROUP BY hits
ORDER BY times DESC limit 10;
""")
top_frequent_keys.subheader("Top 10 keys")
top_frequent_keys.dataframe(df)
df = conn.query("""
SELECT hits, COUNT(*) as times
FROM keyboard_monitor
WHERE hits LIKE '%+%'
GROUP BY hits
ORDER BY times DESC limit 10;
""")
top_frequent_combos.subheader("Top 10 combos")
top_frequent_combos.dataframe(df)st.header("Find your inputs frequency of day")
local_tz = tzlocal.get_localzone()
hours = int(local_tz.utcoffset(datetime.datetime.now()).total_seconds() / 3600)
if hours > 0:offset = f" + INTERVAL '{hours} hours'"
elif hours < 0:offset = f" - INTERVAL '{hours} hours'"
else:offset = ''
d = st.date_input("Pick a day:", value=datetime.date.today())
query = f"""
SELECT ts,COUNT(1) AS times
FROM keyboard_monitor
WHERE strftime('%Y-%m-%d', ts, 'localtime') = '{d}'
GROUP BY strftime('%Y-%m-%d %H:00:00', ts)
ORDER BY ts ASC
LIMIT 10;
"""df = conn.query(query)
#print(df.keys())
df['ts'] = pandas.to_datetime(df['ts'])
df['ts'] = df['ts'].dt.tz_localize(pytz.utc).dt.tz_convert(local_tz)
st.dataframe(df)

这篇关于【python项目推荐】键盘监控--统计打字频率的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/926644

相关文章

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

Python pandas库自学超详细教程

《Pythonpandas库自学超详细教程》文章介绍了Pandas库的基本功能、安装方法及核心操作,涵盖数据导入(CSV/Excel等)、数据结构(Series、DataFrame)、数据清洗、转换... 目录一、什么是Pandas库(1)、Pandas 应用(2)、Pandas 功能(3)、数据结构二、安

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Springboot项目启动失败提示找不到dao类的解决

《Springboot项目启动失败提示找不到dao类的解决》SpringBoot启动失败,因ProductServiceImpl未正确注入ProductDao,原因:Dao未注册为Bean,解决:在启... 目录错误描述原因解决方法总结***************************APPLICA编

Python安装Pandas库的两种方法

《Python安装Pandas库的两种方法》本文介绍了三种安装PythonPandas库的方法,通过cmd命令行安装并解决版本冲突,手动下载whl文件安装,更换国内镜像源加速下载,最后建议用pipli... 目录方法一:cmd命令行执行pip install pandas方法二:找到pandas下载库,然后

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

使用Python构建智能BAT文件生成器的完美解决方案

《使用Python构建智能BAT文件生成器的完美解决方案》这篇文章主要为大家详细介绍了如何使用wxPython构建一个智能的BAT文件生成器,它不仅能够为Python脚本生成启动脚本,还提供了完整的文... 目录引言运行效果图项目背景与需求分析核心需求技术选型核心功能实现1. 数据库设计2. 界面布局设计3

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

Python进行JSON和Excel文件转换处理指南

《Python进行JSON和Excel文件转换处理指南》在数据交换与系统集成中,JSON与Excel是两种极为常见的数据格式,本文将介绍如何使用Python实现将JSON转换为格式化的Excel文件,... 目录将 jsON 导入为格式化 Excel将 Excel 导出为结构化 JSON处理嵌套 JSON: