DeepL API × Python でコピーした英文を自動翻訳

# 1. 概要
誰でもこんな経験したことあると思います．
1. DeepLで翻訳しながら英語の論文を読む
2. 面倒になりPDFごといい感じに翻訳してくれるサービスを探す
3. どのサービスもフォーマットが崩れたり，少しずつしかできなかったりで微妙
4. 結局翻訳したい部分をDeepLにコピペで翻訳してもらう(2~4を無限ループ)

DeepLへのコピペもPDFの端で改行されてしまい，おかしな翻訳になることもしばしば．ということで，
<font color="Red">今回の目標は，英文をコピーしたはずがいつの間にか和文になってる！！</font>
です．

# 2. 本編
今回はこんな流れで進めていきます．
```mermaid
graph TD;
    クリップボードのコピーを監視-->改行やスペース等をいい感じに整える;
    改行やスペース等をいい感じに整える-->DeepLで英文を和文に翻訳;
    DeepLで英文を和文に翻訳-->和文をクリップボードにコピー;
```
## 2-1. クリップボードのコピーを監視
クリップボード関連はpyperclipというライブラリを使えば簡単に操作できます．
pyperclipについては以下のサイトを参考にしました．
[Python, pyperclipでクリップボードを操作（コピー、ペースト、監視）](https://note.nkmk.me/python-pyperclip-usage/)
まずはpipでインストール．
```
pip install pyperclip
```
waitForNewPasteメソッドを使えばクリップボードの更新を監視することができます．また，引数に待機時間を設定することができます．以下の実装だと300秒(5分間)クリップボードの更新がなかったらプログラムが終了するようになっています．
```python
import pyperclip

while True:
    try:
        # コピーされた英文のテキスト
        text = pyperclip.waitForNewPaste(300)
    except pyperclip.PyperclipException:
        print("5分間入力がないため終了します")
        break
    except KeyboardInterrupt:
        print("終了します")
        break
```
## 2-2. 改行やスペースなどをいい感じに整える
コピーした英文をそのままDeepLにつっこむと，PDFの端で改行されていたり，文中の数式で不自然な改行が入っていたりします．
改行をスペースにするだけなら，
```python
text.replace("\n", " ")
```
とするだけでいいのですが，本当に改行している部分では改行したままにしておきたいです．
ということで，改行後の一文字目が大文字かそれ以外かで判断することにしました．具体的には，改行後の一文字目が大文字ならそのまま，それ以外なら改行をスペースに置換するという処理を行いました．
```python
import re

# 改行のインデックスを取得
new_line_list = [i.start() for i in re.finditer("\n", text)]
# 改行後に大文字以外があるかどうか
replace_index = []
# 改行後に大文字以外がある場合、そのインデックスをリストに追加
for i in new_line_list:
    # 改行が最後の文字の場合はスキップ
    if len(text) <= i+1:
        continue
    if not text[i+1].isupper():
        replace_index.append(i)
# 改行後に大文字以外がある場合、改行をスペースに置き換える
new_text = ""
st = 0
for i in replace_index:
    new_text += text[st:i] + " "
    st = i+1
new_text += text[st:]
```
## 2-3. DeepLで英文を和文に翻訳
DeepL APIを使うには[DeepL APIへの登録](https://www.deepl.com/ja/pro-api?cta=header-pro-api/)が必要です．
登録後は，クレジットカード情報を入力することで，認証キーを発行できます．この後に使うので発行できたらコピーしておいてください．
[DeepL APIをPythonで使うための公式のクライアントライブラリ](https://github.com/DeepLcom/deepl-python)があります．これをpipでインストールします．
```
pip install --upgrade deepl
```
このライブラリを使えば翻訳自体はとても簡単にできます．
auth_keyには先ほど発行した認証キーを設定してください．
DeepL APIとdeeplライブラリに関しては以下のサイトを参考にしました．
[python で deepL API を使ってみる](https://qiita.com/Negelon/items/ad0e47d15372e0d82ca9)
```python
import deepl

auth_key = "発行した認証キー"
# 英語から日本語に翻訳
source_lang = "EN"
target_lang = "JA"

# 翻訳
translator = deepl.Translator(auth_key)
result = translator.translate_text(new_text, source_lang=source_lang, target_lang=target_lang)
```
## 2-4. 和文をクリップボードにコピー
2-1で使用したpyperclipのcopyメソッドを使うだけです．
```python
# 翻訳結果をクリップボードにコピー
pyperclip.copy(result.text)
```
# 3. まとめ
- 今回やったこと
    - pyperclipでクリップボード周りのいろいろ
    - DeepL APIで自動翻訳

今回実装したコードを以下に載せておきます．
また，[自身のGitHub](https://github.com/kenshin-627/AutoDeepL)でも公開しています．
```python
import pyperclip
import deepl
import settings
import re

auth_key = settings.AUTH_KEY
source_lang = "EN"
target_lang = "JA"

while True:
    try:
        # コピーされた英文のテキスト
        text = pyperclip.waitForNewPaste(300)
        # 改行のインデックスを取得
        new_line_list = [i.start() for i in re.finditer("\n", text)]
        # 改行後に大文字以外があるかどうか
        replace_index = []
        # 改行後に大文字以外がある場合、そのインデックスをリストに追加
        for i in new_line_list:
            # 改行が最後の文字の場合はスキップ
            if len(text) <= i+1:
                continue
            if not text[i+1].isupper():
                replace_index.append(i)
        # 改行後に大文字以外がある場合、改行をスペースに置き換える
        new_text = ""
        st = 0
        for i in replace_index:
            new_text += text[st:i] + " "
            st = i+1
        new_text += text[st:]
        # 翻訳
        translator = deepl.Translator(auth_key)
        result = translator.translate_text(new_text, source_lang=source_lang, target_lang=target_lang)
        # 翻訳結果をクリップボードにコピー
        pyperclip.copy(result.text)
    except pyperclip.PyperclipException:
        print("5分間入力がないため終了します")
        break
    except KeyboardInterrupt:
        print("終了します")
        break
```
# 4. 終わりに
翻訳が結構ストレスだったので，適当に作ってみたら簡単&便利すぎて感動しました．
ライブラリを作ってくれている先人に感謝！
# 参考文献
[Python, pyperclipでクリップボードを操作（コピー、ペースト、監視）](https://note.nkmk.me/python-pyperclip-usage/)
[python で deepL API を使ってみる](https://qiita.com/Negelon/items/ad0e47d15372e0d82ca9)
[DeepL APIをPythonで使うための公式のクライアントライブラリ](https://github.com/DeepLcom/deepl-python)