從Python使用DeepL翻譯(第2回)

在本篇文章中,將介紹 DeepL 翻譯 API 使用方法的第 2 回:檔案翻譯。(第 1 回請見此處)
※本篇內容以前提具備 Python 與 Linux 的基礎知識為基礎。
文字檔案翻譯
暖身結束後,接下來讓我們嘗試進行檔案翻譯。
這需要結合 3 個 API 呼叫。
請準備一個包含適當日文內容的文字檔 test.txt。
我們將構思一個將其翻譯為英文(美式)並儲存為 test.trans.txt 的機制。
步驟 1:上傳原始語言檔案
在向 DeepL 伺服器發送翻譯請求時,需指定原始語言檔案。
$ curl https://api.deepl.com/v2/document \
$ -F file=@test.txt \
$ -F auth_key=${auth_key} \
$ -F target_lang=en-us
伺服器會以 JSON 格式回傳已受理檔案的 document_id 與 document_key。
將發送前的處理過程以 Python 編寫如下:
url = 'https://api.deepl.com/v2/document'
files = dict()
files['file'] = open(fn, 'rb')
files['auth_key'] = (None, get_key())
files['target_lang'] = (None, 'en-us')
res = requests.post(url, files=files)
auth_key 與 target_lang 的指定方式相當棘手。
files 的項目指定有幾種方法,若是 2 項 tuple,
第 1 項為檔案名稱,第 2 項為物件。
若要指定字串,則需採用這種寫法。
此外,另一種做法是將 auth_key 與 target_lang
如同最初的字串翻譯一樣,存放在 data(dict 格式)中,
並將 data 與 files 同時傳遞給 requests.post()。
步驟 2:取得翻譯處理狀態
查詢翻譯中檔案的翻譯狀態:
$ document_id=[documentID]
$ document_key=[documentKey]
$ curl https://api.deepl.com/v2/document/${document_id} \
$ -d auth_key=${auth_key} \
$ -d document_key=${document_key}
狀態共有 4 種:queued(已受理)、translating(翻譯中)、
error(發生翻譯錯誤)、done(翻譯完成)。
若為 translating,還會回傳預估的剩餘處理時間。
假設已完成變數 document_id 與 document_key 的賦值,
將發送前的處理過程以 Python 編寫如下:
url = f'https://api.deepl.com/v2/document/{document_id}'
data = dict()
data['auth_key'] = get_key()
data['document_key'] = document_key
res = requests.post(url, data=data)
步驟 3:下載目標語言檔案
當翻譯狀態變為 done 後,即可下載檔案:
$ curl https://api.deepl.com/v2/document/${document_id}/result \
$ -d auth_key=${auth_key} \
$ -d document_key=${document_key} > test.trans.txt
下載僅限一次。
翻譯結果已重新導向(儲存)至 test.trans.txt。
發送前的處理過程若以 Python 編寫,如下所示:
url = f'https://api.deepl.com/v2/document/{document_id}/result'
data = dict()
data['auth_key'] = get_key()
data['document_key'] = document_key
res = requests.post(url, data=data)
檔案翻譯處理
最後,將上述處理過程串聯起來。
由於步驟 2 僅會回傳翻譯進度,
因此需要針對該結果進行等待處理。基本上:
・若為 translating,則根據剩餘時間 seconds_remaining 的
秒數進行 sleep,然後再次確認進度。
・若出現 done 或 error,則跳出迴圈。
上述處理過程若以 Python 編寫,如下所示:
import requests
import json
from time import sleep
def get_key():
return open(‘key.txt’).read().rstrip()
def upload_src(fn):
”’
檔案翻譯步驟 1:上傳原始語言檔案
”’
url = ‘https://api.deepl.com/v2/document’
files = dict()
files[‘file’] = open(fn, ‘rb’)
files[‘auth_key’] = (None, get_key())
files[‘target_lang’] = (None, ‘en-us’)
res = requests.post(url, files=files)
res_status = res.status_code # 若成功則為 200(目前未使用)
res_text = res.text
res_data = json.loads(res_text)
document_id = res_data[‘document_id’]
document_key = res_data[‘document_key’]
return document_id, document_key
def get_trans_status(document_id, document_key):
”’
步驟 2 之子步驟:取得翻譯處理狀態
”’
url = f’https://api.deepl.com/v2/document/{document_id}’
data = dict()
data[‘auth_key’] = get_key()
data[‘document_key’] = document_key
res = requests.post(url, data=data)
res_status = res.status_code # 若成功則為 200(目前未使用)
res_text = res.text
res_data = json.loads(res_text)
return res_data
def check_proceeding(document_id, document_key):
”’
檔案翻譯步驟 2:等待翻譯處理
”’
while True:
res = get_trans_status(document_id, document_key)
status = res[‘status’]
print(f’status: {status}’, flush=True)
seconds_remaining = 0
if status == ‘done’ or status == ‘error’:
break
elif status == ‘translating’:
if ‘seconds_remaining’ in res:
seconds_remaining = int(res[‘seconds_remaining’])
# 錯誤迴避
if seconds_remaining <= 0:
seconds_remaining = 10
else: # queued 等
pass
print(f’…waiting for (another) {seconds_remaining}s’, flush=True)
sleep(seconds_remaining)
return status
def download_tgt(fn, document_id, document_key):
”’
檔案翻譯步驟 3:下載目標語言檔案
”’
url = f’https://api.deepl.com/v2/document/{document_id}/result’
data = dict()
data[‘auth_key’] = get_key()
data[‘document_key’] = document_key
res = requests.post(url, data=data)
res_status = res.status_code # 若成功則為 200(目前未使用)
tgt_bin = res._content
with open(fn, ‘w’, encoding=’utf-8′) as f:
print(tgt_bin.decode(‘utf-8’), end=”, file=f)
def main():
fn_src = ‘test.txt’
fn_tgt = fn_src.replace(‘.txt’, ‘.trans.txt’)
print(f’fn_src: {fn_src}’)
print(f’fn_tgt: {fn_tgt}’)
print(f'uploading: {fn_src}')
document_id, document_key = upload_src(fn_src)
status = check_proceeding(document_id, document_key)
if status == 'done':
print(f'downloading: {fn_tgt}')
download_tgt(fn_tgt, document_id, document_key)
if __name__ == '__main__':
main()
這三種 API 呼叫的處理方式相似,
但為了符合「以 Python 編寫 curl 指令」的主題,
特意不進行合併,採用了較為冗長的寫法。
以上,本文介紹了:
・使用 DeepL API 進行了檔案翻譯。
・將 curl 指令的內容轉換為 Python 程式碼並進行了編寫。
感謝您的閱讀。





