DeepL翻訳をPythonから使う(第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

 

翻訳リクエストを受け付けたファイルの document_iddocument_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_keytarget_lang の指定がかなりトリッキーですね。
filesの項目指定にはいくつかの方法があり、2項tupleの場合、
1項目はファイル名、2項目はオブジェクトです。
文字列を指定する場合は、このような書き方になります。
この他のやり方として、auth_keytarget_lang は、
最初の文字列翻訳と同様、data(dict形式)の方に格納して、
requests.post()に data と files を両方渡す方法もあります。

ステップ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(翻訳終了)の4つです。
translating の場合は、処理の残り時間の目安も返却されます。
変数 document_iddocument_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のsub:翻訳処理状況の取得
    ”’
    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()

 

3種類のAPI呼び出しは似たような処理ですが、
「curlコマンドをPythonで書く」というテーマのために
あえてまとめずに冗長な書き方をしています。

以上、この記事では:

・DeepLのAPIを使用して、ファイルを翻訳しました。
・curlコマンドの内容をPythonで表現してプログラムを作成しました。

お読みいただきありがとうございます。