目標
PDFなどをコピペした英文を投げたら自動で改行調整をし、日本語訳を返すコードをPythonで書いたのでそれをdiscord botに導入してみる。
注意
seleniumが並列化できていないため、飽くまで個人用です。
(複数人で共有するとタブクラッシュするかも)
メリット
discord botに翻訳を返してもらえるメリットを挙げると
-記録が残せる
-Shaperを使うのと違ってタブが増殖しない
翻訳コード
とりあえずコードを載せる。
import time
from selenium import webdriver
import chromedriver_binary
from xml.sax.saxutils import unescape
def deepl(text):
text = ' '.join(text.splitlines())
options = webdriver.ChromeOptions()
options.add_argument('--headless')
url="https://www.deepl.com/ja/translator"
driver =webdriver.Chrome(options=options)
driver.get(url)
insec="#dl_translator > div.lmt__text > div.lmt__sides_container > div.lmt__side_container.lmt__side_container--source > div.lmt__textarea_container > div.lmt__inner_textarea_container > textarea"
driver.find_element_by_css_selector(insec).send_keys(text)
outsec="#target-dummydiv"
while 1:
Outputtext = driver.find_element_by_css_selector(outsec).get_attribute("innerHTML")
if Outputtext != "\r\n" :
break
time.sleep(1)
driver.quit
Outputtext=Outputtext.rstrip("\r\n")
Outputtext=unescape(Outputtext)
return Outputtext
英文の改行コードを空白にする
PDFをコピペすると勝手に改行されてイライラするのでとりあえず改行を消して半角空白にする。
text = ' '.join(text.splitlines())
seleniumを使ってDeeplにアクセス
options = webdriver.ChromeOptions() #事前にimportしたchromeのwebdriverを使う
options.add_argument('--headless') #実行の際Chromeを開かないよう指定
url="https://www.deepl.com/ja/translator" #DeepL(ja)のURL
driver =webdriver.Chrome(options=options) #driverを指定
driver.get(url) #DeepLにアクセス
webdriver.ChromeOptionsについては@hanzawak様のこの記事を参照するといいかも。
DeepLに英文を入れる
手法1
https://www.deepl.com/translator#en/ja/英文
にアクセスすることで翻訳を行う。
問題点
例えば文章中にX/Yなどがあるとする。そしたらURLにアクセスする際これをスラッシュと認識して英文が/で途切れてしまう。(%2Fでも同じだった)
手法2
DeepLのサイト内で入力を行う。
まずDeepL内で文入力のsectorを探した。すると
# dl_translator > div.lmt__text > div.lmt__sides_container > div.lmt__side_container.lmt__side_container--source > div.lmt__textarea_container > div.lmt__inner_textarea_container > textarea
にあることが分かった。
ここをfindしてtextを入れる。
insec="#dl_translator > div.lmt__text > div.lmt__sides_container > div.lmt__side_container.lmt__side_container--source > div.lmt__textarea_container > div.lmt__inner_textarea_container > textarea"
driver.find_element_by_css_selector(insec).send_keys(text)
訳文を抽出する
上と同様にtextareaを見つけて抽出しようとしたができなかった。
そのため別のところを探すと
#target-dummydiv のinnerHTMLにあることが分かった。
※訂正
"#dl_translator > div.lmt__text > div.lmt__sides_container > div.lmt__side_container.lmt__side_container--target > div.lmt__textarea_container > div.lmt__inner_textarea_container > textarea"
の"value"にありました
あとはここをfindしてinnerHTML valueを取り出す。
ここで翻訳が終わっていないと"\r\n"が取り出されるため、それ以外のものが取れるまで1秒ごとに操作を行う。
outsec="#dl_translator > div.lmt__text > div.lmt__sides_container > div.lmt__side_container.lmt__side_container--target > div.lmt__textarea_container > div.lmt__inner_textarea_container > textarea"
while 1:
Outputtext = driver.find_element_by_css_selector(outsec).get_attribute("value")
if Outputtext != "" :
break
time.sleep(1)
driver.quit
最後に末尾の"\r\n"を取って訳文Outputtextを獲得...と行きたいところだが、ここでHTML上では特殊文字について、例えば">"は"> ;"で書かれているからそれを普通の記号に変換するためにunescapeに通す。
Outputtext=unescape(Outputtext)
return Outputtext
これで翻訳については完了。
あとはこれをBOTに入れるだけである。
BOT作成
BOTについては基本的な動作を行うだけなため@1ntegrale9様のこの記事を参考にするといいかも。
またseleniumとchromedriver_binaryをHerokuで使う際、Setting->Buildpacksに以下の二つのURLを入れることに注意。
https://github.com/heroku/heroku-buildpack-google-chrome.git
https://github.com/heroku/heroku-buildpack-chromedriver.git
import translate.py
import discord
import asyncio
TOKEN = '自分のtokenを入れてね'
client = discord.Client()
@client.event
async def on_message(message):
author=message.author
dm=await author.create_dm()
if message.channel==dm:
honyaku = translate.deepl(message.content)
await message.channel.send(honyaku)
client.run(TOKEN)
関数内を簡単に説明すると上から
メッセージ(英文)が送ると
まず送ってきた人をauthorとする。
そしてその人とのDMをdmとする。
そしてその人の送ってきた文章がDMからなら実行し、それ以外なら実行しない(大量のグループ内で起動すると迷惑になりそうなので)
あとはtranslate.py内の翻訳関数に通して出力をDMに再び返す。
といった感じである。
async def on_message(message):
author=message.author #メッセージの送り主を特定
dm=await author.create_dm() #送り主のDMを特定
if message.channel==dm: #送ってきたチャンネルがDMか判断
if __name__ == '__main__':
honyaku = deepl2.deepl(message.content) #翻訳関数実行
await message.channel.send(honyaku) #送り主のDMに返す