-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmouse_recorder.py
More file actions
208 lines (169 loc) · 5.66 KB
/
Copy pathmouse_recorder.py
File metadata and controls
208 lines (169 loc) · 5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
"""
鼠标录制与回放工具
- 按 F9 开始/停止录制
- 按 F10 回放录制的操作
- 按 F11 退出程序
"""
import json
import time
import threading
from pynput import mouse, keyboard
import pyautogui
pyautogui.FAILSAFE = True # 鼠标移到左上角(0,0)紧急停止
# 全局状态
actions = []
recording = False
replaying = False
record_start_time = 0
def on_move(x, y):
if recording:
actions.append({
"type": "move",
"x": x,
"y": y,
"time": time.time() - record_start_time
})
def on_click(x, y, button, pressed):
if recording:
actions.append({
"type": "click",
"x": x,
"y": y,
"button": str(button),
"pressed": pressed,
"time": time.time() - record_start_time
})
def on_scroll(x, y, dx, dy):
if recording:
actions.append({
"type": "scroll",
"x": x,
"y": y,
"dx": dx,
"dy": dy,
"time": time.time() - record_start_time
})
def start_recording():
global recording, record_start_time, actions
actions = []
recording = True
record_start_time = time.time()
print("[录制中] 操作鼠标进行录制,按 F9 停止...")
def stop_recording():
global recording
recording = False
print(f"[录制停止] 共记录 {len(actions)} 个事件")
# 保存到文件
with open("mouse_record.json", "w") as f:
json.dump(actions, f, indent=2)
print("[已保存] mouse_record.json")
# 打印简要信息
print_actions_summary()
def print_actions_summary():
"""打印录制的操作摘要"""
clicks = [a for a in actions if a["type"] == "click" and a["pressed"]]
drags = detect_drags(actions)
print("\n--- 操作摘要 ---")
print(f"点击次数: {len(clicks)}")
for i, c in enumerate(clicks):
print(f" 点击 {i+1}: ({c['x']}, {c['y']})")
if drags:
print(f"拖动次数: {len(drags)}")
for i, d in enumerate(drags):
print(f" 拖动 {i+1}: ({d['start_x']}, {d['start_y']}) -> "
f"({d['end_x']}, {d['end_y']}), 耗时 {d['duration']:.2f}s")
print("----------------\n")
def detect_drags(events):
"""从事件序列中检测拖动操作(按下 -> 移动 -> 松开)"""
drags = []
press_event = None
move_positions = []
for e in events:
if e["type"] == "click" and e["pressed"]:
press_event = e
move_positions = [(e["x"], e["y"])]
elif e["type"] == "move" and press_event:
move_positions.append((e["x"], e["y"]))
elif e["type"] == "click" and not e["pressed"] and press_event:
# 检测是否有明显位移(超过 10px 算拖动)
start = move_positions[0]
end = (e["x"], e["y"])
dist = ((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2) ** 0.5
if dist > 10:
drags.append({
"start_x": start[0],
"start_y": start[1],
"end_x": end[0],
"end_y": end[1],
"duration": e["time"] - press_event["time"]
})
press_event = None
move_positions = []
return drags
def replay_actions():
global replaying
if not actions:
print("[错误] 没有录制数据,请先录制")
return
replaying = True
print("[回放中] 3秒后开始,鼠标移到左上角(0,0)可紧急停止...")
time.sleep(3)
prev_time = 0
for i, act in enumerate(actions):
if not replaying:
print("[已中断回放]")
break
# 等待到事件应该发生的时间
wait = act["time"] - prev_time
if wait > 0:
time.sleep(wait)
prev_time = act["time"]
if act["type"] == "move":
pyautogui.moveTo(act["x"], act["y"], _pause=False)
elif act["type"] == "click":
if act["pressed"]:
pyautogui.mouseDown(act["x"], act["y"],
button=act["button"].split(".")[-1].lower(),
_pause=False)
else:
pyautogui.mouseUp(act["x"], act["y"],
button=act["button"].split(".")[-1].lower(),
_pause=False)
elif act["type"] == "scroll":
pyautogui.scroll(act["dy"], x=act["x"], y=act["y"], _pause=False)
replaying = False
print("[回放完成]")
def on_press(key):
global recording, replaying
try:
if key == keyboard.Key.f9:
if not recording:
start_recording()
else:
stop_recording()
elif key == keyboard.Key.f10:
if not replaying:
threading.Thread(target=replay_actions, daemon=True).start()
elif key == keyboard.Key.f11:
print("[退出]")
return False # 停止监听
except AttributeError:
pass
def main():
print("=" * 40)
print(" 鼠标录制回放工具")
print("=" * 40)
print(" F9 = 开始/停止录制")
print(" F10 = 回放录制的操作")
print(" F11 = 退出程序")
print(" 鼠标移到屏幕左上角(0,0) = 紧急停止")
print("=" * 40)
# 启动鼠标监听
mouse_listener = mouse.Listener(on_move=on_move, on_click=on_click, on_scroll=on_scroll)
mouse_listener.start()
# 启动键盘监听
with keyboard.Listener(on_press=on_press) as kb_listener:
kb_listener.join()
mouse_listener.stop()
if __name__ == "__main__":
main()