自动化ai提效工具 Trae-ide-自动点击继续
Trae-IDE-continue-autorun Trea自动点击继续,基于Python的自动化工具,通过图像识别技术实现应用程序按钮的自动点击功能。该工具使用pyautogui进行截图和鼠标操作,结合OpenCV进行图像模板匹配,当检测到目标按钮出现时自动执行点击操作。系统支持两种运行模式:命令行版本和带GUI的悬浮窗版本
·
AI-IDE-Auto-Run-main
Trae-IDE-continue-autorun Trea自动点击继续
自动化ai提效工具
用python实现图像识别匹配(先截图一个应用程序里面的按钮图像,然后监听这个应用程序是否出现了这个图像,如果出现了这个图像,就触发鼠标自动点击操作去点击这个按钮)
一开始的想法是遍历窗口控件查询是否有继续按钮,然后点击 查找不到按钮 监听windows通知中心的Toast消息通知,很麻烦 最后还是使用图像识别 模板匹配 点击 后续可以接入消息通知,以及添加更多的模板实现其他操作 添加发送模板回传文字实现发送功能等
基于图像识别的自动化操作:先截取目标按钮的图像作为模板,然后持续监听指定应用程序窗口,一旦识别到模板图像出现,就自动用鼠标点击该位置 pyautogui:用于截图、图像识别和模拟鼠标点击 opencv-python (cv2):辅助图像匹配,提高识别精度 psutil:用于查找并定位目标应用程序窗口 pillow:图像处理辅助 模板截图、窗口监听、图像匹配和自动点击功能
安装所需依赖
pip install pyautogui opencv-python psutil pillow
核心新增功能:优先识别 jinxingzhong.png,匹配则输出提示且不执行任何操作;
代码优化:将截图、查找逻辑通用化,便于后续扩展其他模板识别;
执行逻辑:先判断 “进行中” 状态 → 再判断是否需要点击按钮,符合你 “出现 jinxingzhong 就只提示不操作” 的需求
cmd版本 前台窗口
后期优化 添加判断trae是不是在前台,如果不是就等待在前台才去匹配
import random
import pyautogui
import cv2
import numpy as np
import time
import os
# 配置参数
TEMPLATE_IMAGE_PATH = "target_button.png" # 目标按钮模板路径
PROCESSING_IMAGE_PATH = "jinxingzhong.png" # 进行中提示模板路径
CONFIDENCE_THRESHOLD = 0.7 # 匹配置信度 阈值
CHECK_INTERVAL = 1 # 检查间隔(秒)
SCREEN_WIDTH, SCREEN_HEIGHT = pyautogui.size() # 获取屏幕分辨率
def capture_template_compatible(template_path=TEMPLATE_IMAGE_PATH):
"""手动框选区域截图(兼容所有pyautogui版本,可指定保存路径)"""
print(f"=== 开始截取目标图像 [{os.path.basename(template_path)}] ===")
print("1. 将鼠标移动到目标区域的左上角位置,按 Enter 确认")
input("按下Enter继续...")
x1, y1 = pyautogui.position()
print(f"左上角坐标: ({x1}, {y1})")
print("\n2. 将鼠标移动到目标区域的右下角位置,按 Enter 确认")
input("按下Enter继续...")
x2, y2 = pyautogui.position()
print(f"右下角坐标: ({x2}, {y2})")
# 修正坐标顺序,确保有效
left = max(0, min(x1, x2))
top = max(0, min(y1, y2))
width = min(SCREEN_WIDTH - left, abs(x2 - x1))
height = min(SCREEN_HEIGHT - top, abs(y2 - y1))
template_region = (left, top, width, height)
# 截取并保存模板
template_screenshot = pyautogui.screenshot(region=template_region)
template_screenshot.save(template_path)
print(f"\n模板图像已保存至: {template_path}")
return template_region
def is_valid_coordinate(x, y):
"""校验坐标是否在屏幕范围内"""
return 0 <= x <= SCREEN_WIDTH and 0 <= y <= SCREEN_HEIGHT
def find_image_on_full_screen(template_path, confidence=0.7):
"""
全屏查找指定模板图像
返回:(中心坐标x, 中心坐标y) 或 None
"""
try:
# 读取模板
template = cv2.imread(template_path, cv2.IMREAD_COLOR)
if template is None:
print(f"❌ 无法读取模板图像: {template_path},请检查文件是否存在")
return None
# 截取全屏
screen = pyautogui.screenshot()
screen_np = np.array(screen)
screen_cv = cv2.cvtColor(screen_np, cv2.COLOR_RGB2BGR)
# 模板匹配
result = cv2.matchTemplate(screen_cv, template, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
# 计算中心坐标
h, w = template.shape[:2]
center_x = max_loc[0] + w // 2
center_y = max_loc[1] + h // 2
if max_val >= confidence:
# 校验坐标有效性
if is_valid_coordinate(center_x, center_y):
return (center_x, center_y, max_val) # 返回坐标+匹配度
else:
print(f"❌ 未找到按钮{os.path.basename(template_path)},最高匹配度: {max_val:.2f} (阈值: {CONFIDENCE_THRESHOLD} 坐标: ({center_x}, {center_y})")
# print(f"❌ 匹配到{os.path.basename(template_path)}的坐标无效: ({center_x}, {center_y})")
else:
print(
f"❌ 未找到按钮{os.path.basename(template_path)},最高匹配度: {max_val:.2f} (阈值: {CONFIDENCE_THRESHOLD} 坐标: ({center_x}, {center_y})")
# safe_click((center_x, center_y), False)
# time.sleep(10)
return None
except Exception as e:
print(f"❌ 查找{os.path.basename(template_path)}出错: {e}")
return None
def safe_click(position,flag=True):
"""安全点击(避免触发fail-safe)"""
if not position:
return False
x, y = position
try:
# 缓慢移动鼠标到目标位置
pyautogui.moveTo(x, y, duration=0.3)
# 执行点击
if(flag):
pyautogui.click()
print(f"✅ 成功点击按钮,位置: ({x}, {y})")
else:
print(f"⚠️ 模拟点击按钮,位置: ({x}, {y})")
return True
except pyautogui.FailSafeException:
print(f"❌ 鼠标移动到屏幕边缘,触发安全保护")
return False
except Exception as e:
print(f"❌ 点击失败: {e}")
return False
def main():
# 检查模板文件,不存在则引导截图
if not os.path.exists(TEMPLATE_IMAGE_PATH):
capture_template_compatible(TEMPLATE_IMAGE_PATH)
# 检查"进行中"模板文件,不存在则引导截图
if not os.path.exists(PROCESSING_IMAGE_PATH):
print(f"\n⚠️ 未找到{PROCESSING_IMAGE_PATH},请截取'进行中'提示的图像")
capture_template_compatible(PROCESSING_IMAGE_PATH)
print(f"\n=== 开始全屏监控 ===")
print(f"屏幕分辨率: {SCREEN_WIDTH}x{SCREEN_HEIGHT}")
print(f"检查间隔: {CHECK_INTERVAL}秒 | 匹配置信度: {CONFIDENCE_THRESHOLD}")
print("监控目标:1. target_button.png(匹配则点击) 2. jinxingzhong.png(匹配则提示)")
print("按 Ctrl+C 停止监控...\n")
try:
while True:
# 1. 先检查是否匹配"进行中"图像
processing_result = find_image_on_full_screen(PROCESSING_IMAGE_PATH, CONFIDENCE_THRESHOLD)
if processing_result:
px, py, p_val = processing_result
print(f"ℹ️ 正常进行中{random.randint(0,1)},匹配度: {p_val:.2f}, 位置: ({px}, {py})")
time.sleep(10)
else:
# 2. 未匹配到"进行中",再检查目标按钮
button_result = find_image_on_full_screen(TEMPLATE_IMAGE_PATH, CONFIDENCE_THRESHOLD)
if button_result:
bx, by, b_val = button_result
print(f"✅ 找到目标按钮,匹配度: {b_val:.2f}, 坐标: ({bx}, {by})")
safe_click((bx, by))
else:
# 可选:关闭此提示避免刷屏
print(f"❌ 未识别到目标按钮或进行中提示,继续监控...")
# 等待后继续检查
time.sleep(CHECK_INTERVAL)
except KeyboardInterrupt:
print("\n✅ 监控已手动停止")
except Exception as e:
print(f"\n❌ 程序出错: {e}")
if __name__ == "__main__":
# 轻微降低鼠标操作速度,减少触发安全保护的概率
pyautogui.PAUSE = 0.1
main()
窗口版本
import random
import pyautogui
import cv2
import numpy as np
import time
import os
import tkinter as tk
from tkinter import ttk
import threading
# 配置参数
TEMPLATE_IMAGE_PATH = "target_button.png" # 目标按钮模板路径
PROCESSING_IMAGE_PATH = "jinxingzhong.png" # 进行中提示模板路径
CONFIDENCE_THRESHOLD = 0.7 # 匹配置信度 阈值
CHECK_INTERVAL = 1 # 检查间隔(秒)
SCREEN_WIDTH, SCREEN_HEIGHT = pyautogui.size() # 获取屏幕分辨率
# 悬浮窗配置
WINDOW_WIDTH = 400
WINDOW_HEIGHT = 300
WINDOW_ALPHA = 0.8 # 窗口透明度 (0-1)
WINDOW_POS_X = SCREEN_WIDTH - WINDOW_WIDTH - 20 # 初始位置:屏幕右侧
WINDOW_POS_Y = 50 # 初始位置:屏幕上方
class FloatingMonitorWindow:
def __init__(self):
self.root = tk.Tk()
self.root.title("图像监控助手")
self.root.geometry(f"{WINDOW_WIDTH}x{WINDOW_HEIGHT}+{WINDOW_POS_X}+{WINDOW_POS_Y}")
self.root.attributes('-topmost', True) # 始终置顶
self.root.attributes('-alpha', WINDOW_ALPHA) # 设置透明度
self.root.resizable(False, False) # 禁止调整大小
# 允许窗口拖动
self.is_dragging = False
self.drag_start_x = 0
self.drag_start_y = 0
self.root.bind('<Button-1>', self.start_drag)
self.root.bind('<B1-Motion>', self.do_drag)
self.root.bind('<ButtonRelease-1>', self.stop_drag)
# 创建UI组件
self._create_ui()
# 保存日志的列表
self.logs = []
self.max_log_lines = 20 # 最大显示日志行数
def _create_ui(self):
# 标题栏
title_frame = ttk.Frame(self.root)
title_frame.pack(fill=tk.X, padx=5, pady=5)
ttk.Label(title_frame, text="图像监控状态", font=("Arial", 12, "bold")).pack(side=tk.LEFT)
# 控制按钮
ttk.Button(title_frame, text="清空日志", command=self.clear_logs).pack(side=tk.RIGHT, padx=2)
ttk.Button(title_frame, text="退出", command=self.exit_app).pack(side=tk.RIGHT, padx=2)
# 状态信息区域
status_frame = ttk.Frame(self.root)
status_frame.pack(fill=tk.X, padx=5, pady=5)
# 关键状态显示
self.status_label = ttk.Label(status_frame, text="状态: 初始化中...", font=("Arial", 10))
self.status_label.pack(anchor=tk.W)
self.match_info_label = ttk.Label(status_frame, text="匹配信息: 无", font=("Arial", 10))
self.match_info_label.pack(anchor=tk.W)
# 日志区域
log_frame = ttk.Frame(self.root)
log_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
ttk.Label(log_frame, text="运行日志:", font=("Arial", 10, "bold")).pack(anchor=tk.W)
# 滚动日志框
self.log_text = tk.Text(log_frame, height=10, width=50, font=("Consolas", 9))
scrollbar = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.log_text.yview)
self.log_text.configure(yscrollcommand=scrollbar.set)
self.log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 设置文本框只读
self.log_text.config(state=tk.DISABLED)
def start_drag(self, event):
"""开始拖动窗口"""
self.is_dragging = True
self.drag_start_x = event.x
self.drag_start_y = event.y
def do_drag(self, event):
"""执行拖动"""
if self.is_dragging:
x = self.root.winfo_x() + event.x - self.drag_start_x
y = self.root.winfo_y() + event.y - self.drag_start_y
self.root.geometry(f"+{x}+{y}")
def stop_drag(self, event):
"""停止拖动"""
self.is_dragging = False
def add_log(self, message):
"""添加日志信息到窗口"""
# 格式化时间
timestamp = time.strftime("[%H:%M:%S]")
log_msg = f"{timestamp} {message}"
# 添加到日志列表并控制长度
self.logs.append(log_msg)
if len(self.logs) > self.max_log_lines:
self.logs.pop(0)
# 更新文本框
self.log_text.config(state=tk.NORMAL)
self.log_text.delete(1.0, tk.END)
self.log_text.insert(tk.END, "\n".join(self.logs))
self.log_text.see(tk.END) # 滚动到最后一行
self.log_text.config(state=tk.DISABLED)
# 立即更新UI
self.root.update_idletasks()
def update_status(self, status):
"""更新状态标签"""
self.status_label.config(text=f"状态: {status}")
self.root.update_idletasks()
def update_match_info(self, info):
"""更新匹配信息标签"""
self.match_info_label.config(text=f"匹配信息: {info}")
self.root.update_idletasks()
def clear_logs(self):
"""清空日志"""
self.logs = []
self.log_text.config(state=tk.NORMAL)
self.log_text.delete(1.0, tk.END)
self.log_text.config(state=tk.DISABLED)
def exit_app(self):
"""退出应用"""
self.root.quit()
self.root.destroy()
def run(self):
"""运行窗口主循环"""
self.root.mainloop()
def capture_template_compatible(template_path=TEMPLATE_IMAGE_PATH, window=None):
"""手动框选区域截图(兼容所有pyautogui版本,可指定保存路径)"""
log_msg = f"=== 开始截取目标图像 [{os.path.basename(template_path)}] ==="
if window:
window.add_log(log_msg)
else:
print(log_msg)
prompt1 = "1. 将鼠标移动到目标区域的左上角位置,按 Enter 确认"
if window:
window.add_log(prompt1)
else:
print(prompt1)
input("按下Enter继续...")
x1, y1 = pyautogui.position()
pos1_msg = f"左上角坐标: ({x1}, {y1})"
if window:
window.add_log(pos1_msg)
else:
print(pos1_msg)
prompt2 = "\n2. 将鼠标移动到目标区域的右下角位置,按 Enter 确认"
if window:
window.add_log(prompt2)
else:
print(prompt2)
input("按下Enter继续...")
x2, y2 = pyautogui.position()
pos2_msg = f"右下角坐标: ({x2}, {y2})"
if window:
window.add_log(pos2_msg)
else:
print(pos2_msg)
# 修正坐标顺序,确保有效
left = max(0, min(x1, x2))
top = max(0, min(y1, y2))
width = min(SCREEN_WIDTH - left, abs(x2 - x1))
height = min(SCREEN_HEIGHT - top, abs(y2 - y1))
template_region = (left, top, width, height)
# 截取并保存模板
template_screenshot = pyautogui.screenshot(region=template_region)
template_screenshot.save(template_path)
save_msg = f"\n模板图像已保存至: {template_path}"
if window:
window.add_log(save_msg)
else:
print(save_msg)
return template_region
def is_valid_coordinate(x, y):
"""校验坐标是否在屏幕范围内"""
return 0 <= x <= SCREEN_WIDTH and 0 <= y <= SCREEN_HEIGHT
def find_image_on_full_screen(template_path, confidence=0.7, window=None):
"""
全屏查找指定模板图像
返回:(中心坐标x, 中心坐标y, 匹配度) 或 None
"""
try:
# 读取模板
template = cv2.imread(template_path, cv2.IMREAD_COLOR)
if template is None:
error_msg = f"❌ 无法读取模板图像: {template_path},请检查文件是否存在"
if window:
window.add_log(error_msg)
else:
print(error_msg)
return None
# 截取全屏
screen = pyautogui.screenshot()
screen_np = np.array(screen)
screen_cv = cv2.cvtColor(screen_np, cv2.COLOR_RGB2BGR)
# 模板匹配
result = cv2.matchTemplate(screen_cv, template, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
# 计算中心坐标
h, w = template.shape[:2]
center_x = max_loc[0] + w // 2
center_y = max_loc[1] + h // 2
if max_val >= confidence:
# 校验坐标有效性
if is_valid_coordinate(center_x, center_y):
match_msg = f"🔍 匹配到{os.path.basename(template_path)},匹配度: {max_val:.2f}, 坐标: ({center_x}, {center_y})"
if window:
window.add_log(match_msg)
window.update_match_info(
f"{os.path.basename(template_path)} | 匹配度: {max_val:.2f} | 坐标: ({center_x}, {center_y})")
else:
print(match_msg)
return (center_x, center_y, max_val) # 返回坐标+匹配度
else:
error_msg = f"❌ 匹配到{os.path.basename(template_path)}的坐标无效: ({center_x}, {center_y})"
if window:
window.add_log(error_msg)
else:
print(error_msg)
else:
error_msg = f"❌ 未找到{os.path.basename(template_path)},最高匹配度: {max_val:.2f} 坐标:({center_x},{center_y})"
if window:
window.add_log(error_msg)
window.update_match_info("无匹配目标")
else:
print(error_msg)
return None
except Exception as e:
error_msg = f"❌ 查找{os.path.basename(template_path)}出错: {e}"
if window:
window.add_log(error_msg)
else:
print(error_msg)
return None
def safe_click(position, flag=True, window=None):
"""安全点击(避免触发fail-safe)"""
if not position:
return False
x, y = position
try:
# 缓慢移动鼠标到目标位置
pyautogui.moveTo(x, y, duration=0.3)
# 执行点击
if flag:
pyautogui.click()
success_msg = f"✅ 成功点击按钮,位置: ({x}, {y})"
if window:
window.add_log(success_msg)
else:
print(success_msg)
else:
info_msg = f"⚠️ 模拟点击按钮,位置: ({x}, {y})"
if window:
window.add_log(info_msg)
else:
print(info_msg)
return True
except pyautogui.FailSafeException:
error_msg = f"❌ 鼠标移动到屏幕边缘,触发安全保护"
if window:
window.add_log(error_msg)
else:
print(error_msg)
return False
except Exception as e:
error_msg = f"❌ 点击失败: {e}"
if window:
window.add_log(error_msg)
else:
print(error_msg)
return False
def monitor_task(window):
"""监控任务(在独立线程中运行)"""
# 检查模板文件,不存在则引导截图
if not os.path.exists(TEMPLATE_IMAGE_PATH):
capture_template_compatible(TEMPLATE_IMAGE_PATH, window)
# 检查"进行中"模板文件,不存在则引导截图
if not os.path.exists(PROCESSING_IMAGE_PATH):
info_msg = f"\n⚠️ 未找到{PROCESSING_IMAGE_PATH},请截取'进行中'提示的图像"
window.add_log(info_msg)
capture_template_compatible(PROCESSING_IMAGE_PATH, window)
init_msg = f"=== 开始全屏监控 ==="
window.add_log(init_msg)
window.add_log(f"屏幕分辨率: {SCREEN_WIDTH}x{SCREEN_HEIGHT}")
window.add_log(f"检查间隔: {CHECK_INTERVAL}秒 | 匹配置信度: {CONFIDENCE_THRESHOLD}")
window.add_log("监控目标:1. target_button.png(匹配则点击) 2. jinxingzhong.png(匹配则提示)")
window.update_status("监控中...")
try:
while True:
# 检查窗口是否还在运行
if not window.root.winfo_exists():
break
# 1. 先检查是否匹配"进行中"图像
processing_result = find_image_on_full_screen(PROCESSING_IMAGE_PATH, CONFIDENCE_THRESHOLD, window)
if processing_result:
px, py, p_val = processing_result
info_msg = f"ℹ️ 正常进行中{random.randint(0, 1)},匹配度: {p_val:.2f}, 位置: ({px}, {py})"
window.add_log(info_msg)
window.update_status("进行中...")
time.sleep(10)
else:
# 2. 未匹配到"进行中",再检查目标按钮
button_result = find_image_on_full_screen(TEMPLATE_IMAGE_PATH, CONFIDENCE_THRESHOLD, window)
if button_result:
bx, by, b_val = button_result
window.update_status("找到目标按钮,点击中...")
safe_click((bx, by), True, window)
else:
# info_msg = f"❌ 未识别到目标按钮或进行中提示,继续监控..."
# window.add_log(info_msg)
window.update_status("监控中(无匹配)")
# 等待后继续检查
time.sleep(CHECK_INTERVAL)
except Exception as e:
error_msg = f"\n❌ 监控任务出错: {e}"
window.add_log(error_msg)
window.update_status(f"出错: {e}")
def main():
# 创建悬浮窗口
floating_window = FloatingMonitorWindow()
# 轻微降低鼠标操作速度,减少触发安全保护的概率
pyautogui.PAUSE = 0.1
# 在新线程中运行监控任务,避免阻塞UI
monitor_thread = threading.Thread(target=monitor_task, args=(floating_window,), daemon=True)
monitor_thread.start()
# 运行窗口主循环
try:
floating_window.run()
except KeyboardInterrupt:
floating_window.add_log("\n✅ 监控已手动停止")
finally:
floating_window.exit_app()
if __name__ == "__main__":
main()
添加exe判断的话 会被弹窗弹走
end
更多推荐

所有评论(0)