大家好,我是我是Python進階者。
一、前言
前幾天有個叫【張茜】的粉絲找我看了一個代碼,關于電子書中英文自動翻譯的,感覺挺有意思,這裡拿出來給大家分享下。
二、簡介
這個小項目是git上一個叫【xiaolai】的大佬分享的,看上去還是挺新的,釋出不太久,14天前釋出的。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2Pn5GcuUDZ5UjY1MjY2UDO0kDMlVWM5EDZzAzMhVjZ1QGMiRGMvwFNygDO1cjMtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.png)
一本書中文譯文大約 39 萬字的書,差不多用 1.5 小時就可以處理完畢(包括基本的格式編輯),這速度恐怖如斯!下面一起來看看這款神器的使用方法吧!
三、電子書格式轉換路徑
首先,需要将電子書從 Kindle 中導出來,并用 ePubor 進行 deDRM,而後将電子書轉換成 epub 檔案。
我都是在 Amazon 上直接買,而後在電腦上安裝一個老版本的 Kindle App,用滑鼠右鍵點選書名,下載下傳,并不打開該電子書,而後退出 Kindle。
ePubor Ultimate 也是個收費軟體,能把舊版 Kindle 下載下傳的電子書的 DRM 去掉;将 awz 檔案轉換成 epub 檔案。(可參考這個網頁)
然後,再用免費軟體 Calibre 将 epub 轉換成 htmlz 檔案(一個壓縮包)。(我嘗試過使用指令行工具包 pandoc,但,比較之後,發現 Calibre 在保留樣式方面可能更好一點……)
在 Terminal 裡用 unzip 指令解開 htmlz 壓縮包。
四、選擇 html 格式作為翻譯格式的原因
可以保留書中大量的腳注、尾注及其連結;DeepL 有專門的 API 參數處理 xml tag,tag_handling="xml";
可以通過 css 檔案随意設定顯示樣式,比較靈活;
可以通過插入 javascript 函數指定某種特定語言的顯示(比如,隻顯示中文);
可以用來作為源檔案轉換成任意格式的電子書……
另外,在調用 tag_handling="xml" 之後,DeepL API 傳回的譯文非正常整,能夠保留所有 html tag;并且,“傳回字元串” 與 “原字元串” 相同,可以作為一個判斷依據 —— 該行有沒有被翻譯,如果沒有,在生成的譯文 html 檔案中,該行沒必要重複出現……
五、清理 html
html 檔案整理起來比較麻煩,一個比較友善的手段是使用 BeautifulSoup 子產品。BeautifulSoup 本來是爬蟲工具,但,它又很友善的手段可以清理 html 檔案。
以下腳本主要完成以下工作:
首先将 html 檔案裡的所有 \n 去掉;将所有
單獨放在一行;将所有
也單獨放在一行;将
内部的所有 \n 全都去掉;并在之前加上一個空行;…… 當然,你可以在這裡做更多你自己喜歡做的格式清理。為了友善起見,
path
和
source_filename
以及
target_filename
都單獨指定。代碼如下:
import bs4
import re
path = "John Law/" # 檔案夾名稱末尾得有 /
source_filename = "index.html"
target_filename = "index2.html"
html = open(path+source_filename)
htmltext = html.read()
soup = bs4.BeautifulSoup(htmltext)
# 将所有的 \n 去掉……
htmltext = str(bs4.BeautifulSoup(htmltext)).replace("\n", "")
# <h... 之前添加空行
pttn = r'<h'
rpl = r'\n\n<h'
re.findall(pttn, htmltext)
htmltext = re.sub(pttn, rpl, htmltext)
# <div... 之前添加空行
pttn = r'<div'
rpl = r'\n\n<div'
re.findall(pttn, htmltext)
htmltext = re.sub(pttn, rpl, htmltext)
# </div> 之前添加空行
pttn = r'</div>'
rpl = r'\n\n</div>'
re.findall(pttn, htmltext)
htmltext = re.sub(pttn, rpl, htmltext)
# <p... 之前添加空行
pttn = r'<p'
rpl = r'\n\n<p'
re.findall(pttn, htmltext)
htmltext = re.sub(pttn, rpl, htmltext)
fileSave = open(path+target_filename, "w")
fileSave.write(htmltext)
print(htmltext)
複制
六、逐行送出 DeepL API Pro 進行翻譯
将清理過的 html 交給以下腳本,逐行送出給 DeepL 翻譯,并傳回。
為了友善起見,path 和 source_filename 以及 target_filename 都單獨指定。
lines 是 source_filename 的内容 new_lines 是将要放到 target_filename 中的内容 startline 是 “從哪一行開始送出 DeepL 翻譯” endline 是 “到哪一行開始結束送出 DeepL 翻譯”。代碼如下:
import re
import requests
auth_key = "<your DeepL API Pro authentication key>" # 注意,要訂閱的是 DeepL API Pro
target_language = "ZH" ## 當然,你可以将目智語言設定成任何 DeepL 支援的語言
path = "John Law/" # 檔案夾名稱末尾得有 /
source_filename = "index2.html" # 上一步生成的檔案,成為這一步的 “源檔案”
target_filename = "index3.html"
def translate(text):
result = requests.get(
"https://api.deepl.com/v2/translate",
params={
"auth_key": auth_key,
"target_lang": target_language,
"text": text,
"tag_handling": "xml", # 這個參數確定 DeepL 正确處理 html tags
},
)
return result.json()["translations"][0]["text"]
def add_language_tag_en(html):
pttn = re.compile(r'^<(.*?) class="(.*?)">', re.M)
rpl = r'<\1 class="\2 en">'
re.findall(pttn, html)
html = re.sub(pttn, rpl, html)
return html
def add_language_tag_cn(html):
pttn = re.compile(r'^<(.*?) class="(.*?)">', re.M)
rpl = r'<\1 class="\2 cn">'
re.findall(pttn, html)
html = re.sub(pttn, rpl, html)
return html
lines = open(path+source_filename, "r").readlines()
new_lines = []
line_count = 0
startline = 16
endline = 4032
for line in lines:
line_count += 1
if line_count < startline or line_count > endline or line.strip() == '':
new_lines.append(line)
print(line)
continue
succeeded = False
while not succeeded:
# 以下比較粗暴的 try... except,用來防止執行過程中出現 DeepL 連接配接錯誤而導緻翻譯任務中斷……
try:
line_translated = translate(line)
# 以下一行確定将傳回的字元串轉換成一整行,而非含有 \n 的多行文本
line_translated = line_translated.replace("\n", "")
succeeded = True
except:
succeeded = False
if line.strip() == line_translated.strip():
#傳回的字元串與原字元串相同,說明 html tag 之間的内容無需翻譯
new_lines.append(line)
print(line)
else:
line = add_language_tag_en(line)
line_translated = add_language_tag_cn(line_translated)
new_lines.append(line)
print(line)
new_lines.append(line_translated)
print(line_translated)
with open(path+target_filename, 'w') as f:
f.write("\n".join(new_lines))
複制
七、結果展示
1、運作代碼之後,會自動讀取待翻譯的檔案,然後進行翻譯,如下圖所示:
2、運作完程式之後,可以得到想要的結果,如下圖所示:
八、總結
大家好,我是Python進階者。這篇文章主要給大家介紹了使用Python腳本調用DeepL API Pro進電子書的行中英文自動翻譯的方法,代碼親測可行,歡迎大家積極嘗試,下次再遇到需要自動翻譯的時候,不妨調用下這個API,興許事半功倍呢!
------------------- End -------------------