因為能及時地完成這個小工具,全靠在網上找到一些代碼來用,所以,也把自己完成的東西回饋給網路。:)
之前有這麼一個小需求,要大量地翻譯一些零散的句子,對於翻譯的品質並不在意,直接採用翻譯工具的結果就可以了。但是量很大,於是就想著用 Google 的翻譯 API 來做。一開始想用 JavaScript 來寫的,但由於只會 JavaScript 的對 Google 翻譯 API 的非同步呼叫方式,不知道如何才能進行批量的翻譯。
於是決定用 Python 的來實現。先從網上抄了一些現成的代碼(主要是參考這篇),但都不能正確地得到結果。由於稍微做了一些修改,使之能正常地運行得到翻譯的結果,代碼如下:
import urllib,urllib2from sgmllib import SGMLParserclass URLLister(SGMLParser): def __init__(self, result): SGMLParser.__init__(self) self.result = result self.open = False def start_div(self, attrs): id = [v for k, v in attrs if k=='id'] if 'tts_button' in id: self.open = True def handle_data(self, text): if self.open: self.result.append(text) self.open = Falsedef Translate(text, f, t): MySentence = [] values = {'hl':'zh-CN','ie':'UTF-8', 'text':text,'langpair':"%s|%s"%(f, t)} url = 'http://translate.google.cn/translate_t' data = urllib.urlencode(values) req = urllib2.Request(url, data) req.add_header('User-Agent', "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)") response = urllib2.urlopen(req) parser = URLLister(MySentence) parser.feed(response.read()) parser.close() return MySentence def TranlateForIgnorException(text): excpCnt = 0 while 1: try: arStr = Translate(langStr, "en", "ar")[0] break except: excpCnt = excpCnt + 1 if excpCnt > 10: break time.sleep(2) return arStrif __name__ == "__main__": ArStr = TranlateForIgnorException("This")
函數 Translate (第20行),是類比瀏覽器向 google 發出 http 的請求。第一個參數是需要翻譯的句子,第二、三個參數是原語言和目標語言,分別是一定預選定義好的字串(英文是 "en",阿拉伯語是"ar",簡體中文是'zh-CN'等),完整的定義在 Google 翻譯 API 的文檔中有描述。傳回值是翻譯後的字串,是 UTF8 的編碼。這個函數可以看成是同步的。
我在使用的時候,把要翻譯的句子讀入一個 list 中,然後依次進行翻譯。連續調用的時候,很容易出現 http 506 錯誤的異常。我不知道如何正確地處理它,於是我用了另一個函數(第33行)TranlateForIgnorException ,當出現異常時就再進行一次翻譯,直到翻譯成功為止,或是,異常連續出現 10 次(因為有的句子無法進行翻譯,比如,帶有"http://"這樣網址的字串)。
另外一點需要說明的是,原來在網上抄的代碼中,解析 html 檔案得到翻譯後字串的部分有點問題,問題是在第 13 行代碼處,原來的代碼是以'result_box' 為標籤時進行抽取,但我使用後發現不太對,於是把 google 發回的整個 html 檔案存下來,查看後發現,翻譯後文字是存在 'tts_button' 為 id 的 div 標籤中的。所以我進行了修改,我不保證這個絕對正確,如果您發現有不對的地方,可以試著從這些看看。