吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2846|回复: 9
收起左侧

[Python 原创] 抖音自动清屏2.0,根据本人之前发布的抖音自动清屏修改

  [复制链接]
离愁 发表于 2025-11-1 13:40
本帖最后由 离愁 于 2025-11-1 14:37 编辑

之前的帖子抖音自动清屏,基于二改作者bbsky3099A的图像识别点击 [图像识别自动点击按键... https://www.52pojie.cn/thread-2069209-1-1.html (出处: 吾爱破解论坛)[/url]
更新了2.0,新增了以下设置,ps个人感觉完美了
1,以往ctrl+q键不能进行启动,现在改为了f1键可以缩为最小化进行启动与关闭
2,新增鼠标光标的隐藏位置可以自己填写屏幕坐标代码


下载地址.txt (39 Bytes, 下载次数: 39)
QQ_1761974812803.png
[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import filedialog, simpledialog, ttk, messagebox
from PIL import Image, ImageGrab
import cv2
import numpy as np
import pyautogui
import time
import random
import threading
import keyboard
import os
import json

class ImageRecognitionApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图像识别与点击")
        self.image_list = []  # 存储 (图像路径, 等待时间)
        self.default_wait_time = 100  # 默认等待时间 100 毫秒
        self.threshold = 0.9  # 默认匹配度阈值
        self.screenshot_area = None
        self.rect = None
        self.start_x = None
        self.start_y = None
        self.canvas = None
        self.running = False
        self.thread = None
        self.stop_requested = False
        self.custom_hotkey = None
        self.registered_hotkey = None
        screen_width, screen_height = pyautogui.size()
        self.hide_position = (screen_width - 10, screen_height - 10)  # 默认隐藏鼠标位置
        self.last_folder = os.path.expanduser("~")  # 默认文件夹
        self.data_file = "images.json"  # 保存数据文件
        self.init_ui()
        self.root.minsize(600, 400)
        self.set_default_hotkey()
        self.load_images()  # 加载上次保存的图片
        self.root.protocol("WM_DELETE_WINDOW", self.on_close)  # 安全关闭

    # =================== 数据保存与加载 ===================
    def load_images(self):
        if os.path.exists(self.data_file):
            try:
                with open(self.data_file, "r", encoding="utf-8") as f:
                    data = json.load(f)
                    self.image_list = data.get("image_list", [])
                    self.last_folder = data.get("last_folder", self.last_folder)
                    self.threshold = data.get("threshold", 0.9)
                    self.threshold_slider.set(self.threshold)
                    self.current_threshold_label.config(text=f"当前值: {self.threshold:.2f}")
                    # 加载隐藏鼠标位置
                    self.hide_position = tuple(data.get("hide_position", self.hide_position))
                    self.hide_pos_entry.delete(0, tk.END)
                    self.hide_pos_entry.insert(0, f"{self.hide_position[0]},{self.hide_position[1]}")
                self.update_image_listbox()
                self.safe_set_status(f"已加载 {len(self.image_list)} 张图片")
            except Exception as e:
                self.safe_set_status(f"加载图片列表失败: {e}")

    def save_images(self):
        try:
            with open(self.data_file, "w", encoding="utf-8") as f:
                json.dump({
                    "image_list": self.image_list,
                    "last_folder": self.last_folder,
                    "threshold": self.threshold,
                    "hide_position": self.hide_position
                }, f, ensure_ascii=False, indent=2)
        except Exception as e:
            self.safe_set_status(f"保存图片列表失败: {e}")

    # =================== 公共方法 ===================
    def safe_set_status(self, text):
        self.root.after(0, lambda: self.status_var.set(text))

    # 设置默认快捷键 F1
    def set_default_hotkey(self):
        self.custom_hotkey = 'f1'
        self.register_hotkey()
        self.hotkey_label.config(text=f"当前快捷键: {self.custom_hotkey}")

    # 注册全局热键
    def register_hotkey(self):
        if self.registered_hotkey:
            keyboard.remove_hotkey(self.registered_hotkey)
        try:
            self.registered_hotkey = keyboard.add_hotkey(self.custom_hotkey, self.toggle_script_by_hotkey)
            return True
        except Exception as e:
            messagebox.showerror("快捷键错误", f"无法注册快捷键 {self.custom_hotkey}: {e}")
            return False

    # 全局快捷键触发
    def toggle_script_by_hotkey(self):
        if self.running:
            self.stop_script()
        else:
            if not self.image_list:
                self.safe_set_status("请先添加至少一张图片")
                return
            self.start_script_thread()
            self.safe_set_status("脚本运行中... 使用快捷键停止")

    def on_close(self):
        self.save_images()
        if self.registered_hotkey:
            keyboard.remove_hotkey(self.registered_hotkey)
        self.root.destroy()

    # =================== UI 初始化 ===================
    def init_ui(self):
        main_frame = tk.Frame(self.root, padx=10, pady=10)
        main_frame.pack(fill=tk.BOTH, expand=True)

        button_frame = tk.LabelFrame(main_frame, text="操作面板", padx=10, pady=10)
        button_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))

        button_width = 15
        tk.Button(button_frame, text="上传图像", command=self.upload_image, width=button_width).pack(pady=5, fill=tk.X)
        tk.Button(button_frame, text="框选截图", command=self.prepare_capture_screenshot, width=button_width).pack(pady=5, fill=tk.X)
        tk.Button(button_frame, text="删除图片", command=self.delete_selected_image, width=button_width).pack(pady=5, fill=tk.X)
        tk.Button(button_frame, text="清空全部", command=self.clear_all_images, width=button_width).pack(pady=5, fill=tk.X)
        self.toggle_run_button = tk.Button(button_frame, text="开始运行", command=self.toggle_script, width=button_width)
        self.toggle_run_button.pack(pady=5, fill=tk.X)

        # 快捷键设置
        hotkey_frame = tk.LabelFrame(button_frame, text="快捷键设置", padx=10, pady=10)
        hotkey_frame.pack(pady=10, fill=tk.X)
        self.hotkey_label = tk.Label(hotkey_frame, text="当前快捷键: f1")
        self.hotkey_label.pack(pady=5)
        tk.Button(hotkey_frame, text="设置自定义快捷键", command=self.set_custom_hotkey, width=button_width).pack(pady=5, fill=tk.X)

        # 隐藏鼠标位置设置 - 使用输入框
        tk.Label(button_frame, text="鼠标点击后移动位置 (x,y):").pack(pady=(10,2))
        self.hide_pos_entry = tk.Entry(button_frame, width=20)
        self.hide_pos_entry.pack(pady=2)
        self.hide_pos_entry.insert(0, f"{self.hide_position[0]},{self.hide_position[1]}")
        tk.Button(button_frame, text="更新位置", command=self.update_hide_position_from_entry, width=button_width).pack(pady=5, fill=tk.X)

        # 阈值控制
        threshold_frame = tk.LabelFrame(button_frame, text="匹配度阈值", padx=10, pady=10)
        threshold_frame.pack(pady=10, fill=tk.X)
        self.current_threshold_label = tk.Label(threshold_frame, text=f"当前值: {self.threshold:.2f}", font=("Arial", 10, "bold"))
        self.current_threshold_label.pack(pady=(0, 5))
        self.threshold_slider = tk.Scale(threshold_frame, from_=0.5, to=1.0, resolution=0.01,
                                         orient=tk.HORIZONTAL, showvalue=False, length=180,
                                         command=self.update_threshold)
        self.threshold_slider.set(self.threshold)
        self.threshold_slider.pack(fill=tk.X)

        scale_labels = tk.Frame(threshold_frame)
        scale_labels.pack(fill=tk.X)
        tk.Label(scale_labels, text="0.5").pack(side=tk.LEFT)
        tk.Label(scale_labels, text="0.75").pack(side=tk.LEFT, padx=45)
        tk.Label(scale_labels, text="1.0").pack(side=tk.RIGHT)

        # 图像列表
        list_frame = tk.LabelFrame(main_frame, text="图像列表", padx=10, pady=10)
        list_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        self.tree = ttk.Treeview(list_frame, columns=("图片", "等待时间"), show='headings')
        self.tree.heading("图片", text="图片")
        self.tree.heading("等待时间", text="等待时间 (毫秒)")
        self.tree.column("图片", width=250)
        self.tree.column("等待时间", width=100)
        scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.tree.yview)
        self.tree.configure(yscroll=scrollbar.set)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.tree.bind('<Double-1>', self.edit_wait_time)

        # 状态栏
        self.status_var = tk.StringVar(value="就绪")
        status_bar = tk.Label(self.root, textvariable=self.status_var, bd=1, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)

    # =================== 功能区 ===================
    def set_custom_hotkey(self):
        hotkey = simpledialog.askstring("自定义快捷键", "请输入快捷键组合 (例如: ctrl+q 或 alt+s,需小写):", initialvalue=self.custom_hotkey)
        if hotkey:
            self.custom_hotkey = hotkey.strip()
            if self.register_hotkey():
                self.hotkey_label.config(text=f"当前快捷键: {self.custom_hotkey}")
                self.safe_set_status(f"已设置快捷键: {self.custom_hotkey}")

    def update_hide_position_from_entry(self):
        pos = self.hide_pos_entry.get().strip()
        try:
            x, y = map(int, pos.split(','))
            screen_width, screen_height = pyautogui.size()
            if 0 <= x < screen_width and 0 <= y < screen_height:
                self.hide_position = (x, y)
                self.hide_pos_entry.delete(0, tk.END)
                self.hide_pos_entry.insert(0, f"{x},{y}")  # 保持格式统一
                self.save_images()  # 保存到 json
                self.safe_set_status(f"鼠标点击后移动位置已更新为: {self.hide_position}")
            else:
                self.safe_set_status("坐标超出屏幕范围")
        except Exception as e:
            self.safe_set_status(f"输入格式错误,应为 x,y ({e})")

    def update_threshold(self, value):
        self.threshold = float(value)
        self.current_threshold_label.config(text=f"当前值: {self.threshold:.2f}")

    def upload_image(self):
        file_path = filedialog.askopenfilename(initialdir=self.last_folder, filetypes=[("Image files", "*.jpg *.png")])
        if file_path:
            self.image_list.append((file_path, self.default_wait_time))
            self.last_folder = os.path.dirname(file_path)
            self.update_image_listbox()
            self.safe_set_status(f"已上传图像: {file_path}")

    def prepare_capture_screenshot(self):
        os.makedirs("screenshots", exist_ok=True)
        self.last_folder = os.path.abspath("screenshots")
        self.root.withdraw()
        time.sleep(0.5)
        self.safe_set_status("请框选截图区域 (按ESC取消)")
        self.top = tk.Toplevel(self.root)
        self.top.attributes('-fullscreen', True)
        self.top.attributes('-alpha', 0.3)
        self.top.attributes('-topmost', True)
        self.top.bind("<Escape>", self.cancel_screenshot)
        self.canvas = tk.Canvas(self.top, cursor="cross", bg='grey')
        self.canvas.pack(fill=tk.BOTH, expand=True)
        self.canvas.bind("<ButtonPress-1>", self.on_button_press)
        self.canvas.bind("<B1-Motion>", self.on_mouse_drag)
        self.canvas.bind("<ButtonRelease-1>", self.on_button_release)

    def cancel_screenshot(self, event=None):
        if self.top:
            self.top.destroy()
        self.root.deiconify()
        self.safe_set_status("截图已取消")

    def on_button_press(self, event):
        self.start_x, self.start_y = event.x, event.y
        if self.rect:
            self.canvas.delete(self.rect)
        self.rect = self.canvas.create_rectangle(self.start_x, self.start_y, self.start_x, self.start_y, outline='red', width=2)

    def on_mouse_drag(self, event):
        self.canvas.coords(self.rect, self.start_x, self.start_y, event.x, event.y)

    def on_button_release(self, event):
        end_x, end_y = event.x, event.y
        bbox = (min(self.start_x, end_x), min(self.start_y, end_y),
                max(self.start_x, end_x), max(self.start_y, end_y))
        screenshot_path = os.path.join("screenshots", f"JT{random.randint(100000, 999999)}.png")
        ImageGrab.grab(bbox).save(screenshot_path)
        self.image_list.append((screenshot_path, self.default_wait_time))
        self.update_image_listbox()
        self.top.destroy()
        self.root.deiconify()
        self.safe_set_status(f"已保存截图: {screenshot_path}")

    def update_image_listbox(self):
        for row in self.tree.get_children():
            self.tree.delete(row)
        for img_path, wait_time in self.image_list:
            self.tree.insert("", tk.END, values=(img_path, wait_time))

    def clear_all_images(self):
        if messagebox.askyesno("确认", "确定清空所有图像?"):
            self.image_list.clear()
            self.update_image_listbox()
            self.safe_set_status("已清空所有图像")

    def edit_wait_time(self, event):
        selected_item = self.tree.selection()[0]
        idx = self.tree.index(selected_item)
        path, old_time = self.image_list[idx]
        new_time = simpledialog.askinteger("修改等待时间", "请输入新的等待时间(毫秒):", initialvalue=old_time)
        if new_time is not None:
            self.image_list[idx] = (path, new_time)
            self.update_image_listbox()
            self.safe_set_status(f"已更新等待时间: {new_time} 毫秒")

    def delete_selected_image(self):
        selected_item = self.tree.selection()
        if selected_item:
            idx = self.tree.index(selected_item[0])
            deleted = self.image_list.pop(idx)
            self.update_image_listbox()
            self.safe_set_status(f"已删除图像: {deleted[0]}")

    # =================== 运行与控制 ===================
    def toggle_script(self):
        if not self.running:
            if not self.image_list:
                messagebox.showwarning("警告", "请先添加至少一个图像")
                return
            self.start_script_thread()
            self.toggle_run_button.config(text="停止运行", state=tk.NORMAL)
            self.safe_set_status("脚本运行中... 使用快捷键停止")
        else:
            self.stop_script()
            self.toggle_run_button.config(text="开始运行", state=tk.NORMAL)

    def start_script_thread(self):
        if not self.running:
            self.running = True
            self.stop_requested = False
            self.thread = threading.Thread(target=self.run_script, daemon=True)
            self.thread.start()

    def run_script(self):
        while self.running and not self.stop_requested and self.image_list:
            for img_path, wait_time in self.image_list:
                if not self.running or self.stop_requested:
                    break
                self.safe_set_status(f"处理中: {img_path}...")
                self.match_and_click(img_path)
                sleep_interval, total_sleep = 0.1, wait_time / 1000.0
                slept = 0
                while slept < total_sleep and not self.stop_requested:
                    time.sleep(sleep_interval)
                    slept += sleep_interval
                if self.stop_requested:
                    break
        self.running = False
        self.root.after(0, self.script_finished)

    def script_finished(self):
        if self.stop_requested:
            self.safe_set_status("脚本已停止")
        else:
            self.safe_set_status("脚本运行完成")
        self.toggle_run_button.config(text="开始运行", state=tk.NORMAL)

    def stop_script(self):
        self.stop_requested = True
        self.running = False
        self.safe_set_status("正在停止脚本...")

    # =================== 图像匹配与点击 ===================
    def match_and_click(self, template_path):
        screenshot = pyautogui.screenshot()
        screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
        template = cv2.imread(template_path, 0)
        if template is None:
            self.safe_set_status(f"无法读取图像: {template_path}")
            return
        gray_screen = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)

        if template.shape[0] > gray_screen.shape[0] or template.shape[1] > gray_screen.shape[1]:
            self.safe_set_status(f"模板比屏幕大,无法匹配: {template_path}")
            return

        result = cv2.matchTemplate(gray_screen, template, cv2.TM_CCOEFF_NORMED)
        loc = np.where(result >= self.threshold)
        found = False
        for pt in zip(*loc[::-1]):
            click_x, click_y = pt[0] + template.shape[1] // 2, pt[1] + template.shape[0] // 2
            pyautogui.click(click_x, click_y)
            found = True
            break
        if not found:
            self.safe_set_status(f"未找到匹配区域: {template_path} (阈值: {self.threshold:.2f})")
        else:
            try:
                pyautogui.moveTo(*self.hide_position, duration=0.2)
            except Exception as e:
                self.safe_set_status(f"移动鼠标出错: {e}")

if __name__ == "__main__":
    root = tk.Tk()
    app = ImageRecognitionApp(root)
    root.mainloop()

免费评分

参与人数 1吾爱币 +7 热心值 +1 收起 理由
hrh123 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

禅味龟 发表于 2025-11-1 21:02
感谢分享
qq7226282 发表于 2025-11-3 09:46
zjy369 发表于 2025-11-5 20:15
Hxn 发表于 2025-11-16 22:48
好东西好东西
zhanghdong 发表于 2025-12-9 22:37
在主屏幕上好使,程序正常。但是在双屏幕的情况下,无法截取另外一个屏幕的图。

还有就是抖音在另外一个屏幕上,也不点击。

就是程序不支持多屏幕。
 楼主| 离愁 发表于 2025-12-10 14:45
zhanghdong 发表于 2025-12-9 22:37
在主屏幕上好使,程序正常。但是在双屏幕的情况下,无法截取另外一个屏幕的图。

还有就是抖音在另外一个 ...

因为我没用双屏幕所以就没写
weiming 发表于 2026-1-10 23:14
感谢分享
bjham 发表于 2026-4-15 22:59
不错,还好用。这下清爽了。
hxf3000 发表于 2026-6-2 10:15
感谢分享 收下试试
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-9-9 05:56

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表