基于 Tkinter 的中英互译工具开发:360 翻译 API 爬取与应用

摘要

本文介绍如何使用 Python 开发一个集成自定义截图 OCR 识别360 翻译 API 爬取的中英互译工具。通过 Tkinter 构建 GUI 界面,Pillow 处理图像,pytesseract 实现文字识别,结合 requests 库爬取 360 翻译结果,实现双语互译功能。文章重点解析反爬策略、API 请求参数构造及界面交互逻辑,适合学习 Web 数据采集与桌面应用开发的初学者。

一 :实际实现样式

1.运行代码

        

2.代码进行翻译

3.翻译后会出现fanyi.txt 里面记录 翻译记录

二 环境安装

1.安装必须模块

# 安装依赖
pip install pillow pytesseract requests fake_useragent

2.实现截图翻译功能

.安装 ocr 

Home · UB-Mannheim/tesseract Wiki

三.代码展示与解释

一、环境配置与依赖导入

python

import tkinter as tk
from tkinter import messagebox, filedialog, ttk
from PIL import Image, ImageGrab, ImageTk  # 图像处理与截图
import pytesseract  # OCR引擎接口
import requests  # 网络请求(调用翻译API)
import time  # 时间处理
import tempfile  # 临时文件存储截图
from fake_useragent import FakeUserAgent  # 生成随机User-Agent(反爬)
import ctypes  # 设置DPI感知(解决高分辨率界面模糊)

# 解决高DPI屏幕缩放问题(Windows系统)
ctypes.windll.shcore.SetProcessDpiAwareness(1)

# 配置Tesseract路径(需根据实际安装路径修改)
# pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

  • 核心依赖
    • Tkinter:Python 内置 GUI 框架,用于创建窗口和组件
    • Pillow:图像处理库,支持截图、预览和保存
    • pytesseract:调用 Tesseract-OCR 引擎,需单独安装 OCR 程序
    • requests:发送 HTTP 请求获取翻译结果
    • fake_useragent:生成随机浏览器标识,绕过翻译网站反爬机制

二、全局变量与界面初始化

python

url = 'https://fanyi.so.com/index/search'  # 360翻译API地址
is_translating = False  # 防止重复翻译的标志

root = tk.Tk()
root.title("中英互译小工具")
root.geometry("480x400")
root.resizable(False, False)  # 禁止调整窗口大小

# 界面样式配置(ttk主题)
style = ttk.Style()
style.theme_use('clam')  # 使用现代风格主题
# 自定义按钮样式(蓝色主色调,扁平化设计)
style.configure("TButton", 
    padding=6, relief="flat", background="#4A90E2", foreground="white", 
    font=("Arial", 10, "bold")
)
style.map("TButton", 
    background=[('active', '#357ABD')]  # 鼠标悬停时变色
)

  • 界面特点
    • 固定窗口大小(480x400),适合桌面工具
    • 使用 ttk 组件(比原生 tkinter 更美观),配置蓝色主色调和扁平化按钮
    • is_translating 防止用户连续点击导致重复请求

三、翻译日志记录功能

def log_translation(text, result):
    """记录翻译内容到本地文本文件"""
    now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    current_dir = os.path.dirname(os.path.abspath(__file__))  # 获取当前脚本路径
    log_path = os.path.join(current_dir, "fanyi.txt")  # 日志文件路径
    
    with open(log_path, "a", encoding="utf-8") as f:
        # ljust(20) 使字段左对齐并填充至20字符宽度
        f.write(f"时间: {now_time.ljust(20)} 原文: {text.ljust(20)} 结果: {result.ljust(20)}\n")
        f.write("-" * 60 + "\n")  # 分隔线

  • 功能作用
    • 在当前脚本目录下创建 / 追加 fanyi.txt
    • 记录每次翻译的时间、原文和结果,方便追溯
    • 使用 UTF-8 编码避免中文乱码

四、核心翻译逻辑

python

def translate(text):
    """调用360翻译API进行文本翻译"""
    global is_translating
    if not text or is_translating:
        return  # 防止空文本或重复请求
    
    is_translating = True
    translate_btn.config(state=tk.DISABLED)  # 禁用按钮防止误操作
    output_var.set("正在翻译...")
    
    try:
        # 构造请求参数(eng=1为英→中,eng=0为中→英)
        data = {
            "eng": "1" if mode_var.get() == "en2zh" else "0",
            "query": text
        }
        # 生成随机User-Agent(反爬关键)
        headers = {"User-Agent": FakeUserAgent().random}
        response = requests.post(url, headers=headers, data=data, timeout=10)
        
        if response.status_code == 200:
            result = response.json()["data"]["fanyi"]
            output_var.set(result)
            log_translation(text, result)  # 记录翻译日志
        else:
            output_var.set(f"❌ 翻译失败:HTTP {response.status_code}")
            
    except Exception as e:
        output_var.set(f"❌ 错误:{str(e)}")
    finally:
        is_translating = False
        translate_btn.config(state=tk.NORMAL)  # 恢复按钮状态

  • 技术要点
    • 反爬措施:每次请求生成随机 User-Agent,模拟真实浏览器
    • 状态管理:通过 is_translating 防止并发请求,按钮禁用避免用户重复点击
    • 异常处理:捕获网络超时、API 错误等异常,给出友好提示

五、OCR 截图翻译功能

def custom_screenshot():
    """自定义区域截图并翻译"""
    # 创建全屏透明窗口用于截图
    top = tk.Toplevel()
    top.attributes("-fullscreen", True, "-alpha", 0.3)  # 30%透明度
    canvas = tk.Canvas(top, cursor="cross")
    canvas.pack(fill=tk.BOTH)
    
    start_x = start_y = 0
    
    # 鼠标按下:记录起点
    def on_mouse_down(event):
        nonlocal start_x, start_y
        start_x, start_y = event.x_root, event.y_root
    
    # 鼠标拖动:绘制红色选框
    def on_mouse_drag(event):
        canvas.create_rectangle(start_x, start_y, event.x_root, event.y_root, 
                              outline="red", width=2, tag="rect")
    
    # 鼠标释放:处理截图
    def on_mouse_up(event):
        x1, y1 = min(start_x, event.x_root), min(start_y, event.y_root)
        x2, y2 = max(start_x, event.x_root), max(start_y, event.y_root)
        top.destroy()
        
        # 截取指定区域并保存临时文件
        screenshot = ImageGrab.grab((x1, y1, x2, y2))
        with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmpfile:
            screenshot.save(tmpfile.name)
        
        # 显示预览窗口
        preview = tk.Toplevel()
        img = ImageTk.PhotoImage(screenshot.resize((400, 300)))
        tk.Label(preview, image=img).pack()
        preview.image = img  # 防止图片被GC回收
        
        # 异步执行OCR识别和翻译
        root.after(100, lambda: ocr_image(screenshot))

  • 流程解析
    1. 创建透明全屏窗口,允许用户拖动选择翻译区域
    2. 使用 ImageGrab.grab() 截取屏幕指定区域
    3. 生成临时图片文件并显示预览
    4. 调用 ocr_image() 进行文字识别和翻译

六、OCR 文字识别

def ocr_image(image):
    """对截图进行OCR识别并触发翻译"""
    try:
        # 调用Tesseract进行中英文混合识别
        text = pytesseract.image_to_string(image, lang="eng+chi_sim").strip()
        if not text:
            messagebox.showwarning("提示", "未识别到文字")
            return
        
        input_entry.delete(0, tk.END)
        input_entry.insert(0, text)  # 将识别结果填充到输入框
        root.after(2000, translate, text)  # 延迟2秒触发翻译(避免网络拥堵)
        
    except Exception as e:
        messagebox.showerror("错误", f"OCR失败:{str(e)}")

  • 关键参数
    • lang="eng+chi_sim":同时识别英文和简体中文
    • root.after(2000, ...):延迟执行翻译,确保 OCR 结果已填充到输入框

七、界面组件布局

# 翻译方向选择(RadioButton)
mode_var = tk.StringVar(value="en2zh")
ttk.Label(root, text="选择翻译方向:").pack(pady=5)
mode_frame = tk.Frame(root)
ttk.Radiobutton(mode_frame, text="英文 ➜ 中文", variable=mode_var, value="en2zh").pack(side=tk.LEFT)
ttk.Radiobutton(mode_frame, text="中文 ➜ 英文", variable=mode_var, value="zh2en").pack(side=tk.LEFT)

# 输入框
ttk.Label(root, text="请输入要翻译的内容:").pack(pady=5)
input_entry = ttk.Entry(root, font=("Arial", 12), width=40)
input_entry.pack()

# 功能按钮
translate_btn = ttk.Button(root, text="开始翻译", command=lambda: translate(input_entry.get().strip()))
screenshot_btn = ttk.Button(root, text="自定义截屏并翻译", command=custom_screenshot)
translate_btn.pack(pady=10)
screenshot_btn.pack(pady=10)

# 翻译结果显示
ttk.Label(root, text="翻译结果:").pack()
output_frame = ttk.Frame(root, borderwidth=2, relief="groove")
output_label = ttk.Label(output_frame, textvariable=output_var, 
                       wraplength=440, foreground="blue")
output_label.pack(padx=10, pady=10)
  • 布局特点
    • 使用 ttk 组件(如ttk.Entryttk.Button)提升界面美观度
    • wraplength=440 使翻译结果自动换行,适应窗口宽度
    • 按钮和输入框通过pack()布局,结构清晰
  1. 使用注意

    • 需手动配置 Tesseract-OCR 路径
    • 360 翻译 API 可能限制请求频率,建议添加请求间隔
    • 部分系统需安装依赖库(如 Windows 的 Visual C++ 运行时)

四.代码展示

import tkinter as tk
from tkinter import messagebox, filedialog, ttk
from PIL import Image, ImageGrab, ImageTk
import pytesseract
import requests
import time
import tempfile
from fake_useragent import FakeUserAgent
import ctypes
ctypes.windll.shcore.SetProcessDpiAwareness(1)  # 设置为 DPI 感知模式

# 设置 Tesseract 路径(根据实际安装路径修改)
# pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR'

# 全局变量
url = 'https://fanyi.so.com/index/search'
is_translating = False  # 防止重复翻译标志

# GUI主窗口
root = tk.Tk()
root.title("中英互译小工具")
root.geometry("480x400")
root.resizable(False, False)

# 在 root 初始化之后添加样式配置
style = ttk.Style()
style.theme_use('clam')  # 使用现代感更强的主题

# 自定义样式
style.configure("TButton", padding=6, relief="flat", background="#4A90E2", foreground="white", font=("Arial", 10, "bold"))
style.map("TButton",
          background=[('active', '#357ABD')],
          foreground=[('pressed', 'black'), ('active', 'white')])

style.configure("TEntry", padding=5, relief="flat", borderwidth=2, fieldbackground="#F5F5F5")
style.configure("TRadiobutton", background="#FFFFFF", font=("Arial", 10))
style.configure("TLabel", background="#FFFFFF", font=("Arial", 10))

# 全局变量初始化
output_var = tk.StringVar()

def get_headers():
    """获取随机 User-Agent"""
    ua = FakeUserAgent().random
    return {'Pro': 'fanyi', 'User-Agent': ua}

def log_translation(text, result):
    """记录翻译日志"""
    now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

    import os
    # 获取当前脚本所在目录
    current_dir = os.path.dirname(os.path.abspath(__file__))
    log_path = os.path.join(current_dir, "fanyi.txt")
    # 写入时自动创建文件(如果不存在)
    with open(log_path, "a", encoding="utf-8") as f:
        f.write(f"时间: {now_time.ljust(20)} 原文: {text.ljust(20)} 结果: {result.ljust(20)}\n")
        f.write("-" * 60 + "\n")

# 翻译逻辑
def translate(text):
    global is_translating
    if not text or is_translating:
        return

    is_translating = True
    translate_btn.config(state=tk.DISABLED)
    output_var.set("正在翻译...")

    mode = mode_var.get()
    data = {
        "eng": "1" if mode == "en2zh" else "0",
        "validate": "",
        "ignore_trans": "0",
        "query": text
    }

    try:
        response = requests.post(url, headers=get_headers(), data=data, timeout=10)
        if response.status_code == 200:
            result = response.json()['data']['fanyi']
            output_var.set(result)
            log_translation(text, result)
        else:
            output_var.set("❌ 翻译失败,请稍后再试")
    except requests.exceptions.RequestException as e:
        output_var.set(f"❌ 网络异常:{e}")
    except Exception as e:
        output_var.set(f"❌ 异常:{e}")
    finally:
        is_translating = False
        translate_btn.config(state=tk.NORMAL)

# OCR识别
def ocr_image(image):
    try:
        text = pytesseract.image_to_string(image).strip()
        input_entry.delete(0, tk.END)
        input_entry.insert(0, text)
        root.after(2000, translate, text)  # 延迟翻译
    except Exception as e:
        messagebox.showerror("错误", f"图像处理失败: {e}")

# 自定义截图功能
def custom_screenshot():
    top = tk.Toplevel()
    top.attributes("-fullscreen", True)
    top.attributes("-alpha", 0.3)
    top.config(bg='black')
    top.lift()

    canvas = tk.Canvas(top, cursor="cross")
    canvas.pack(fill=tk.BOTH, expand=True)

    rect = None
    start_x = start_y = 0

    def on_mouse_down(event):
        nonlocal start_x, start_y
        start_x, start_y = event.x_root, event.y_root
        canvas.delete("all")

    def on_mouse_drag(event):
        end_x, end_y = event.x_root, event.y_root
        canvas.delete("all")
        canvas.create_rectangle(start_x, start_y, end_x, end_y, outline="red", width=2)

    def on_mouse_up(event):
        nonlocal start_x, start_y
        end_x, end_y = event.x_root, event.y_root
        x1, y1 = min(start_x, end_x), min(start_y, end_y)
        x2, y2 = max(start_x, end_x), max(start_y, end_y)
        top.destroy()

        def do_screenshot():
            screenshot = ImageGrab.grab(bbox=(x1, y1, x2, y2))
            with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmpfile:
                screenshot_path = tmpfile.name
            screenshot.save(screenshot_path)

            # 显示预览窗口
            preview = tk.Toplevel(root)
            preview.title("截图预览")
            img = Image.open(screenshot_path)
            img.thumbnail((400, 300))
            tk_img = ImageTk.PhotoImage(img)
            label = tk.Label(preview, image=tk_img)
            label.image = tk_img
            label.pack(padx=10, pady=10)

            def save_screenshot():
                save_path = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG files", "*.png")])
                if save_path:
                    screenshot.save(save_path)
                    messagebox.showinfo("保存成功", "截图已成功保存!")

            save_btn = ttk.Button(preview, text="保存截图", command=save_screenshot)
            save_btn.pack(pady=10)

            loading = tk.Toplevel(root)
            loading.title("正在翻译")
            loading.geometry("200x100")
            tk.Label(loading, text="加载中...", font=("Arial", 14)).pack(padx=20, pady=20)

            def do_ocr():
                preview.destroy()
                ocr_image(screenshot)
                loading.destroy()

            root.after(2000, do_ocr)

        root.after(150, do_screenshot)

    canvas.bind("<ButtonPress-1>", on_mouse_down)
    canvas.bind("<B1-Motion>", on_mouse_drag)
    canvas.bind("<ButtonRelease-1>", on_mouse_up)

# 翻译方向选择
mode_var = tk.StringVar(value="en2zh")
ttk.Label(root, text="选择翻译方向:", font=("Arial", 12)).pack(pady=5)
mode_frame = tk.Frame(root)
mode_frame.pack()
ttk.Radiobutton(mode_frame, text="英文 ➜ 中文", variable=mode_var, value="en2zh").pack(side=tk.LEFT, padx=10)
ttk.Radiobutton(mode_frame, text="中文 ➜ 英文", variable=mode_var, value="zh2en").pack(side=tk.LEFT, padx=10)

# 输入框
ttk.Label(root, text="请输入要翻译的内容:", font=("Arial", 12)).pack(pady=5)
input_entry = ttk.Entry(root, font=("Arial", 12), width=40)
input_entry.pack()

# 翻译按钮
translate_btn = ttk.Button(root, text="开始翻译", command=lambda: translate(input_entry.get().strip()))
translate_btn.pack(pady=10)

# 自定义截屏按钮
screenshot_btn = ttk.Button(root, text="自定义截屏并翻译", command=custom_screenshot)
screenshot_btn.pack(pady=10)

# 输出结果
ttk.Label(root, text="翻译结果:", font=("Arial", 12)).pack()
output_frame = ttk.Frame(root, borderwidth=2, relief="groove")
output_frame.pack(pady=5, padx=10, fill=tk.X)

output_label = ttk.Label(output_frame, textvariable=output_var, font=("Arial", 12), foreground="blue", wraplength=440, anchor="center")
output_label.pack(padx=10, pady=10)

# 主循环
root.mainloop()

五.仅仅实现翻译

在运行界面输入翻译内容

import requests

from fake_useragent import FakeUserAgent  #这个是user,agent代理用户池

ua = FakeUserAgent().random               #随机生成用户代理

import time

url = 'https://fanyi.so.com/index/search'
headers = {
    'Pro': 'fanyi', #这个是这个网站关键处 没有就没法爬取
    'User-Agent': ua
}

now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

fanyi_chioce = input("你是需要将 英文 翻译为 中文 吗? 请输入'1',还是将 中文 翻译为 英文 ? 请输入'2':\n")
def fanyi():
    if fanyi_chioce == '1':
        people_Input = input('输入需要翻译的英文: ')
        #下面的这个为表单参数  在载荷里面可以看 (post)
        data_format = {
            "eng": "1",
            "validate": "",
            "ignore_trans": "0",
            "query": people_Input
        }
    elif fanyi_chioce == '2':
        people_Input = input('输入需要翻译的中文: ')
        data_format = {
            "eng": "0",
            "validate": "",
            "ignore_trans": "0",
            "query": people_Input
        }
    else:
        print('无效的选择')
        return
    try:
        response = requests.post(url, headers=headers, data=data_format, proxies={"http": None, "https": None})
        abc = response.status_code
        if abc == 200 :
            print("网络请求成功,正在翻译")
            data = response.json()   #这个数据.txt打印出来是字典(最外面有{}就是字典)说明这个就是json数据
            results = data['data']['fanyi']
            time.sleep(2)
            print('翻译结果是:', results)
            with open('fanyi.txt', 'a', encoding='utf-8') as file:
                file.write(f"时间: {now_time.ljust(20)}原文: {people_Input.ljust(20)}翻译结果: {results.ljust(20)}\n")
                file.write("-" * 60 + "\n")  # 用分隔符标记每次翻译结
        else:
            print("翻译失败,网络连接中断")

    except Exception as e:
        print(f"网络请求失败请稍后尝试,{e}")
        print("翻译失败")

while True:
    fanyi()
    fanyi_chioce = input("是否需要再次翻译? 输入'1' 翻译英文,'2' 代表翻译为中文。随便按将会退出\n")
    if fanyi_chioce not in ['1','2']:
        break
# 设置一个常用的用户代理(模拟浏览器)
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0 Safari/537.36"

# 翻译接口和请求头
url = 'https://fanyi.so.com/index/search'
headers = {
    'Pro': 'fanyi',
    'User-Agent': UA
}

运行样式:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智极Hub

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值