KeyMouseGo使用心得
目录
notepad--优化代码
- 坐标点位正则表达式替换鼠标抬起坐标,由
坐标点位-->当前点击位置
left up",action: \[.*?\]-->left up",action: \[-1\, -1\]
![image]()
JSON5脚本批量处理工具 全量最终需求文档
优先级说明:核心约束 > 功能规则 > 输出规则
一、核心约束(最高优先级,所有实现必须严格遵守)
- 处理全程不得破坏原文件的原始格式与内容结构,禁止通过JSON/JSON5解析后重写的方式实现,必须采用纯文本逐行处理方案
- 必须100%完整保留原文件所有内容:包含//开头的注释行、空行、外层结构的缩进与换行,输出文件与原文件视觉风格完全一致
- 仅可对符合规则的内容进行修改,其余内容、格式、标点不得改动,允许的修改范围仅为:
3.1 删除符合规则的mouse move事件行
3.2 修改指定事件的delay数值
3.3 去除指定位置之间的空白字符 - 所有处理均不修改、不覆盖原文件,处理结果生成独立新文件,新文件默认保存在原文件同级目录
二、基础交互要求
- 支持批量处理 .json5 格式文件
- 通过系统原生可视化文件选择窗口选文件,支持按住Ctrl多选多个文件
- 处理完成后在控制台输出处理统计:成功数量、失败数量、对应文件路径
三、功能1:JSON5格式单行化处理
3.1 需去除空白、合并为一行的规则
对以下位置之间的所有空白字符(空格、回车、换行、制表符等全部空白)进行去除,合并为同一行:
- { 与 delay 之间
- , 与 event_type 之间
- , 与 action_type 之间
- , 与 action 之间
- [ 与 " 之间
- , 与 " 之间
- , 与 type 之间
- 字符串数组(如action字段的数组)结尾的 , 与 ] 之间
3.2 禁止合并规则(必须保留原有换行与缩进)
以下场景不得去除空白、不得合并,必须保留原始格式:
- 最外层scripts对象数组结尾的 }, 与 ] 之间
- 最外层结构的 ], 与 } 之间
- 所有注释行、空行、外层声明行(如 scripts: [ )
四、功能2:鼠标事件delay累加与精简处理
处理对象:文件中scripts数组内的所有事件
4.1 普通状态基础规则
- 遍历事件序列,遇到 action_type 为 "mouse move" 的事件时,将该事件的delay数值累加到延迟累计池,同时删除该事件行
- 遇到第一个非 "mouse move" 类型的事件时,将延迟累计池的总数值叠加到该事件的delay字段上,叠加完成后重置累计池
- 若文件末尾全部为mouse move事件、无后续非move事件,这些事件直接删除,累计的延迟值不再处理
4.2 拖拽场景特殊保护规则
- 触发条件:遇到 action_type 为 "mouse left down" 的事件后,立即进入拖拽保护状态
- 保护期规则:拖拽状态内,所有mouse move事件完整保留,不参与延迟累加、不被删除
- 退出条件:遇到 action_type 为 "mouse left up" 的事件后,立即退出拖拽保护状态,恢复普通状态规则
- 边界兼容:若只有mouse left down事件、无对应mouse left up事件,后续所有mouse move事件持续保留
五、输出文件命名规则
根据执行的功能组合,新文件命名规则如下:
- 仅执行格式单行化处理:原文件名 + Format + 原后缀 (例:record.json5 → recordFormat.json5)
- 仅执行事件精简处理:原文件名 + _Delay + 原后缀 (例:record.json5 → record_Delay.json5)
- 同时执行格式单行化+事件精简处理:原文件名 + _FormatDelay + 原后缀 (例:record.json5 → record_FormatDelay.json5)
脚本批量处理录屏文件JSON5
点击查看代码
import tkinter as tk
from tkinter import filedialog
import os
import re
# ===================== 功能配置开关 =====================
# 开启=执行对应功能,自动匹配对应输出文件名规则
ENABLE_FORMAT_PROCESS = True # 是否执行【格式单行化处理】
ENABLE_DELAY_PROCESS = True # 是否执行【鼠标事件delay累加精简处理】
# =======================================================
def process_delay_events(lines):
"""
功能2:鼠标事件delay累加与精简处理
严格遵守拖拽保护规则,所有非事件行(注释、空行、外层结构)原样保留
依赖:输入的每个事件必须为完整单行(先经过格式单行化处理)
"""
result_lines = []
delay_accumulator = 0 # 普通状态下的delay累计池
is_dragging = False # 拖拽保护状态标记
for line in lines:
stripped_line = line.strip()
# 非事件行:注释、空行、外层结构行,直接原样保留
if (stripped_line.startswith('//')
or stripped_line == ''
or ('action_type' not in line and 'delay' not in line)):
result_lines.append(line)
continue
# 提取事件核心字段,提取失败则原样保留
action_match = re.search(r'action_type:\s*"([^"]+)"', line)
delay_match = re.search(r'delay:\s*(\d+)', line)
if not action_match or not delay_match:
result_lines.append(line)
continue
action_type = action_match.group(1)
origin_delay = int(delay_match.group(1))
# ========== 拖拽状态:所有事件完整保留 ==========
if is_dragging:
result_lines.append(line)
# 遇到鼠标抬起事件,退出拖拽保护状态
if action_type == 'mouse left up':
is_dragging = False
continue
# ========== 普通状态:累加+删除规则 ==========
if action_type == 'mouse move':
# 累加delay,不保留该事件行
delay_accumulator += origin_delay
else:
# 将累计delay叠加到当前非move事件
new_delay = origin_delay + delay_accumulator
new_line = re.sub(r'delay:\s*\d+', f'delay: {new_delay}', line, count=1)
result_lines.append(new_line)
delay_accumulator = 0
# 遇到鼠标按下事件,进入拖拽保护状态
if action_type == 'mouse left down':
is_dragging = True
return result_lines
def process_format(content):
"""
功能1:JSON5格式单行化处理
仅去除指定位置空白,严格遵守最外层结构禁止合并规则
"""
# 格式替换规则:匹配(前缀)(空白字符)(后缀),替换为 前缀+后缀
replace_rules = [
# 1. { 与 delay 之间的空白
(r'(\{)\s+(delay)', r'\1\2'),
# 2. , 与 event_type 之间的空白
(r'(,)\s+(event_type)', r'\1\2'),
# 3. , 与 action_type 之间的空白
(r'(,)\s+(action_type)', r'\1\2'),
# 4. , 与 action 之间的空白
(r'(,)\s+(action)', r'\1\2'),
# 5. [ 与 " 之间的空白
(r'(\[)\s+(")', r'\1\2'),
# 6. , 与 " 之间的空白
(r'(,)\s+(")', r'\1\2'),
# 7. , 与 type 之间的空白
(r'(,)\s+(type)', r'\1\2'),
# 8. 字符串数组结尾的 , 与 ] 之间的空白(仅匹配字符串数组,不触碰对象数组结尾)
(r'(",)\s+(\])', r'\1\2'),
# 9. 事件对象结尾的 , 与 } 之间的空白(排除最外层],与},符合禁止合并规则)
(r'(?<!\]),\s+(\})', r',\1'),
]
processed = content
for pattern, repl in replace_rules:
processed = re.sub(pattern, repl, processed)
return processed
def process_single_file(file_path):
"""单个文件完整处理流程:先格式单行化 → 再事件处理,保证识别准确"""
# 1. 读取原文件,完整保留所有原始格式与换行
with open(file_path, 'r', encoding='utf-8') as f:
origin_content = f.read()
current_content = origin_content
# 2. 第一步:先执行格式单行化处理,把每个事件合并为完整一行
if ENABLE_FORMAT_PROCESS:
current_content = process_format(current_content)
# 3. 第二步:再执行事件delay精简处理(单行事件才能正确识别字段)
if ENABLE_DELAY_PROCESS:
lines = current_content.splitlines(keepends=True)
processed_lines = process_delay_events(lines)
current_content = ''.join(processed_lines)
# 4. 按功能组合生成对应后缀的文件名
dir_name = os.path.dirname(file_path)
base_name = os.path.basename(file_path)
name, ext = os.path.splitext(base_name)
if ENABLE_FORMAT_PROCESS and ENABLE_DELAY_PROCESS:
suffix = '_FormatDelay'
elif ENABLE_FORMAT_PROCESS:
suffix = 'Format'
elif ENABLE_DELAY_PROCESS:
suffix = '_Delay'
else:
suffix = '_NoProcess'
new_file_path = os.path.join(dir_name, f"{name}{suffix}{ext}")
# 5. 写入新文件,不修改原文件
with open(new_file_path, 'w', encoding='utf-8') as f:
f.write(current_content)
return new_file_path
def main():
# 初始化可视化文件选择窗口
root = tk.Tk()
root.withdraw()
# 弹出多选文件对话框
selected_files = filedialog.askopenfilenames(
title="选择要处理的JSON5文件",
filetypes=[("JSON5文件", "*.json5"), ("所有文件", "*.*")]
)
if not selected_files:
print("未选择任何文件,程序退出")
return
# 批量处理统计
success_count = 0
fail_count = 0
total_count = len(selected_files)
for file_path in selected_files:
try:
output_path = process_single_file(file_path)
print(f"处理成功:{output_path}")
success_count += 1
except Exception as e:
print(f"处理失败:{file_path} → 错误原因:{str(e)}")
fail_count += 1
# 输出最终统计
print(f"\n{'='*50}")
print(f"处理完成:共选中 {total_count} 个文件")
print(f"成功:{success_count} 个 | 失败:{fail_count} 个")
print(f"{'='*50}")
if __name__ == "__main__":
main()


浙公网安备 33010602011771号