[Python] 网页自动化翻译扩展工具-附带源码

2025年2月13日 27点热度 0人点赞
import os
import pytesseract
from PIL import ImageGrab
import tkinter as tk
import time
import threading
import cv2
import numpy as np
import requests
import json

# 动态检测Tesseract路径
import os  # 确保os模块在最外层导入
try:
    # 优化后的路径检测逻辑
    import winreg

    # 1. 先尝试系统PATH环境变量
    try:
        pytesseract.pytesseract.tesseract_cmd = 'tesseract'
        # 添加调试信息
        print(f"尝试PATH中的tesseract路径: {pytesseract.pytesseract.tesseract_cmd}")
        # 验证PATH是否有效
        if not os.path.exists(pytesseract.pytesseract.tesseract_cmd):
            raise FileNotFoundError(f"未找到文件: {pytesseract.pytesseract.tesseract_cmd}")
    except Exception:
        # 2. 检查默认安装路径
        default_paths = [
            r"C:\Program Files\Tesseract-OCR\tesseract.exe",
            r"C:\Program Files (x86)\Tesseract-OCR\tesseract.exe",
            r"D:\Tesseract-OCR\tesseract.exe",  # 常见第三方安装路径
            r"C:\Users\{}\AppData\Local\Tesseract-OCR\tesseract.exe".format(os.getenv('USERNAME')),
            os.path.expanduser(r"~\AppData\Local\Programs\Tesseract-OCR\tesseract.exe"),
            r"C:\Users\Public\Tesseract-OCR\tesseract.exe",  # 公共用户目录
            r"C:\Tesseract-OCR\tesseract.exe",  # 根目录安装
            os.path.expandvars(r"%LOCALAPPDATA%\Tesseract-OCR\tesseract.exe"),  # 环境变量路径
            r"C:\Program Files\WindowsApps\*Tesseract*"  # Windows应用商店安装路径
        ]

        found = False
        # 修复缩进并优化路径检测
        for path in default_paths:
            # 使用os.path.expandvars处理环境变量
            expanded_path = os.path.expandvars(os.path.expanduser(path))
            if os.path.exists(expanded_path):
                pytesseract.pytesseract.tesseract_cmd = expanded_path
                found = True
                break

        if not found:
            # 3. 合并所有可能路径并进行统一检测
            all_paths = list({
                r"C:\Program Files\Tesseract-OCR\tesseract.exe",
                r"C:\Program Files (x86)\Tesseract-OCR\tesseract.exe",
                r"C:\Users\{}\AppData\Local\Tesseract-OCR\tesseract.exe".format(os.getenv('USERNAME')),
                os.path.expanduser(r"~\AppData\Local\Programs\Tesseract-OCR\tesseract.exe"),
                r"D:\Tesseract-OCR\tesseract.exe",
                r"C:\Users\Public\Tesseract-OCR\tesseract.exe",
                r"C:\Program Files\WindowsApps\*Tesseract*",
                os.path.expandvars(r"%LOCALAPPDATA%\Programs\Tesseract-OCR\tesseract.exe")
            })

            print("正在扫描所有已知安装路径...")
            for path in all_paths:
                try:
                    expanded_path = os.path.expandvars(os.path.expanduser(path))
                    # 处理通配符路径
                    if '*' in expanded_path:
                        import glob
                        matches = glob.glob(expanded_path)
                        if matches:
                            expanded_path = sorted(matches, reverse=True)[0]  # 取最新版本

                    if os.path.exists(expanded_path):
                        print(f"找到有效路径: {expanded_path}")
                        pytesseract.pytesseract.tesseract_cmd = expanded_path
                        found = True
                        break
                except Exception as e:
                    print(f"路径检测异常: {str(e)}")

            # 最终PATH环境变量检查
            if not found:
                print("正在系统PATH中搜索...")
                path_dirs = [os.path.expandvars(d) for d in os.getenv('PATH').split(';') if d.strip()]
                for dir_path in path_dirs:
                    test_path = os.path.join(dir_path, 'tesseract.exe')
                    print(f"检查PATH目录: {test_path}")
                    if os.path.isfile(test_path):
                        print(f"在系统PATH中找到: {test_path}")
                        pytesseract.pytesseract.tesseract_cmd = test_path
                        found = True
                        break

            # 最终验证
            if not found:
                print("错误: 所有检测方式均未找到Tesseract")
                raise RuntimeError(
        "Tesseract OCR安装问题解决方案:\n\n"
        "1. 安装Tesseract OCR:\n"
        "   - 方法一:使用winget快速安装\n"
        "     winget install -e --id UB-Mannheim.TesseractOCR\n\n"
        "   - 方法二:手动下载安装包\n"
        "     https://github.com/UB-Mannheim/tesseract/wiki\n\n"
        "2. 配置环境变量:\n"
        "   - 右键'此电脑' → 属性 → 高级系统设置 → 环境变量\n"
        "   - 在系统变量的Path中添加:\n"
        "     C:\\Program Files\\Tesseract-OCR\n\n"
        "3. 验证安装:\n"
        "   - 打开新的CMD窗口执行:\n"
        "     tesseract --version\n\n"
        "4. 注意事项:\n"
        "   - 安装时务必勾选'Add to PATH'选项\n"
        "   - 需要重启所有CMD/VSCode窗口使PATH生效\n"
        "   - 如果已安装,请检查杀毒软件是否误删文件\n"
        "   - 32位系统需安装32位版本"
    )
except Exception as e:
    raise RuntimeError(
        "Tesseract OCR安装问题解决方案:\n\n"
        "1. 安装Tesseract OCR:\n"
        "   - 方法一:使用winget快速安装\n"
        "     winget install -e --id UB-Mannheim.TesseractOCR\n\n"
        "   - 方法二:手动下载安装包\n"
        "     https://github.com/UB-Mannheim/tesseract/wiki\n\n"
        "2. 配置环境变量:\n"
        "   - 右键'此电脑' → 属性 → 高级系统设置 → 环境变量\n"
        "   - 在系统变量的Path中添加:\n"
        "     C:\\Program Files\\Tesseract-OCR\n\n"
        "3. 验证安装:\n"
        "   - 打开新的CMD窗口执行:\n"
        "     tesseract --version\n\n"
        "4. 注意事项:\n"
        "   - 安装时务必勾选'Add to PATH'选项\n"
        "   - 需要重启所有CMD/VSCode窗口使PATH生效\n"
        "   - 如果已安装,请检查杀毒软件是否误删文件\n"
        "   - 32位系统需安装32位版本"
    ) from e

class TranslationApp:
    def __init__(self):
        self.root = tk.Tk()
        self.root.overrideredirect(True)
        self.root.attributes('-topmost', True)
        self.root.attributes('-alpha', 0.9)

        # 创建主框架
        self.frame = tk.Frame(self.root, bg='#2C3E50')
        self.frame.pack(padx=5, pady=5)

        # 创建标签显示翻译结果
        self.label = tk.Label(self.frame, text="等待翻译...", 
                          font=('微软雅黑', 12), 
                          bg='#2C3E50', fg='#ECF0F1',
                          wraplength=300, justify='left',
                          padx=10, pady=5)
        self.label.pack()

        self.running = True
        self.update_interval = 2  # 截图间隔2秒
        self.last_text = ""  # 存储上一次识别的文本

        # 翻译API的请求头
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }

        self.setup_ui()
        self.start_capture()

    def translate_text(self, text):
        try:
            # 检测文本语言
            is_chinese = any('\u4e00' <= c <= '\u9fa5' for c in text)
            from_lang = 'zh' if is_chinese else 'en'
            to_lang = 'en' if is_chinese else 'zh'

            # 构建API URL
            url = f"https://fy.httpcn.com/bdaify/?s1={from_lang}&t1={to_lang}&q={text}"

            # 发送翻译请求
            response = requests.get(url, headers=self.headers, timeout=5)
            result = response.json()

            if 'result' in result and 'trans_result' in result['result']:
                return result['result']['trans_result'][0]['dst']
            else:
                print(f"翻译错误: {result}")
                return None
        except Exception as e:
            print(f"翻译过程出错: {str(e)}")
            return None

    def capture_and_translate(self):
        try:
            # 获取屏幕截图
            screenshot = ImageGrab.grab()

            # 转换为灰度图像并增强对比度
            img_np = np.array(screenshot)
            gray = cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY)
            enhanced = cv2.convertScaleAbs(gray, alpha=1.2, beta=0)

            # OCR识别文本
            text = pytesseract.image_to_string(enhanced, lang='eng')
            text = text.strip()

            # 如果识别到的文本与上次相同,则跳过
            if text and text != self.last_text:
                self.last_text = text
                # 翻译文本
                translation = self.translate_text(text)
                if translation:
                    self.update_display(f"原文: {text}\n译文: {translation}")
                else:
                    self.update_display("翻译失败,请检查网络连接")
        except Exception as e:
            self.update_display(f"错误: {str(e)}")

    def update_display(self, text):
        try:
            self.label.config(text=text)
            # 自动调整窗口大小
            self.root.update_idletasks()
            self.frame.update_idletasks()
            self.root.geometry('')
        except Exception as e:
            print(f"更新显示出错: {str(e)}")

    def start_capture(self):
        def capture_loop():
            while self.running:
                self.capture_and_translate()
                time.sleep(self.update_interval)

        thread = threading.Thread(target=capture_loop, daemon=True)
        thread.start()

    def setup_ui(self):
        # 添加控制按钮框架
        control_frame = tk.Frame(self.frame, bg='#2C3E50')
        control_frame.pack(fill='x', pady=(5,0))

        # 添加开始/暂停按钮
        self.toggle_btn = tk.Button(control_frame, text="暂停", 
                                  command=self.toggle_capture,
                                  bg='#3498DB', fg='white',
                                  relief='flat', width=6)
        self.toggle_btn.pack(side='left', padx=2)

        # 添加退出按钮
        exit_btn = tk.Button(control_frame, text="退出", 
                           command=self.exit_app,
                           bg='#E74C3C', fg='white',
                           relief='flat', width=6)
        exit_btn.pack(side='right', padx=2)

        # 绑定拖动事件
        self.label.bind('<Button-1>', self.start_move)
        self.label.bind('<B1-Motion>', self.on_move)

    def toggle_capture(self):
        self.running = not self.running
        btn_text = "暂停" if self.running else "开始"
        btn_color = "#3498DB" if self.running else "#2ECC71"
        self.toggle_btn.config(text=btn_text, bg=btn_color)

    def start_move(self, event):
        self._drag_start_x = event.x
        self._drag_start_y = event.y

    def on_move(self, event):
        self.target_x = self.root.winfo_x() - self._drag_start_x + event.x
        self.target_y = self.root.winfo_y() - self._drag_start_y + event.y

    def update_position(self):
        if hasattr(self, 'target_x'):
            current_x = self.root.winfo_x()
            current_y = self.root.winfo_y()
            dx = (self.target_x - current_x) * 0.3
            dy = (self.target_y - current_y) * 0.3
            self.root.geometry(f"+{int(current_x + dx)}+{int(current_y + dy)}")
        self.root.after(10, self.update_position)

    def exit_app(self):
        self.running = False
        self.root.destroy()

    def run(self):
        self.root.mainloop()

if __name__ == "__main__":
    app = TranslationApp()
    app.run()

这个API每天的免费配额很少,建议换别的API进行调试,初学者也不知道哪里有渠道获得更好的又免费的翻译API地址。

希望这个项目能够帮助到更多像我一样的编程初学者,让我们一起在学习编程的旅程中探索更多的可能性!如果你对这个项目感兴趣,欢迎提出建议或参与开发!

附上源码:
蓝奏:https://wwdd.lanzouw.com/iJqaA2nld2pc 密码:52pj

胖二十

这个人很懒,什么都没留下