通过Python使用DeepL翻译(第2回)

在本文中,我们将介绍DeepL翻译API使用方法的第2回,即文档翻译。(第1回请见此处)
※前提是具备Python和Linux的基础知识。

文本文件翻译

热身结束后,接下来让我们尝试文档翻译。
这需要结合三个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

 

已受理翻译请求的文件的 document_id 和 document_key,
会以json格式从服务器返回。
发送过程的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项目的指定有几种方法,如果是二项元组,
第一项是文件名,第二项是对象。
若指定字符串,则采用这种写法。
此外,auth_key 和 target_lang 也可以
和最初的文本翻译一样,存放在data(字典格式)中,
并将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}

 

状态共有四种: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
睡眠相应的秒数,然后再次确认进度。
・如果出现 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编写成了程序。

感谢您的阅读。