在PyCharm中开发键鼠录制与循环重复的宏脚本需求
宏录制与回放脚本:问题修复与实现方案
原代码核心问题
- 未导入
pyautogui库,回放阶段会触发NameError - 仅轮询活动窗口的鼠标位置,未捕获鼠标点击、拖拽及键盘按键、组合键等关键操作
- 完全缺失键盘事件的录制与回放逻辑
- 轮询式录制生成大量重复鼠标位置数据,导致回放冗余、卡顿
- 热键停止逻辑依赖循环轮询,响应延迟且占用系统资源
修正后的完整代码
我们使用pynput实现事件驱动的精准录制,pyautogui处理回放动作,keyboard实现可靠的热键停止:
import time from pynput import mouse, keyboard import pyautogui # 全局变量:存储录制的事件,标记录制状态 recorded_events = [] is_recording = False def on_mouse_event(x, y, button, pressed): """监听鼠标事件:移动、点击、拖拽""" global recorded_events if not is_recording: return False # 停止监听 event_type = None event_data = None if button is not None: # 处理点击/拖拽事件 action = "press" if pressed else "release" event_type = f"mouse_{action}" event_data = (x, y, str(button)) else: # 处理鼠标移动事件 event_type = "mouse_move" event_data = (x, y) recorded_events.append(("mouse", time.time(), event_type, event_data)) def on_keyboard_event(key, pressed): """监听键盘事件:按键按下/释放""" global recorded_events if not is_recording: return False # 停止监听 if pressed: try: # 普通字符按键 key_str = key.char except AttributeError: # 特殊按键(如Ctrl、Shift、Enter等) key_str = str(key).replace("Key.", "") recorded_events.append(("keyboard", time.time(), "press", key_str)) else: # 记录按键释放(用于处理组合键) try: key_str = key.char except AttributeError: key_str = str(key).replace("Key.", "") recorded_events.append(("keyboard", time.time(), "release", key_str)) def stop_recording(): """停止录制的回调函数:按下热键'9'触发""" global is_recording is_recording = False print("\n录制已停止") def main(): global is_recording, recorded_events # 注册停止录制的热键 keyboard.add_hotkey('9', stop_recording) # 开始录制 print("开始录制,按下热键'9'停止...") is_recording = True recorded_events.clear() # 启动鼠标和键盘监听线程 mouse_listener = mouse.Listener(on_move=on_mouse_event, on_click=on_mouse_event, on_scroll=lambda x,y,dx,dy: None) keyboard_listener = keyboard.Listener(on_press=lambda key: on_keyboard_event(key, True), on_release=lambda key: on_keyboard_event(key, False)) mouse_listener.start() keyboard_listener.start() # 等待录制停止 while is_recording: time.sleep(0.1) # 停止监听线程 mouse_listener.stop() keyboard_listener.stop() keyboard.remove_hotkey('9') # 获取重复次数 try: repetitions = int(input("输入重复次数:")) except ValueError: print("输入无效,默认重复1次") repetitions = 1 # 回放录制的事件 if repetitions > 0 and recorded_events: print(f"开始重复执行{repetitions}次...") for _ in range(repetitions): prev_timestamp = recorded_events[0][1] for event in recorded_events: event_type, timestamp, action, data = event # 保持原操作的时间间隔 time.sleep(timestamp - prev_timestamp) prev_timestamp = timestamp if event_type == "mouse": x, y = data[:2] pyautogui.moveTo(x, y) if action == "mouse_press": button = data[2] if button == "Button.left": pyautogui.mouseDown(button='left') elif button == "Button.right": pyautogui.mouseDown(button='right') elif button == "Button.middle": pyautogui.mouseDown(button='middle') elif action == "mouse_release": button = data[2] if button == "Button.left": pyautogui.mouseUp(button='left') elif button == "Button.right": pyautogui.mouseUp(button='right') elif button == "Button.middle": pyautogui.mouseUp(button='middle') elif event_type == "keyboard": if action == "press": if len(data) == 1: # 普通字符直接输入 pyautogui.press(data) else: # 特殊按键(如enter、ctrl等) pyautogui.press(data) print("执行完成") else: print("无录制事件或重复次数无效") if __name__ == '__main__': main()
代码说明
- 依赖安装:先执行以下命令安装所需库
pip install pynput pyautogui keyboard - 事件录制:
- 鼠标监听:捕获移动、左键/右键/中键的按下/释放,记录坐标、按键类型及时序
- 键盘监听:捕获普通字符与特殊按键的按下/释放,支持组合键录制
- 热键停止:按下
9键立即终止录制,响应及时
- 事件回放:
- 严格按照录制时的时间间隔执行操作,还原原操作节奏
- 鼠标操作:移动到对应坐标,执行按下/释放动作(支持拖拽)
- 键盘操作:模拟按键按下/释放,支持普通字符与特殊按键
注意事项
- 运行脚本时需授予系统控制输入设备的权限(如Windows的管理员权限、Mac的辅助功能权限)
- 避免在录制时使用
9键以外的热键冲突,可自行修改stop_recording中的热键 - 拖拽操作会自动记录为"按下→移动→释放"的连续事件,回放时会完整还原
内容的提问来源于stack exchange,提问作者Matthew Darling
相关产品推荐
相关产品推荐

