用python实现一个脚本精灵
前言
最近重复工作比较多,想着写个自动化脚本来替我打工!废话不多说,上源码:
需要先安装第三方库:
#使用国内源提速
pip install pyautogui keyboard -i https://pypi.tuna.tsinghua.edu.cn/simple/
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import pyautogui
import time
import threading
import keyboard
from functools import partial
class Action:
def __init__(self, action_type, x=0, y=0, key=None, description=None):
self.action_type = action_type # "click", "key", "paste", "enter"
self.x = x
self.y = y
self.key = key
self.description = description or self.get_default_description()
def get_default_description(self):
if self.action_type == "click":
return f"点击位置 ({self.x}, {self.y})"
elif self.action_type == "key":
return f"按键 {self.key}"
elif self.action_type == "paste":
return "粘贴 (Ctrl+V)"
elif self.action_type == "enter":
return "按回车键"
return "未知操作"
def execute(self, delay):
if self.action_type == "click":
pyautogui.click(self.x, self.y)
elif self.action_type == "key":
pyautogui.press(self.key)
elif self.action_type == "paste":
pyautogui.hotkey('ctrl', 'v')
elif self.action_type == "enter":
pyautogui.press('enter')
time.sleep(delay)
class EnhancedAutoClickerApp:
def __init__(self, root):
self.root = root
self.root.title("自动化点击工具")
self.root.geometry("600x600")
# 存储动作列表
self.actions = []
# 设置循环次数和延迟时间
self.loop_count = tk.StringVar(value="10")
self.delay_time = tk.StringVar(value="0.5")
# 运行状态标志
self.is_running = False
self.is_listening = False
# 创建界面
self.create_widgets()
# 设置F2热键监听
keyboard.add_hotkey('f2', self.on_f2_pressed)
def create_widgets(self):
# 主框架
main_frame = ttk.Frame(self.root, padding="10")
main_frame.pack(fill=tk.BOTH, expand=True)
# 标题
title_label = ttk.Label(main_frame, text="增强版自动化点击工具", font=("Arial", 16, "bold"))
title_label.pack(pady=10)
# 设置框架
settings_frame = ttk.LabelFrame(main_frame, text="设置")
settings_frame.pack(fill=tk.X, padx=5, pady=5)
# 循环设置
loop_frame = ttk.Frame(settings_frame)
loop_frame.pack(fill=tk.X, padx=5, pady=5)
ttk.Label(loop_frame, text="循环次数:").pack(side=tk.LEFT, padx=5)
ttk.Entry(loop_frame, textvariable=self.loop_count, width=10).pack(side=tk.LEFT, padx=5)
ttk.Label(loop_frame, text="操作间隔(秒):").pack(side=tk.LEFT, padx=5)
ttk.Entry(loop_frame, textvariable=self.delay_time, width=10).pack(side=tk.LEFT, padx=5)
# 操作按钮框架
button_frame = ttk.Frame(main_frame)
button_frame.pack(fill=tk.X, padx=5, pady=5)
# 添加鼠标点击按钮
self.add_click_btn = ttk.Button(
button_frame,
text="添加鼠标点击 (F2)",
command=self.start_mouse_capture
)
self.add_click_btn.pack(side=tk.LEFT, padx=5)
# 添加其他操作按钮
ttk.Button(
button_frame,
text="添加粘贴操作",
command=lambda: self.add_action(Action("paste"))
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="添加回车键",
command=lambda: self.add_action(Action("enter"))
).pack(side=tk.LEFT, padx=5)
ttk.Button(
button_frame,
text="添加按键",
command=self.add_key_action
).pack(side=tk.LEFT, padx=5)
# 动作列表框架
actions_frame = ttk.LabelFrame(main_frame, text="动作列表 (可拖动排序)")
actions_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# 创建Treeview用于显示和排序动作
self.actions_tree = ttk.Treeview(
actions_frame,
columns=("序号", "动作"),
show="headings",
selectmode="browse"
)
self.actions_tree.heading("序号", text="序号")
self.actions_tree.heading("动作", text="动作")
self.actions_tree.column("序号", width=50, anchor=tk.CENTER)
self.actions_tree.column("动作", width=500, anchor=tk.W)
self.actions_tree.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# 绑定拖放事件
self.actions_tree.bind("<ButtonPress-1>", self.on_tree_press)
self.actions_tree.bind("<B1-Motion>", self.on_tree_motion)
self.actions_tree.bind("<ButtonRelease-1>", self.on_tree_release)
# 右键菜单
self.context_menu = tk.Menu(self.root, tearoff=0)
self.context_menu.add_command(label="编辑", command=self.edit_action)
self.context_menu.add_command(label="删除", command=self.delete_action)
self.actions_tree.bind("<Button-3>", self.show_context_menu)
# 控制按钮框架
control_frame = ttk.Frame(main_frame)
control_frame.pack(fill=tk.X, padx=5, pady=10)
self.start_btn = ttk.Button(
control_frame,
text="开始执行",
command=self.start_automation
)
self.start_btn.pack(side=tk.LEFT, padx=5)
self.stop_btn = ttk.Button(
control_frame,
text="停止执行",
command=self.stop_automation,
state="disabled"
)
self.stop_btn.pack(side=tk.LEFT, padx=5)
ttk.Button(
control_frame,
text="清空列表",
command=self.clear_actions
).pack(side=tk.LEFT, padx=5)
# 状态栏
self.status_var = tk.StringVar(value="就绪")
status_bar = ttk.Label(main_frame, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
status_bar.pack(fill=tk.X, padx=5, pady=5)
# 提示信息
ttk.Label(
main_frame,
text="提示: 按下F2可以捕获鼠标位置,按ESC键可以紧急停止执行",
foreground="gray"
).pack(pady=5)
# 设置拖放变量
self.drag_data = {"item": None, "x": 0, "y": 0}
def on_tree_press(self, event):
"""开始拖动项目"""
item = self.actions_tree.identify_row(event.y)
if item:
self.drag_data["item"] = item
self.drag_data["x"] = event.x
self.drag_data["y"] = event.y
def on_tree_motion(self, event):
"""拖动项目时显示移动线"""
if self.drag_data["item"]:
# 显示拖动线
self.actions_tree.selection_set(self.drag_data["item"])
def on_tree_release(self, event):
"""释放拖动项目,重新排序"""
if self.drag_data["item"]:
target_item = self.actions_tree.identify_row(event.y)
if target_item and target_item != self.drag_data["item"]:
# 获取源和目标的索引
source_idx = int(self.actions_tree.item(self.drag_data["item"], "values")[0]) - 1
target_idx = int(self.actions_tree.item(target_item, "values")[0]) - 1
# 移动动作
action = self.actions.pop(source_idx)
self.actions.insert(target_idx, action)
# 更新显示
self.update_actions_tree()
self.drag_data["item"] = None
def show_context_menu(self, event):
"""显示右键菜单"""
item = self.actions_tree.identify_row(event.y)
if item:
self.actions_tree.selection_set(item)
self.context_menu.post(event.x_root, event.y_root)
def edit_action(self):
"""编辑选中的动作"""
selection = self.actions_tree.selection()
if not selection:
return
item = selection[0]
idx = int(self.actions_tree.item(item, "values")[0]) - 1
action = self.actions[idx]
if action.action_type == "click":
# 编辑点击位置
result = simpledialog.askstring(
"编辑点击位置",
"输入新的坐标 (x,y):",
initialvalue=f"{action.x},{action.y}"
)
if result:
try:
x, y = map(int, result.split(","))
action.x = x
action.y = y
action.description = f"点击位置 ({x}, {y})"
self.update_actions_tree()
except:
messagebox.showerror("错误", "坐标格式无效,请使用 x,y 格式")
elif action.action_type == "key":
# 编辑按键
key = simpledialog.askstring(
"编辑按键",
"输入新的按键:",
initialvalue=action.key
)
if key:
action.key = key
action.description = f"按键 {key}"
self.update_actions_tree()
def delete_action(self):
"""删除选中的动作"""
selection = self.actions_tree.selection()
if not selection:
return
item = selection[0]
idx = int(self.actions_tree.item(item, "values")[0]) - 1
self.actions.pop(idx)
self.update_actions_tree()
def start_mouse_capture(self):
"""开始捕获鼠标位置"""
if not self.is_listening:
self.is_listening = True
self.add_click_btn.configure(text="正在捕获... (按F2记录位置)")
self.status_var.set("按F2记录当前鼠标位置")
def on_f2_pressed(self):
"""当按下F2时,捕获鼠标位置"""
if self.is_listening:
x, y = pyautogui.position()
self.add_action(Action("click", x, y))
self.status_var.set(f"已添加点击位置: ({x}, {y})")
def add_key_action(self):
"""添加按键动作"""
key = simpledialog.askstring("添加按键", "输入要按下的键:")
if key:
self.add_action(Action("key", key=key))
def add_action(self, action):
"""添加动作到列表"""
self.actions.append(action)
self.update_actions_tree()
# 如果是在捕获模式下,继续保持捕获状态
if not self.is_listening and action.action_type == "click":
self.add_click_btn.configure(text="添加鼠标点击 (F2)")
def update_actions_tree(self):
"""更新动作列表显示"""
# 清空树
for item in self.actions_tree.get_children():
self.actions_tree.delete(item)
# 添加动作
for i, action in enumerate(self.actions):
self.actions_tree.insert("", "end", values=(i + 1, action.description))
def start_automation(self):
"""开始执行自动化任务"""
if not self.actions:
messagebox.showwarning("警告", "请先添加动作")
return
try:
loops = int(self.loop_count.get())
delay = float(self.delay_time.get())
if loops <= 0 or delay < 0:
messagebox.showwarning("警告", "循环次数和延迟时间必须大于0")
return
# 停止捕获模式
self.is_listening = False
self.add_click_btn.configure(text="添加鼠标点击 (F2)")
# 开始执行
self.is_running = True
self.start_btn.configure(state="disabled")
self.stop_btn.configure(state="normal")
# 创建并启动执行线程
self.automation_thread = threading.Thread(
target=self.run_automation,
args=(loops, delay),
daemon=True
)
self.automation_thread.start()
except ValueError:
messagebox.showerror("错误", "请输入有效的循环次数和延迟时间")
def run_automation(self, loops, delay):
"""在线程中执行自动化任务"""
try:
self.status_var.set("准备执行,3秒后开始...")
time.sleep(3) # 给用户时间切换窗口
for loop in range(loops):
if not self.is_running:
break
self.status_var.set(f"执行中: 第 {loop + 1}/{loops} 次循环")
for i, action in enumerate(self.actions):
if not self.is_running:
break
self.root.after(0, lambda idx=i: self.highlight_action(idx))
action.execute(delay)
self.root.after(0, self.reset_ui)
self.status_var.set("执行完成")
except Exception as e:
self.root.after(0, lambda: messagebox.showerror("执行错误", str(e)))
self.root.after(0, self.reset_ui)
def highlight_action(self, index):
"""高亮显示当前执行的动作"""
for item in self.actions_tree.get_children():
idx = int(self.actions_tree.item(item, "values")[0]) - 1
if idx == index:
self.actions_tree.selection_set(item)
self.actions_tree.see(item)
break
def stop_automation(self):
"""停止执行"""
self.is_running = False
self.status_var.set("已停止执行")
self.reset_ui()
def reset_ui(self):
"""重置UI状态"""
self.is_running = False
self.start_btn.configure(state="normal")
self.stop_btn.configure(state="disabled")
def clear_actions(self):
"""清空动作列表"""
if messagebox.askyesno("确认", "确定要清空所有动作吗?"):
self.actions = []
self.update_actions_tree()
self.status_var.set("动作列表已清空")
def main():
root = tk.Tk()
app = EnhancedAutoClickerApp(root)
# 设置ESC键为紧急停止
keyboard.add_hotkey('esc', app.stop_automation)
root.mainloop()
if __name__ == "__main__":
main()
实现一个自动化点击工具,使用Python的tkinter构建GUI界面,结合pyautogui和keyboard库实现自动化操作。
核心功能概述
- 自动化操作执行:可以按设定的循环次数和时间间隔自动执行一系列预定义的操作
多种操作类型支持:
- 鼠标点击(记录坐标)
- 键盘按键
- 粘贴操作(Ctrl+V)
- 回车键操作
动作管理功能:
- 添加/编辑/删除动作
- 拖拽排序动作顺序
- 清空动作列表
- 实时捕获鼠标位置:通过F2热键记录当前鼠标位置
- 紧急停止机制:通过ESC键可随时中断执行
代码结构分析
1. Action类
这是一个表示自动化操作的基础类,具有以下特点:
class Action:
def __init__(self, action_type, x=0, y=0, key=None, description=None):
# 初始化操作类型和参数
- 操作类型:支持"click"、"key"、"paste"、"enter"四种类型
- 参数存储:存储坐标(x,y)、按键名称等
- 描述生成:自动生成操作的文字描述
- 执行方法:
execute()
方法根据操作类型调用pyautogui执行相应动作
2. EnhancedAutoClickerApp类
主应用类,实现了GUI界面和核心功能:
初始化和界面构建
def __init__(self, root):
# 初始化应用
# 设置F2热键监听
def create_widgets(self):
# 构建复杂的GUI界面元素
- 创建主窗口和各种控件
- 设置布局和事件绑定
- 初始化数据结构和状态变量
动作管理功能
def add_action(self, action):
# 添加动作到列表
def edit_action(self):
# 编辑选中的动作
def delete_action(self):
# 删除选中的动作
- 支持添加、编辑和删除动作
- 使用对话框收集用户输入
- 实时更新界面显示
拖放排序功能
def on_tree_press(self, event):
# 开始拖动
def on_tree_motion(self, event):
# 拖动过程
def on_tree_release(self, event):
# 完成拖动并重排序
- 实现了Treeview控件中的项目拖放
- 支持动作顺序的直观调整
- 拖放后自动更新数据和界面
鼠标位置捕获
def start_mouse_capture(self):
# 开始捕获鼠标位置
def on_f2_pressed(self):
# 当按下F2时,捕获鼠标位置
- 通过F2热键实时捕获鼠标坐标
- 自动添加为点击操作
自动化执行
def start_automation(self):
# 开始执行自动化任务
def run_automation(self, loops, delay):
# 在线程中执行自动化任务
- 使用单独线程执行操作,避免界面卡死
- 支持设定循环次数和操作间隔
- 执行过程中高亮显示当前操作
- 提供紧急停止机制
技术亮点
- 多线程设计:使用threading模块创建后台线程执行自动化任务,保持GUI响应性
- 热键集成:通过keyboard库实现全局热键(F2捕获位置,ESC紧急停止)
- 拖放排序:实现了自定义的拖放排序功能,增强用户体验
- 上下文菜单:右键菜单提供快捷操作
- 状态管理:清晰的状态变量和UI状态同步机制
- 异常处理:完善的错误处理和用户反馈
使用场景
这个工具适用于多种自动化场景:
- 重复性表单填写:自动点击表单字段并输入数据
- 游戏自动化:执行重复性游戏操作(如自动点击、自动钓鱼等)
- 软件测试:自动执行UI测试步骤
- 批量处理:自动执行多步骤的文件处理操作
- 数据录入:简化重复性数据录入工作
可能的改进点
- 配置保存/加载:添加保存和加载操作序列的功能
- 条件分支:增加条件判断和分支执行能力
- 图像识别:整合图像识别功能,基于屏幕内容执行操作
- 延时随机化:添加随机延时选项,使自动化操作更像人工操作
- 日志记录:添加详细的执行日志功能
这改进有空再做哈哈哈哈哈,
使用截图:
关注@运维躬行录,获取【按键精灵】。转发本文至三个技术群,可免费领取《python自动化办公教程》祝你效率翻倍