KeymouseGo:当鼠标键盘的“重复劳动“被编译成一张可跳转的事件图
KeymouseGo当鼠标键盘的重复劳动被编译成一张可跳转的事件图【免费下载链接】KeymouseGo类似按键精灵的鼠标键盘录制和自动化操作 模拟点击和键入 | automate mouse clicks and keyboard input项目地址: https://gitcode.com/gh_mirrors/ke/KeymouseGoKeymouseGo 是一个 Python 编写的跨平台鼠标键盘录制与自动化执行框架。它的核心命题并不新鲜——把人的重复操作变成可重放的指令序列——真正难的是同一段脚本如何在不同操作系统、不同分辨率、不同 DPI 缩放的机器上复现出与录制时一致的点击与键入。本文不罗列功能而是沿着录制端到回放端这条数据流拆解它的事件抽象、坐标换算、时序控制、脚本编译与插件扩展五层设计。分层先解决统一还是先解决差异录一段操作换一台机器回放是此类工具最常见的死法。底层输入机制完全分裂Windows 靠 Win32 消息钩子Linux 与 macOS 依赖 pynput 这类事件监听库。若在业务代码里写满if platform Windows录制器、回放器、UI 三个模块都会被平台判断污染。KeymouseGo 的答案是在导入期做一次分支而不是在运行期做一万次分支。看Event/__init__.py与Recorder/__init__.py两个目录都在import时根据platform.system()一次性选定平台实现并把结果以统一符号导出# Event/__init__.py —— 导入期工厂而非运行期分发 from platform import system if system() Windows: import Event.WindowsEvents as _Event event_cls _Event.WindowsEvent # Win32 钩子 mouse_event 注入 elif system() in [Linux, Darwin]: import Event.UniversalEvents as _Event event_cls _Event.UniversalEvent # pynput 监听 pyautogui 注入 else: raise OSError(Unsupported platform {}.format(system())) ScriptEvent event_cls # 上层只认这一个名字这意味着从 UI 到执行引擎全程只与ScriptEvent打交道平台差异被压缩在事件类的execute方法内。这是一次典型的模板方法 简单工厂组合抽象基类锁死流程子类替换实现细节。事件抽象用四个字段描述一切操作抽象层把任意一次输入收敛成四个字段——delay延时、event_typeEM/EK/EX 三类、action_type动作名、action参数。抽象基类只负责从字典反序列化并留出execute给子类实现# Event/Event.py —— 事件抽象基类 from abc import ABCMeta, abstractmethod from typing import Dict, Any class Event(metaclassABCMeta): def __init__(self, content: Dict[str, Any]): # 统一从字典初始化延时、事件类型、动作类型、动作参数 for key in [delay, event_type, action_type, action]: setattr(self, key, content[key]) def sleep(self, thd): thd.sleep(self.delay) # 延时经由执行器代理便于插入暂停/唤醒逻辑 abstractmethod def execute(self, thdNone): 由平台子类实现真正的输入注入 pass这个设计的价值在于录制与回放完全解耦录制端只负责把原始输入翻译成这四个字段的字典回放端只负责把字典变回输入。中间任意环节——序列化、编辑、版本管理——都不依赖任何平台代码。而sleep不直接调用time.sleep而是经由执行线程代理为后面的暂停/恢复机制留了关键接口。坐标难题存像素还是存比例桌面自动化最隐蔽的坑是显示缩放。同一台机器Windows 缩放从 100% 调到 150%GetCursorPos返回的像素坐标可能不变但物理屏幕映射已经变了跨机器回放时分辨率差异同样致命。如果脚本里写死像素坐标换环境必然偏移。KeymouseGo 没有押注单一方案而是按平台和场景混合使用三种坐标系取舍逻辑值得拆开看坐标系实现方式跨分辨率DPI 适配多显示器绝对像素录制与回放都存(x, y)差依赖进程 DPI 感知好相对比例存(x/SW, y/SH)回放时乘回当前分辨率好随分辨率线性缩放需特殊处理规范化绝对坐标映射到 0~65535 区间交给系统换算一般系统级处理天然免疫缩放好通用平台Linux/macOS走比例路线录制时把像素除以当时的屏幕宽高存成 0~1 的小数回放时再乘以当前屏幕宽高还原。这段逻辑写在录制器里# Recorder/UniversalRecorder.py —— 录制时归一化坐标 def get_mouse_event(x, y, action_type): # 关键把物理像素转成屏幕宽高的比例0~1 之间的小数 tx x / SW ty y / SH delay get_delay(action_type) if delay 0: return None # 被轨迹采样节流过滤不产生冗余事件 return globalv.ScriptEvent({ delay: delay, event_type: EM, action_type: action_type, action: (tx, ty) # 存储相对坐标而非像素 })Windows 端则更精细。单显示器时回放用mouse_event(MOUSEEVENTF_ABSOLUTE, ...)把坐标换算到 0~65535 的规范化区间——这是 Win32 的经典技巧系统会按当前 DPI 实时换算成物理像素因此天然规避缩放偏差一旦检测到多显示器则退回SetCursorPos用真实像素因为规范化坐标在多屏拼接下无法可靠定位# Event/WindowsEvents.py —— 回放时按场景切换坐标策略 if isinstance(x, int) and isinstance(y, int): if numofmonitors 1: win32api.SetCursorPos([x, y]) # 多显示器必须真实像素 else: # MOUSEEVENTF_ABSOLUTE 的坐标范围是 0~65535 # 系统按当前 DPI 换算成物理像素规避缩放偏差 nx int(x * 65535 / SW) ny int(y * 65535 / SH) win32api.mouse_event( win32con.MOUSEEVENTF_ABSOLUTE | win32con.MOUSEEVENTF_MOVE, nx, ny, 0, 0)这种默认比例、特殊场景回退绝对坐标的混合策略本质是对两类坐标系的缺陷做对冲比例坐标负责跨分辨率规范化坐标负责 DPI 与多显示器。代价是坐标语义在不同平台不再统一但换来的是实测可用的精度。时序精度从 200ms 采样到可中断的毫秒睡眠自动化失败的第二大根源是时序。回放快了界面还没响应慢了脚本拖沓到无法接受。KeymouseGo 的时序链由三段构成。录制端每个事件都携带delay其值为距上一个事件的时间差毫秒由current_ts()time.time() * 1000相减得出。这个字段让事件序列天然携带节奏信息脚本文件本身无需额外的时间表。轨迹节流鼠标移动事件极其高频若不节流一次普通操作能录出上千条mouse move。录制器引入mouse_interval_ms默认 200ms移动事件间隔小于该值的直接丢弃# Recorder/UniversalRecorder.py —— 轨迹采样节流 def get_delay(action_type): delay globalv.current_ts() - globalv.latest_time # 录制鼠标轨迹的精度数值越小越精准同时冗余事件越多 mouse_move_interval_ms globalv.mouse_interval_ms or 999999 if action_type mouse move and delay mouse_move_interval_ms: return -1 # 返回 -1 表示丢弃该事件 globalv.latest_time globalv.current_ts() return delay这是一个可调的精度-冗余权衡参数追求轨迹还原度就调小追求脚本体积小就调大。回放端delay的执行不是简单time.sleep而是借助 Qt 的QWaitConditionQDeadlineTimer。其精妙之处在于睡眠本身可以被外部打断。执行线程的sleep锁定互斥量后等待条件变量暂停时wait_if_pause让线程挂起恢复时wakeAll唤醒停止时直接返回让循环退出。这让暂停/继续/停止三个操作不用靠轮询标志位而是靠线程同步原语实现回放线程始终能被及时接管。脚本是图不是纸带早期版本的回放器像读磁带一个数组顺序执行到底。但这种模型无法表达循环到某一步重试根据条件分支跳转到指定位置——而这些恰恰是自动化脚本的高频需求。KeymouseGo 的关键设计是在解析期把脚本编译成一张链表图而不是执行期做解释。脚本本体是 JSON5宽松版 JSON允许注释和尾逗号由Parser.link_objects处理。它的实现相当有想法倒序遍历脚本数组从末尾向前构建JsonObject节点每个节点持有next_object指针这样正向执行时天然就是顺序链表# Util/Parser.py —— 倒序遍历 JSON5 脚本把事件数组编成链表 def link_objects(objects, target_object, label_maps, pending_dict): objects.reverse() # 从末尾向前构建next 指针自然形成 current None for content in objects: current JsonObject(content) if content.get(label): label_maps[content[label]] current # 记录跳转锚点 if content[type] in (event, subroutine, custom): current.next_object target_object # 顺序连接 elif content[type] if: # 条件节点分裂出真/假两条后继子序列递归建链 current.next_object link_objects(content[do], target_object, ...) current.next_object_if_false link_objects(content[else], target_object, ...) elif content[type] goto: # 目标 label 可能尚未收录先挂起全图建完后再补指针 pending_dict[current] content[tolabel] target_object current return current两个细节值得玩味。其一goto采用二次解析前向跳转目标在后面可以立即解析后向跳转目标在前面则先存入pending_dict待全部 label 收录后再回填指针——这避免了递归建链时的顺序陷阱。其二执行器run_object只需沿着next_object走if节点根据插件判断结果选择next_object或next_object_if_falsegoto节点什么都不做、只改变指针走向。控制流被完全折叠进数据结构执行引擎没有一行跳转逻辑。subroutine类型则支持嵌套调用子脚本相当于把脚本文件当成可复用的函数。这套JSON5 源文件 链表编译产物的设计让脚本既能用任何文本编辑器离线编辑、进版本控制又能在运行时获得接近原生循环的性能。内核之外插件系统的边界控制执行引擎做得很薄的另一面是把扩展能力交给了插件系统。PluginInterface定义了两个抽象方法register_functions返回函数名 - 可调用对象的映射供脚本通过call/judge/custom节点调用register_record_functions预留了录制期扩展位。# Plugin/Interface.py —— 插件接口只暴露注册能力 class PluginInterface: functions: List[Callable] [] def __init__(self, manifest: Dict): self.meta PluginMeta(manifest) # 从 manifest.json5 读取元信息 abstractmethod def register_functions(self) - Dict[str, Callable]: 返回 {函数名: 函数}脚本中通过 call 节点调用 abstractmethod def register_record_functions(self) - List[Callable]: 录制期扩展点可对捕获的事件做预处理PluginManager负责生命周期扫描plugins/目录读取每个子目录的manifest.json5按entry与plugin_class字段用SourceFileLoader动态导入并实例化最后汇总所有register_functions结果到一张函数表。执行器在遇到call节点时查表调用查不到就报错。这种设计把内核保持最小、能力可插拔落到了实处图像识别、OCR、网络请求这些重逻辑统统不进主代码而是作为插件注册。代价是插件与脚本之间只有函数名这一层弱契约缺少参数校验和类型约束——这是典型的工程取舍灵活性优先安全性靠插件自身负责。落地场景报表数据录入的完整闭环把上述机制串起来看一个具体场景财务人员每天要把 CSV 中的几十行金额录入进网页表单。录制操作者手动完成第一行数据的输入录制器把动作序列存为 JSON5 脚本坐标已是相对比例时序节奏保留在delay中改造手工给脚本包裹一层循环并用插件提供的read_csv函数逐行取数脚本中通过call节点调用回放脚本在任意分辨率、任意缩放比例的机器上执行if节点判断单元格是否为空来决定是否跳过goto实现循环体的跳转控制{ scripts: [ { type: loop, variable: row, range: [1, 50], scripts: [ { type: call, name: read_csv, args: [data.csv, ${row}, amount] }, { type: event, event_type: EM, delay: 120, action_type: mouse left click, action: [0.15%, 0.20%] }, { type: event, event_type: EX, delay: 80, action_type: input, action: ${csv_data} } ] } ] }这里能看出比例坐标与延时字段的实际价值脚本脱离录制机后依然可靠且循环体内部每次迭代的节奏都被delay精确控制不会因机器性能差异而时快时慢。生态与演进项目的扩展路径清晰功能型插件图像识别、OCR、数据源接入走register_functions控制型插件条件判断、循环、异常重试直接复用已有的if/goto图结构集成型插件与 CI、云服务对接则可借助命令行模式KeymouseGo.py script.json5 -rt N脱离 GUI 运行。README 与多语言文案assets/i18n 下的 ts/qm 文件表明项目对多语言与打包分发有完整支持。未来方向大致三条一是插件系统的契约增强——为call节点引入参数 schema 校验二是轨迹录制的智能降采样用算法替代固定 200ms 阈值三是把sequence/subroutine组合成更高级的流程模板。这些演进都建立在现有的事件图模型之上无需推翻内核。技术总结与启示回到开篇的问题KeymouseGo 如何让一段脚本在异构环境下稳定复现答案不是一个杀手级特性而是一组环环相扣的取舍——导入期平台分支换来代码纯净比例坐标为主、规范化坐标为辅换来跨环境精度事件自带 delay 可中断睡眠换来节奏可控解析期编译成链表图换来脚本的表达力薄内核 函数表插件换来生态扩展空间。每个环节都以录制端翻译、回放端还原为轴心形成闭环。对同类工具的启示同样明确桌面自动化的可靠性不取决于某一次点击的注入成功率而取决于从录制到回放整条链路上语义是否一致。坐标、时序、控制流这三件事任何一件在两台机器之间产生偏差脚本都会失败。KeymouseGo 的价值在于把这三件事都显式建模并让它们可以独立调试——这正是录制回放类工具最值得借鉴的架构思路。【免费下载链接】KeymouseGo类似按键精灵的鼠标键盘录制和自动化操作 模拟点击和键入 | automate mouse clicks and keyboard input项目地址: https://gitcode.com/gh_mirrors/ke/KeymouseGo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

2022国赛数学建模深度复盘:从机理建模到数据分析的实战路径解析

2022国赛数学建模深度复盘:从机理建模到数据分析的实战路径解析

1. 项目概述:一次对经典赛题的深度复盘又到了每年国赛备赛的黄金期,不少同学开始翻看往年的赛题和优秀论文,试图从中找到一些规律和灵感。2022年的国赛A、B、C三题,可以说是近年来风格非常鲜明、区分度极高的一届。今天我们不聊空…

2026/10/13 11:45:33 阅读更多 →
KMS_VL_ALL_AIO使用教程:用这个KMS激活工具一次部署长期搞定Windows与Office

KMS_VL_ALL_AIO使用教程:用这个KMS激活工具一次部署长期搞定Windows与Office

KMS_VL_ALL_AIO使用教程:用这个KMS激活工具一次部署长期搞定Windows与Office 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO KMS_VL_ALL_AIO 是一款以单个脚本文件承载全部激活逻辑的…

2026/10/14 2:46:54 阅读更多 →
让Windows更新起死回生:Reset Windows Update Tool 完整修复指南

让Windows更新起死回生:Reset Windows Update Tool 完整修复指南

让Windows更新起死回生:Reset Windows Update Tool 完整修复指南 【免费下载链接】Reset-Windows-Update-Tool Troubleshooting Tool with Windows Updates (Developed in Dev-C). 项目地址: https://gitcode.com/gh_mirrors/re/Reset-Windows-Update-Tool 当…

2026/10/14 2:46:54 阅读更多 →

最新新闻

本地化素材管理工作流:用文件夹+脚本把写作周期从三天缩到三小时

本地化素材管理工作流:用文件夹+脚本把写作周期从三天缩到三小时

很多人写博客、做教程、做知识付费内容,卡得最多的不是文笔,不是选题,而是生产流程。素材散落在手机截图、浏览器收藏夹、聊天记录和草稿箱里,真正要动手写的时候,找资料找半天,排版又要折腾半天&#xff0…

2026/10/14 3:01:31 阅读更多 →
kubectl --generator弃用全解析:从原理到迁移避坑指南

kubectl --generator弃用全解析:从原理到迁移避坑指南

如果你最近在跑 K8s 部署脚本时,终端里突然冒出一行kubectl run --generatordeployment/v1 is DEPRECATED...的警告,先别慌,这不是集群坏了,而是你手里的命令还在用几年前的旧写法。kubectl 的--generator参数从 1.12 开始被标记为…

2026/10/14 3:01:31 阅读更多 →
WoSignCode代码签名证书更换实战:时间戳、证书链与批量签名全流程

WoSignCode代码签名证书更换实战:时间戳、证书链与批量签名全流程

这几天刚帮项目把一批到期代码签名证书换完,整个流程走下来,顺手把沃通代码签名工具WoSignCode的用法从头到尾重理了一遍。这个工具看着不起眼,真到证书临期、用户那边开始报“未知发布者”的时候,它就是那个能少熬夜的救急设备。…

2026/10/14 3:01:31 阅读更多 →
Abaqus中水力压裂裂缝交互模拟技术解析

Abaqus中水力压裂裂缝交互模拟技术解析

1. 水力压裂模拟中的裂缝交互难题在油气田开发领域,水力压裂技术已经成为非常规储层增产的核心手段。但实际作业中经常会遇到一个棘手问题:当人工水力裂缝在扩展过程中遭遇天然裂缝网络时,其扩展路径和开度会发生怎样的变化?这个问…

2026/10/14 3:01:31 阅读更多 →
Django电商订单分析系统:智能处理与可视化优化

Django电商订单分析系统:智能处理与可视化优化

1. 项目背景与核心价值电商行业每天产生海量订单数据,但大多数中小商家缺乏专业数据分析能力。这套基于Django的Python电商订单分析系统,正是为解决这个痛点而生。我在实际电商项目中发现,原始数据中藏着大量金矿——用户购买时段分布、热销商…

2026/10/14 3:01:31 阅读更多 →
DLMS协议实战解析:从HDLC帧结构到AARQ/AARE调试指南

DLMS协议实战解析:从HDLC帧结构到AARQ/AARE调试指南

简介:这是IEC62056协议族(DLMS协议族)的中文说明手册,面向电能量数据采集终端研发与调试人员,解决与DLMS电能表通讯时的协议理解与报文解析问题。手册按三层模型展开:物理层负责底层硬件操作与连接建立&…

2026/10/14 3:00:31 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →