前言
由於最近APP需要增加對其它語言的支持,因此需要有個可以實現翻譯的腳本,摸索了兩三天,雖然最後感覺腳本不怎麼完美,但還是記錄下這期間遇到的問題:
過程
在網上搜了一些如何用python實現google腳本,大致有三種:
1.調用google API的
2.使用別人已經封裝好的庫
3.類似爬蟲方式獲取(我沒爬過,也不知道算不算)
這裏採用第三種,主要是看了利用python調用谷歌翻譯API這篇文章,感覺蠻簡單,也感覺比較靠譜,然後就開搞了。
按照利用python調用谷歌翻譯API這篇文章實現腳本以後,發現只能翻譯成中文,而且不適合翻譯多個句子。
最後自己摸索了一下,將這個腳本稍微改了下,支持翻譯多條語句:
import requests
import json
import execjs # 必須,需要先用pip 安裝,用來執行js腳本
from urllib.parse import quote
# 用來判斷是否需要打印日誌
debug = True
class Py4Js:
def __init__(self):
self.ctx = execjs.compile("""
function TL(a) {
var k = "";
var b = 406644;
var b1 = 3293161072;
var jd = ".";
var $b = "+-a^+6";
var Zb = "+-3^+b+-f";
for (var e = [], f = 0, g = 0; g < a.length; g++) {
var m = a.charCodeAt(g);
128 > m ? e[f++] = m : (2048 > m ? e[f++] = m >> 6 | 192 : (55296 == (m & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (m = 65536 + ((m & 1023) << 10) + (a.charCodeAt(++g) & 1023),
e[f++] = m >> 18 | 240,
e[f++] = m >> 12 & 63 | 128) : e[f++] = m >> 12 | 224,
e[f++] = m >> 6 & 63 | 128),
e[f++] = m & 63 | 128)
}
a = b;
for (f = 0; f < e.length; f++) a += e[f],
a = RL(a, $b);
a = RL(a, Zb);
a ^= b1 || 0;
0 > a && (a = (a & 2147483647) + 2147483648);
a %= 1E6;
return a.toString() + jd + (a ^ b)
};
function RL(a, b) {
var t = "a";
var Yb = "+";
for (var c = 0; c < b.length - 2; c += 3) {
var d = b.charAt(c + 2),
d = d >= t ? d.charCodeAt(0) - 87 : Number(d),
d = b.charAt(c + 1) == Yb ? a >>> d: a << d;
a = b.charAt(c) == Yb ? a + d & 4294967295 : a ^ d
}
return a
}
""")
def get_tk(self, text):
return self.ctx.call("TL", text)
def build_url(text, tk, tl='zh-CN'):
"""
需要用轉URLEncoder
:param text:
:param tk:
:param tl:
:return:
"""
return 'https://translate.google.cn/translate_a/single?client=webapp&sl=auto&tl=' + tl + '&hl=zh-CN&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&source=btn&ssel=0&tsel=0&kc=0&tk=' \
+ str(tk) + '&q=' + quote(text, encoding='utf-8')
def translate(js, text, tl='zh-CN'):
"""
tl爲要翻譯的語言
de:德語
ja:日語
sv:瑞典語
nl:荷蘭語
ar:阿拉伯語
ko:韓語
pt:葡萄牙語
zh-CN:中文簡體
zh-TW:中文繁體
"""
header = {
'authority': 'translate.google.cn',
'method': 'GET',
'path': '',
'scheme': 'https',
'accept': '*/*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9,ja;q=0.8',
# 'cookie': '_ga=GA1.3.110668007.1547438795; _gid=GA1.3.791931751.1548053917; 1P_JAR=2019-1-23-1; NID=156=biJbQQ3j2gPAJVBfdgBjWHjpC5m9vPqwJ6n6gxTvY8n1eyM8LY5tkYDRsYvacEnWNtMh3ux0-lUJr439QFquSoqEIByw7al6n_yrHqhFNnb5fKyIWMewmqoOJ2fyNaZWrCwl7MA8P_qqPDM5uRIm9SAc5ybSGZijsjalN8YDkxQ',
'cookie':'_ga=GA1.3.110668007.1547438795; _gid=GA1.3.1522575542.1548327032; 1P_JAR=2019-1-24-10; NID=156=ELGmtJHel1YG9Q3RxRI4HTgAc3l1n7Y6PAxGwvecTJDJ2ScgW2p-CXdvh88XFb9dTbYEBkoayWb-2vjJbB-Rhf6auRj-M-2QRUKdZG04lt7ybh8GgffGtepoA4oPN9OO9TeAoWDY0HJHDWCUwCpYzlaQK-gKCh5aVC4HVMeoppI',
# 'cookie': '',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.108 Safari/537.36',
'x-client-data': 'CKi1yQEIhrbJAQijtskBCMG2yQEIqZ3KAQioo8oBCL+nygEI7KfKAQjiqMoBGPmlygE='
}
url = build_url(text, js.get_tk(text), tl)
res = []
try:
r = requests.get(url, headers=header)
result = json.loads(r.text)
r.encoding = "UTF-8"
if debug:
print(r.url)
print(r.headers)
print(r.request.headers)
print(result)
res = result[0]
if res is None:
if result[7] is not None:
# 如果我們文本輸錯,提示你是不是要找xxx的話,那麼重新把xxx正確的翻譯之後返回
try:
correct_text = result[7][0].replace('<b><i>', ' ').replace('</i></b>', '')
if debug:
print(correct_text)
correct_url = build_url(correct_text, js.get_tk(correct_text), tl)
correct_response = requests.get(correct_url)
correct_result = json.loads(correct_response.text)
res = correct_result[0]
except Exception as e:
if debug:
print(e)
res = []
except Exception as e:
res = []
if debug:
print(url)
print("翻譯" + text + "失敗")
print("錯誤信息:")
print(e)
finally:
return res
def get_translate(word, tl):
js = Py4Js()
translate_result = translate(js, word, tl)
if debug:
print("word== %s, tl== %s" % (word, tl))
print(translate_result)
return translate_result
if __name__ == '__main__':
debug = True
translate_text = '3.Hear voice prompt \"start configuration mode\". click \"reset successfully\" button\n'
results = get_translate(translate_text, 'cs')
translate_result = ""
if "." in translate_text or "?" in translate_text:
for result in results:
translate_result += result[0]
else:
result_translate = results[0]
if debug:
print("translate_result:" + translate_result)
其中: tl 是要進行翻譯的其它國家語言的縮寫
遇到的問題
1.由於需要翻譯上千條字段,於是開啓多線程翻譯,並且每次請求間隔很短,導致很多請求超時
想到的解決方式是:每次請求翻譯儘量多的字段
2.在翻譯多個字段的時候,返回的子列表比要翻譯的字段多,如:
'3.Hear voice prompt \"start configuration mode\". click \"reset successfully\" button\n'
該字符串中在APP中是一個字段,但是包含兩個句子,因爲中間包含英文句號’.’,其返回結果
[
['3. Hlasová výzva "start konfigurační režim". ', '3.Hear voice prompt "start configuration mode".', None, None, 3],
['klikněte na tlačítko "obnovit úspěšně"', 'click "reset successfully" button', None, None, 3]
]
備註:最內層的每個列表(一個列表表示一句)就是翻譯結果,列表的第1項爲翻譯結果,第2項爲對應要翻譯的內容。
因此,遇到有多個句子的字段需要單獨翻譯
備註:英文句號“.”,問號“?”,換行符“\n”,都會導致返回結果,因此猜測,其它分割語句的符號也是,但是目前腳本沒有做其它分割語句的處理。
3.翻譯結果符號問題
3.1 莫名多出空格,如:格式化字符串 %d會在中間多出空格:% d,/前後會多出空格等
3.2 要在Android 資源文件中使用,需要注意翻譯結果是否出現單引號,出現單引號需要加斜槓’'處理,如果需要顯示雙引號,也需要加斜槓處理。
附腳本
腳本
該腳本翻譯內容從Excel獲取,然後將結果放到另一個Excel中。