Python3(venv)でDeepL APIを使って翻訳してみる


■Pythnの仮想環境である、venvのためには「python3.11-venv」が必要

```
$ lsb_release -d 2>/dev/null
Description:    Debian GNU/Linux 12 (bookworm)
```

```
$ dpkg -l | awk '$1 ~ /ii/ && $2 ~ /^python3/{print $2,$3}' | column
python3 3.11.2-1+b1                             python3-gi-cairo 3.42.2-3+b1                    python3-pysimplesoap 1.16.2-5
python3-apt 2.6.0                               python3-httplib2 0.20.4-3                       python3-reportbug 12.0.0
python3-brlapi:amd64 6.5-7+deb12u1              python3-idna 3.3-1+deb12u1                      python3-requests 2.28.1+dfsg-1
python3-cairo:amd64 1.20.1-5+b1                 python3-lib2to3 3.11.2-3                        python3-setuptools-whl 66.1.1-1
python3-certifi 2022.9.24-1                     python3-libvirt 9.0.0-1                         python3-six 1.16.0-4
python3-chardet 5.1.0+dfsg-2                    python3-libxml2:amd64 2.9.14+dfsg-1.3~deb12u1   python3-speechd 0.11.4-2
python3-charset-normalizer 3.0.1-2              python3-louis 3.24.0-1                          python3-uno 4:7.4.7-1+deb12u5
python3-debconf 1.5.82                          python3-minimal 3.11.2-1+b1                     python3-urllib3 1.26.12-1
python3-debian 0.1.49                           python3-pip-whl 23.0.1+dfsg-1                   python3-venv 3.11.2-1+b1
python3-debianbts 4.0.1                         python3-pkg-resources 66.1.1-1                  python3-xdg 0.28-2
python3-distro 1.8.0-1                          python3-pyatspi 2.46.0-2                        python3.11 3.11.2-6+deb12u4
python3-distutils 3.11.2-3                      python3-pycurl 7.45.2-3                         python3.11-minimal 3.11.2-6+deb12u4
python3-gi 3.42.2-3+b1                          python3-pyparsing 3.0.9-1                       python3.11-venv 3.11.2-6+deb12u4
```
■仮想環境にrequestsライブラリを入れ、普通のWebページを持ってくる
　※w3mでhtmlを変換

```
$ python3 -m venv deepl
$ source deepl/bin/activate
(deepl) $ pip install requests
(deepl) $ pip freeze > requirements.txt
(deepl) $ cat requirements.txt
certifi==2024.8.30
charset-normalizer==3.4.0
idna==3.10
requests==2.32.3
urllib3==2.2.3

(deepl) $ cat sample.py
import requests

url = "http://google.com"
response = requests.get(url)

print(response.text)

(deepl) $ python3 sample.py | w3m -dump -T text/html | head -1
labunix's blog
```
■DeepLの無料プランでAPIキーを取得
　※クレジットカードの登録は必須。**APIは公開しないように注意**

```https://www.deepl.com/ja/your-account/keys```

■APIを使って翻訳してみる

```
(deepl) $ sed -e 's/=.*/={your_api_key}/' .deepl_api.txt
DEEPL_API_KEY={your_api_key}
```

```
(deepl) $ chmod 400 .deepl_api.txt
```

```(deepl) $ cat deepl_tr.py 
import requests

def load_api_key(file_path):
    """
    ファイルからAPIキーを読み取る関数。
    
    :param file_path: APIキーが保存されているファイルのパス
    :return: 読み取ったAPIキー
    """
    try:
        with open(file_path, "r") as file:
            for line in file:
                if line.startswith("DEEPL_API_KEY="):
                    return line.strip().split("=")[1]
    except FileNotFoundError:
        print("Error: APIキーのファイルが見つかりません。")
        return None
    except Exception as e:
        print(f"Error: {e}")
        return None

def deepl_translate(api_key, text, target_lang="JA", source_lang="EN"):
    """
    DeepLのAPIを使用してテキストを翻訳する関数。
    
    :param api_key: DeepL APIキー
    :param text: 翻訳するテキスト
    :param target_lang: 翻訳先の言語（デフォルトは日本語）
    :param source_lang: 翻訳元の言語（デフォルトは英語）
    :return: 翻訳されたテキスト
    """
    url = "https://api-free.deepl.com/v2/translate"  # 無料プラン用のURL。有料プランは "https://api.deepl.com/v2/translate"
    headers = {
        "Content-Type": "application/x-www-form-urlencoded"
    }
    data = {
        "auth_key": api_key,
        "text": text,
        "target_lang": target_lang,
        "source_lang": source_lang
    }

    response = requests.post(url, headers=headers, data=data)
    
    if response.status_code == 200:
        translated_text = response.json()["translations"][0]["text"]
        return translated_text
    else:
        print(f"Error: {response.status_code}")
        print(response.text)
        return None

def process_file(api_key, input_file, output_file):
    """
    英文のテキストファイルを翻訳し、原文と翻訳文を出力する関数。
    
    :param api_key: DeepL APIキー
    :param input_file: 入力ファイルのパス
    :param output_file: 出力ファイルのパス
    """
    try:
        with open(input_file, "r", encoding="utf-8") as infile:
            lines = infile.readlines()
        
        results = []
        for line in lines:
            line = line.strip()
            if line:  # 空行をスキップ
                translated = deepl_translate(api_key, line)
                if translated:
                    results.append(f"Original: {line}\nTranslated: {translated}\n")
        
        with open(output_file, "w", encoding="utf-8") as outfile:
            outfile.writelines(results)
        
        print(f"翻訳が完了しました: {output_file}")
    except FileNotFoundError:
        print(f"Error: 入力ファイルが見つかりません: {input_file}")
    except Exception as e:
        print(f"Error: {e}")

# 使用例
if __name__ == "__main__":
    config_file_path = ".deepl_api.txt"  # APIキーを保存したファイルのパス
    input_file_path = "input.txt"   # 翻訳する英文のテキストファイル
    output_file_path = "output.txt" # 原文と翻訳文を保存するファイル

    API_KEY = load_api_key(config_file_path)

    if API_KEY:
        process_file(API_KEY, input_file_path, output_file_path)

```

■ジョブズ氏のスピーチの冒頭を翻訳

```
#Google翻訳では「たった３話。」。
#こういうときのために原文を残した。
```

おおまかには上手に翻訳できているが、訳文は「3つの話題に絞った」くらいにしてほしい。**できれば無料のAPIがある生成AIに渡したいところ**

```
#改行を入れることで、一文ごとにする
$ sed -e 's/\. /&\n/g' a > input.txt
```

```(deepl) $ python3 deepl_tr.py 
翻訳が完了しました: output.txt
```

```(deepl) $ cat output.txt 
Original: Thank You.
Translated: ありがとう。
Original: I am honored to be with you today for your commencement from one of the finest universities in the world.
Translated: 本日、世界でも有数の大学の卒業式にご一緒できることを光栄に思います。
Original: Truth be told I never graduated from college and this is the closest I’ve ever gotten to a college graduation.
Translated: 実を言うと、私は大学を卒業したことがなく、これが大学の卒業式に最も近いものだ。
Original: Today I want to tell you three stories from my life.
Translated: 今日は私の人生から3つの話をしたい。
Original: That’s it.
Translated: それだけだ。
Original: No big deal.
Translated: 大したことじゃない。
Original: Just three stories.
Translated: たった3階建てだ。
```