1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
| """
通过监听快捷键快速实现指定功能。
监听快捷键 [Alt + O], 从剪切板拿到图片数据,通过调用腾讯AI的OCR接口,获得返回后的文本,将OCR的文本放入剪切板中。
Python Version: 3.12.2
依赖:
win10toast==0.9 -- 向操作系统发送通知
pywin32==223 -- Windons API 库
Pillow==10.4.0 -- PIL 图像处理库
keyboard==0.13.5 -- 使用这个小型Python库完全控制你的键盘。挂钩全局事件、注册热键、模拟按键等等。
requests==2.32.3 -- HTTP请求库
快速安装:
pip install win10toast==0.9 pywin32==223 Pillow==10.4.0 keyboard==0.13.5 requests==2.32.3
"""
import base64
import datetime
import io
import json
import logging
import random
import hashlib
import hmac
import time
import functools
from pathlib import Path
from urllib.parse import urlparse
import requests
import keyboard
import pyperclip
import win32clipboard as wc
from PIL import Image
from win10toast import ToastNotifier
logger = logging.getLogger("root")
FILE_DIR = Path(__file__).parent.absolute()
keys = json.loads(FILE_DIR.joinpath("self_config.json").read_text())
s_keys = keys["tencent_key"]
def send_notication(title, text, duration=3):
ToastNotifier().show_toast(title=title, msg=text, duration=duration, threaded=True)
def get_image_from_clipboard():
try:
wc.OpenClipboard()
if wc.IsClipboardFormatAvailable(wc.CF_DIB):
# Get the device-independent bitmap (DIB) format data
dib = wc.GetClipboardData(wc.CF_DIB)
return Image.open(io.BytesIO(dib))
except Exception as e:
logger.error(f"Error reading image from clipboard: {e}")
return 0
finally:
wc.CloseClipboard()
def most_english(text) -> bool:
"""字符串中大多数是英语"""
if len(text) == 0:
raise ValueError("空字符串.")
ec_num = 0
for c in text:
if c.isalpha and "a" <= c.lower() <= "z":
ec_num += 1
if ec_num / len(text) > 0.5:
return True
return False
@functools.lru_cache(25)
def translate_api(text, from_lang="auto", to_lang="zh") -> list[dict[str, str]]:
"""翻译API,
return src, dst
"""
url = "http://api.fanyi.baidu.com/api/trans/vip/translate"
salt = random.randint(32768, 65536)
appid, appkey = keys["baidu_translate"]
sign = hashlib.md5((appid + text + str(salt) + appkey).encode("utf-8")).hexdigest()
resp = requests.post(
url=url,
headers={"Content-Type": "application/x-www-form-urlencoded"},
params={
"appid": appid,
"q": text,
"from": from_lang,
"to": to_lang,
"salt": salt,
"sign": sign,
},
)
if resp.status_code != 200:
raise Exception(resp.text())
return resp.json().get("trans_result")
def translate_iamge(image_data: bytes, from_lang="auto", to_lang="zh") -> list:
""""""
url = "http://fanyi-api.baidu.com/api/trans/sdk/picture"
salt = random.randint(32768, 65536)
appid = "20240531002066479"
appkey = "05IgcgzWKnf5J7hDKlyK"
file_md5 = hashlib.md5(image_data).hexdigest()
cuid, mac = "APICUID", "mac"
sign = hashlib.md5(
(appid + file_md5 + str(salt) + cuid + mac + appkey).encode()
).hexdigest()
payload = {
"from": from_lang,
"to": to_lang,
"appid": appid,
"salt": salt,
"sign": sign,
"cuid": cuid,
"mac": mac,
}
image = {"image": ("translate-iamge", image_data, "multipart/form-data")}
resp = requests.post(url, params=payload, files=image)
if resp.status_code != 200:
raise Exception(resp.text())
return resp.json().get("data", {}).get("content", [])
def translate():
# 从剪贴板读取数据
keyboard.send("ctrl+c")
clipb_data = pyperclip.paste()
if not clipb_data:
logger.error("翻译失败: 未从剪切板获取到数据")
send_notication("翻译失败", "未从剪切板获取到数据")
return
logger.debug("剪贴板内容: %s", clipb_data)
# 处理剪贴板数据
processed_data = translate_api(
clipb_data,
to_lang="zh" if most_english(clipb_data) else "en",
)
# processed_data = json.dumps(processed_data, ensure_ascii=False, indent=2)
processed_data = "\n".join([l.get("dst") for l in processed_data])
# 将处理后的数据放回剪贴板
pyperclip.copy(processed_data)
# keyboard.send("F3")
send_notication("翻译结果已经放入剪切板", processed_data)
logger.debug("处理后的数据已放回剪贴板: %s", processed_data)
if __name__ == "__main__":
# 注册快捷键组合
keyboard.add_hotkey("ctrl+alt+d", translate, suppress=False)
print("""1. 监听快捷 [Ctrl+Alt+S], 从剪切板中得到拿到文本数据, 通过调用百度翻译的API接口翻译文本,将翻译后的数据放入剪切板中。
2. 监听快捷键 [Alt + O], 从剪切板拿到图片数据,通过调用腾讯AI的OCR接口,获得返回后的文本,将OCR的文本放入剪切板中。""")
logging.basicConfig(level="DEBUG")
# 保持程序运行,直到手动终止
keyboard.wait()
|