两种免费的翻译API调用方式详解 - Edge官方API与个人缓存服务
一、前言
在日常开发中,翻译功能是一个非常常见的需求。本文将详细介绍两种完全免费的翻译API调用方式,并提供完整的代码实现和部署教程。
1.1 方案对比
| 对比项 | Edge官方翻译API | 个人翻译服务 |
|---|---|---|
| 调用方式 | 直接HTTP请求 | 通过本地Flask服务 |
| 是否需要认证 | 否 | 需要获取Edge Token |
| 是否支持缓存 | 否 | 支持SQLite缓存 |
| 并发处理 | 无限制 | 支持并发,防止缓存击穿 |
| 部署难度 | 简单 | 中等 |
| 适用场景 | 少量翻译请求 | 大量翻译请求 |
二、环境准备
2.1 Python环境要求
bash
# Python 3.7+
python --version
# 安装依赖包
pip install requests flask
2.2 项目结构
translation_project/
├── edge_translator.py # Edge官方API翻译
├── personal_translator.py # 个人翻译服务(含Flask API)
├── translation_utils.py # 统一调用接口
├── main.py # 主程序入口
└── requirements.txt # 依赖清单
三、Edge官方翻译API实现
3.1 API接口分析
Edge浏览器的翻译接口不需要任何认证,直接发送POST请求即可使用。接口地址为:
https://edge.microsoft.com/translate/translatetext?from=en&to=zh-CHS
3.2 完整代码实现
文件:edge_translator.py
python
"""
Edge官方翻译API封装
特点:无需认证,直接调用
"""
import requests
import json
from typing import Optional, List
from urllib.parse import urlencode
class EdgeTranslator:
"""Edge翻译器"""
def __init__(self):
self.base_url = "https://edge.microsoft.com/translate/translatetext"
self.headers = {
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
"Origin": "https://www.microsoft.com",
"Referer": "https://www.microsoft.com/"
}
def translate(self, text: str, from_lang: str = "en", to_lang: str = "zh-CHS") -> str:
"""
翻译文本
Args:
text: 待翻译文本
from_lang: 源语言代码
to_lang: 目标语言代码
Returns:
翻译后的文本
"""
# 构建请求参数
params = {
"from": from_lang,
"to": to_lang,
"api-version": "3.0"
}
# 构建完整URL
url = f"{self.base_url}?{urlencode(params)}"
# 发送请求
try:
response = requests.post(
url,
json=[text],
headers=self.headers,
timeout=30
)
response.raise_for_status()
# 解析响应
result = response.json()
return result[0] if isinstance(result, list) else result.get('translation', '')
except requests.exceptions.RequestException as e:
raise Exception(f"Edge翻译API调用失败: {e}")
def batch_translate(self, texts: List[str], from_lang: str = "en", to_lang: str = "zh-CHS") -> List[str]:
"""
批量翻译
Args:
texts: 待翻译文本列表
from_lang: 源语言
to_lang: 目标语言
Returns:
翻译后的文本列表
"""
params = {
"from": from_lang,
"to": to_lang,
"api-version": "3.0"
}
url = f"{self.base_url}?{urlencode(params)}"
try:
response = requests.post(url, json=texts, headers=self.headers, timeout=60)
response.raise_for_status()
result = response.json()
return result if isinstance(result, list) else [result.get('translation', '')]
except requests.exceptions.RequestException as e:
raise Exception(f"Edge批量翻译失败: {e}")
def get_supported_languages(self) -> dict:
"""获取支持的语言列表(部分常用语言)"""
return {
"en": "英语",
"zh-CHS": "简体中文",
"zh-CHT": "繁体中文",
"ja": "日语",
"ko": "韩语",
"fr": "法语",
"de": "德语",
"es": "西班牙语",
"ru": "俄语",
"ar": "阿拉伯语"
}
# 使用示例
if __name__ == "__main__":
translator = EdgeTranslator()
# 单个翻译
result = translator.translate("Hello, world!", from_lang="en", to_lang="zh-CHS")
print(f"翻译结果: {result}")
# 批量翻译
texts = ["Hello", "World", "Programming"]
results = translator.batch_translate(texts)
for original, translated in zip(texts, results):
print(f"{original} -> {translated}")
四、个人翻译服务实现(带缓存)
4.1 服务架构设计
个人翻译服务基于Flask框架,主要特点:
- 本地缓存:使用SQLite存储翻译结果,减少API调用
- Token管理:自动获取和刷新Edge认证Token
- 缓存击穿防护:使用线程锁防止同一文本被并发重复翻译
- 高并发支持:采用WAL模式提升数据库并发性能
4.2 完整服务代码
文件:personal_translator.py
python
"""
个人翻译服务 - 带本地缓存和并发控制
运行方式: python personal_translator.py
"""
import json
import os
import sqlite3
import time
import threading
from datetime import datetime
from typing import Optional
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
# 数据库配置
DB_PATH = os.environ.get("DB_PATH", "translate_cache.db")
AUTH_URL = "https://edge.microsoft.com/translate/auth"
TRANSLATE_URL = "https://api.cognitive.microsofttranslator.com/translate"
# 全局变量
_token = None
_token_expire_at = 0
_token_lock = threading.Lock()
_write_lock = threading.Lock()
_text_locks = {}
_text_locks_guard = threading.Lock()
def _get_conn():
"""获取数据库连接"""
conn = sqlite3.connect(DB_PATH, timeout=30, check_same_thread=False)
# 启用WAL模式,提升并发性能
conn.execute("PRAGMA journal_mode=WAL")
conn.execute("PRAGMA busy_timeout=5000")
# 创建表
conn.execute("""
CREATE TABLE IF NOT EXISTS translations (
src TEXT PRIMARY KEY,
dst TEXT NOT NULL,
created_at INTEGER NOT NULL
)
""")
return conn
def get_token() -> str:
"""
获取Edge翻译Token(带缓存)
Token有效期约10分钟,这里9分钟后自动刷新
"""
global _token, _token_expire_at
with _token_lock:
if _token and time.time() < _token_expire_at:
return _token
print(f"[{datetime.now()}] 获取新的Edge Token...")
resp = requests.get(AUTH_URL, timeout=10)
resp.raise_for_status()
_token = resp.text.strip()
_token_expire_at = time.time() + 9 * 60 # 9分钟有效期
print(f"[{datetime.now()}] Token获取成功")
return _token
def db_get(text: str) -> Optional[str]:
"""从缓存查询翻译"""
conn = _get_conn()
try:
row = conn.execute(
"SELECT dst FROM translations WHERE src = ?", (text,)
).fetchone()
return row[0] if row else None
finally:
conn.close()
def db_set(text: str, dst: str):
"""写入缓存"""
with _write_lock:
conn = _get_conn()
try:
conn.execute(
"INSERT INTO translations (src, dst, created_at) VALUES (?, ?, ?) "
"ON CONFLICT(src) DO UPDATE SET dst=excluded.dst, created_at=excluded.created_at",
(text, dst, int(time.time()))
)
conn.commit()
finally:
conn.close()
def call_translate_api(text: str, from_lang: str = "zh-CHS", to_lang: str = "en") -> str:
"""
调用真实翻译API
Args:
text: 待翻译文本
from_lang: 源语言
to_lang: 目标语言
"""
token = get_token()
# 构建请求参数
params = {
"from": from_lang,
"to": to_lang,
"api-version": "3.0",
"includeSentenceLength": "true"
}
headers = {
"authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
payload = json.dumps([{"Text": text}])
# 构建完整URL
url = f"{TRANSLATE_URL}?{requests.compat.urlencode(params)}"
resp = requests.post(url, headers=headers, data=payload, timeout=10)
resp.raise_for_status()
data = resp.json()
return data[0]["translations"][0]["text"]
def translate(text: str, from_lang: str = "zh-CHS", to_lang: str = "en") -> str:
"""
翻译主函数(带缓存和并发控制)
Args:
text: 待翻译文本
from_lang: 源语言
to_lang: 目标语言
"""
# 1. 先查缓存
cached = db_get(text)
if cached is not None:
return cached
# 2. 获取该文本的锁,防止缓存击穿
with _text_locks_guard:
lock = _text_locks.setdefault(text, threading.Lock())
with lock:
# 再次检查缓存(可能其他线程已写入)
cached = db_get(text)
if cached is not None:
result = cached
else:
# 调用API翻译
result = call_translate_api(text, from_lang, to_lang)
# 保存到缓存
db_set(text, result)
# 3. 清理未使用的锁
with _text_locks_guard:
if lock.acquire(False):
del _text_locks[text]
lock.release()
return result
@app.route("/translate", methods=["POST"])
def translate_endpoint():
"""翻译接口"""
body = request.get_json(silent=True) or {}
text = body.get("text")
from_lang = body.get("from", "zh-CHS")
to_lang = body.get("to", "en")
if not text or not str(text).strip():
return jsonify({"error": "缺少参数 text"}), 400
try:
result = translate(str(text).strip(), from_lang, to_lang)
except sqlite3.Error as e:
return jsonify({"error": f"数据库错误: {e}"}), 502
except requests.RequestException as e:
return jsonify({"error": f"翻译服务调用失败: {e}"}), 502
return jsonify({
"translation": result,
"from": from_lang,
"to": to_lang
})
@app.route("/batch_translate", methods=["POST"])
def batch_translate_endpoint():
"""批量翻译接口"""
body = request.get_json(silent=True) or {}
texts = body.get("texts", [])
from_lang = body.get("from", "zh-CHS")
to_lang = body.get("to", "en")
if not texts or not isinstance(texts, list):
return jsonify({"error": "缺少参数 texts(必须为列表)"}), 400
results = []
for text in texts:
if text and str(text).strip():
result = translate(str(text).strip(), from_lang, to_lang)
results.append(result)
else:
results.append("")
return jsonify({
"translations": results,
"from": from_lang,
"to": to_lang
})
@app.route("/health", methods=["GET"])
def health():
"""健康检查"""
return jsonify({
"status": "ok",
"timestamp": datetime.now().isoformat()
})
@app.route("/cache/stats", methods=["GET"])
def cache_stats():
"""缓存统计"""
conn = _get_conn()
try:
size = conn.execute("SELECT COUNT(*) FROM translations").fetchone()[0]
finally:
conn.close()
return jsonify({
"size": size,
"db_path": DB_PATH
})
@app.route("/cache/clear", methods=["POST"])
def clear_cache():
"""清空缓存"""
conn = _get_conn()
try:
conn.execute("DELETE FROM translations")
conn.commit()
return jsonify({"message": "缓存已清空"})
finally:
conn.close()
if __name__ == "__main__":
print("=" * 60)
print("个人翻译服务启动")
print(f"数据库路径: {DB_PATH}")
print("服务地址: http://localhost:5000")
print("=" * 60)
print("接口列表:")
print(" POST /translate - 翻译单个文本")
print(" POST /batch_translate - 批量翻译")
print(" GET /health - 健康检查")
print(" GET /cache/stats - 缓存统计")
print(" POST /cache/clear - 清空缓存")
print("=" * 60)
# 启动服务
app.run(host="0.0.0.0", port=5000, debug=False, threaded=True)
五、统一调用接口
为了方便切换两种翻译方式,我们实现一个统一的调用接口。
文件:translation_utils.py
python
"""
翻译工具统一接口
支持切换Edge官方API和个人缓存服务
"""
from typing import Optional, List
from enum import Enum
from edge_translator import EdgeTranslator
import requests
class TranslateMethod(Enum):
EDGE = "edge"
PERSONAL = "personal"
class Translator:
"""统一翻译器"""
def __init__(self, method: TranslateMethod = TranslateMethod.PERSONAL):
"""
初始化翻译器
Args:
method: 翻译方式,EDGE或PERSONAL
"""
self.method = method
self.edge_translator = EdgeTranslator() if method == TranslateMethod.EDGE else None
self.personal_api_url = "http://localhost:5000/translate"
def translate(self, text: str, from_lang: str = "zh-CHS", to_lang: str = "en") -> str:
"""
翻译文本
Args:
text: 待翻译文本
from_lang: 源语言
to_lang: 目标语言
"""
if self.method == TranslateMethod.EDGE:
# 使用Edge API
return self.edge_translator.translate(text, from_lang, to_lang)
else:
# 使用个人服务
try:
response = requests.post(
self.personal_api_url,
json={"text": text, "from": from_lang, "to": to_lang},
timeout=30
)
response.raise_for_status()
return response.json()["translation"]
except requests.exceptions.RequestException as e:
raise Exception(f"个人翻译服务调用失败: {e}")
def batch_translate(self, texts: List[str], from_lang: str = "zh-CHS", to_lang: str = "en") -> List[str]:
"""批量翻译"""
if self.method == TranslateMethod.EDGE:
return self.edge_translator.batch_translate(texts, from_lang, to_lang)
else:
try:
response = requests.post(
f"{self.personal_api_url}/batch_translate",
json={"texts": texts, "from": from_lang, "to": to_lang},
timeout=60
)
response.raise_for_status()
return response.json()["translations"]
except requests.exceptions.RequestException as e:
raise Exception(f"个人批量翻译服务调用失败: {e}")
def switch_method(self, method: TranslateMethod):
"""切换翻译方式"""
self.method = method
if method == TranslateMethod.EDGE and not self.edge_translator:
self.edge_translator = EdgeTranslator()
# 使用示例
if __name__ == "__main__":
# 测试两种翻译方式
texts = ["你好,世界!", "今天天气很好", "Python是一门优秀的编程语言"]
print("=" * 60)
print("1. 使用个人翻译服务")
print("=" * 60)
translator = Translator(TranslateMethod.PERSONAL)
for text in texts:
result = translator.translate(text)
print(f"{text} -> {result}")
print("\n" + "=" * 60)
print("2. 使用Edge官方API")
print("=" * 60)
translator.switch_method(TranslateMethod.EDGE)
for text in texts:
result = translator.translate(text, from_lang="zh-CHS", to_lang="en")
print(f"{text} -> {result}")
六、主程序入口
文件:main.py
python
"""
翻译工具主程序
支持命令行交互和API调用两种模式
"""
import argparse
import sys
from translation_utils import Translator, TranslateMethod
def main():
parser = argparse.ArgumentParser(description="翻译工具")
parser.add_argument("-t", "--text", help="待翻译文本")
parser.add_argument("-f", "--from", dest="from_lang", default="zh-CHS", help="源语言")
parser.add_argument("-to", "--to", dest="to_lang", default="en", help="目标语言")
parser.add_argument("--method", choices=["edge", "personal"], default="personal",
help="翻译方式: edge(Edge官方API) 或 personal(个人缓存服务)")
parser.add_argument("--batch", action="store_true", help="批量翻译模式")
args = parser.parse_args()
# 创建翻译器
method = TranslateMethod.EDGE if args.method == "edge" else TranslateMethod.PERSONAL
translator = Translator(method)
# 批量翻译模式
if args.batch:
print("批量翻译模式(输入多行文本,Ctrl+D结束):")
lines = sys.stdin.read().strip().splitlines()
for line in lines:
if line.strip():
try:
result = translator.translate(line.strip(), args.from_lang, args.to_lang)
print(f"{line.strip()} -> {result}")
except Exception as e:
print(f"翻译失败: {e}")
else:
# 单文本翻译
if not args.text:
print("请输入待翻译文本: ", end="")
args.text = sys.stdin.readline().strip()
if not args.text:
print("错误: 请输入文本")
sys.exit(1)
try:
result = translator.translate(args.text, args.from_lang, args.to_lang)
print(f"翻译结果: {result}")
except Exception as e:
print(f"翻译失败: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
七、部署和使用指南
7.1 部署个人翻译服务
bash
# 1. 创建虚拟环境(可选)
python -m venv venv
source venv/bin/activate # Linux/Mac
# 或
venv\Scripts\activate # Windows
# 2. 安装依赖
pip install requests flask
# 3. 启动服务
python personal_translator.py
7.2 使用方式
方式一:命令行调用
bash
# 使用个人服务翻译
python main.py -t "你好,世界" --method personal
# 使用Edge API翻译
python main.py -t "Hello, world" -f en -to zh-CHS --method edge
# 批量翻译
python main.py --batch << EOF
你好
世界
编程
EOF
方式二:API调用
bash
# 翻译单个文本
curl -X POST http://localhost:5000/translate \
-H "Content-Type: application/json" \
-d '{"text": "你好,世界", "from": "zh-CHS", "to": "en"}'
# 批量翻译
curl -X POST http://localhost:5000/batch_translate \
-H "Content-Type: application/json" \
-d '{"texts": ["你好", "世界"], "from": "zh-CHS", "to": "en"}'
# 查看缓存统计
curl http://localhost:5000/cache/stats
方式三:Python代码调用
python
from translation_utils import Translator, TranslateMethod
# 使用个人服务
translator = Translator(TranslateMethod.PERSONAL)
result = translator.translate("你好,世界")
print(result)
# 切换到Edge API
translator.switch_method(TranslateMethod.EDGE)
result = translator.translate("Hello, world", "en", "zh-CHS")
print(result)
7.3 性能优化建议
1. 高并发部署
bash
# 使用gunicorn部署(生产环境)
pip install gunicorn
gunicorn -w 4 -k gthread --threads 8 personal_translator:app
2. 数据库优化
sql
-- 创建索引加速查询
CREATE INDEX idx_created_at ON translations(created_at);
-- 定期清理过期缓存(7天前的数据)
DELETE FROM translations WHERE created_at < strftime('%s', 'now', '-7 days');
3. 内存缓存层(可选)
python
from functools import lru_cache
@lru_cache(maxsize=10000)
def cached_translate(text: str) -> str:
return translate(text)
7.4 常见问题解决
Q1: Edge翻译API返回401错误
解决方案:检查User-Agent是否正确,确保包含Edge浏览器标识。
Q2: 个人服务Token过期
解决方案:程序会自动刷新Token,无需手动处理。
Q3: 数据库锁冲突
解决方案:设置合适的超时时间,使用WAL模式。
python
conn = sqlite3.connect(DB_PATH, timeout=30)
conn.execute("PRAGMA journal_mode=WAL")
Q4: 翻译速度慢
解决方案:
- 使用缓存减少API调用
- 增加线程数
- 考虑使用Redis替代SQLite
八、总结
本文介绍了两种免费的翻译API调用方式:
- Edge官方翻译API:简单直接,无需认证,适合偶尔使用
- 个人翻译服务:带本地缓存,性能更好,适合大量翻译需求
两种方式各有优势,您可以根据实际需求选择。个人翻译服务的缓存机制可以显著减少API调用次数,提高响应速度,尤其适合需要大量翻译的场景。
8.1 扩展建议
- 多语言支持:扩展支持更多语言对
- 翻译记忆库:使用翻译记忆库提高翻译质量
- Web界面:开发友好的Web界面供非技术人员使用
- 监控告警:添加服务监控和异常告警
8.2 参考资源
最简单的参考
python
import requests
url = "https://edge.microsoft.com/translate/translatetext?from=en&to=zh-CHS"
headers = {
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0",
"Origin": "https://www.microsoft.com"
}
data = ["Hello world, edge translate api"]
resp = requests.post(url, json=data, headers=headers)
print(resp.json())
输出内容为
php
[{'translations': [{'text': '你好,世界,Edge 翻译 API', 'to': 'zh-Hans', 'sentLen': {'srcSentLen': [31], 'transSentLen': [17]}}]}]