最近、英語学習をはじめました。
その際に英作文の添削をしてもらっているため、後で日本語のみで英作文をしたいと思い至りました。
そこで、添削がかかった文章のPDFを翻訳し、日本語のみのスクリプトを作成するプログラムがあったら便利なのではと思い、実際に作ってみました。
その際にPDF関連のライブラリなど学びが多かったのでシェアいたします。
実装
from googletrans import Translator
from pdfminer.pdfpage import PDFPage
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
import pathlib
import re
# PDFファイルのパスを取得
p_temp = pathlib.Path('./files').glob('*.pdf')
# ファイル名をリストで取得
temps = [p.name for p in p_temp]
# Layout Analysisのパラメーターを設定
laparams = LAParams()
# 共有リソースを格納するPDFリソースマネージャーオブジェクトを作成
resource_manager = PDFResourceManager()
# 翻訳のオブジェクト作成
tr = Translator(service_urls=['translate.googleapis.com'])
def interpreter_pdf(input_file, output_file):
"""PDFファイルのテキストデータを抽出し、テキストファイルに出力する関数
Args:
input_file (_type_): 読み込むPDFファイル (io.BufferedReader)
output_file (_type_): 出力先ファイル (io.TextIOWrapper)
"""
# テキストに変換
device = TextConverter(resource_manager, output_file, laparams=laparams)
# ページの内容を処理するためのPDFインタプリタオブジェクトを作成
interpreter = PDFPageInterpreter(resource_manager, device)
# ドキュメントに含まれる各ページを処理
for page in PDFPage.get_pages(input_file):
interpreter.process_page(page)
# ファイルを閉じる
output_file.close()
def translate_file(w_list):
"""PDFファイルから作成したテキストファイルを翻訳し、リストに格納する処理
Args:
w_list (_type_): 翻訳後のテキストを格納するリスト (list)
Returns:
_type_: list
"""
# PDFからテキストデータのみ書き込んだファイルを読み込む
with open(f"./txt/{f_name}.txt") as f:
# ファイルを行数分リストに格納
l_strip = [s.strip() for s in f.readlines()]
for strip in l_strip:
# 行に英字が存在する場合
if re.search(r"[a-zA-Z]", strip):
# 英語文字列をリストに格納
# w_list.append(strip)
# 英語を翻訳する
result = tr.translate(strip, dest="ja")
# 翻訳語の文字列をリストに格納
w_list.append(f"{result.text}\n")
f.close()
return w_list
def distinct_list(w_list):
"""リストの重複を取り族関数
Args:
w_list (_type_): 翻訳後のテキストを格納しているリスト (list)
"""
with open(f"./txt/{f_name}.txt", 'w') as f:
# 重複を除去したリストをファイルに書き込む
f.write('\n'.join(list(dict.fromkeys(w_list))))
f.close()
# PDFファイル数分繰り返し
for temp in temps:
# ファイル名称部分のみの文字列に置き換える
f_name = temp.replace('.pdf', '')
# PDFファイル読み込み
input_file = open(f"./files/{f_name}.pdf", 'rb')
# txtファイルでの出力先ファイル
output_file = open(f"./txt/{f_name}.txt", 'w')
# PDFファイルを処理する関数を呼び出し
interpreter_pdf(input_file, output_file)
# 翻訳前後のテキストをリストにする関数の呼び出し
w_list = translate_file(w_list=[])
# リストの重複を除去する関数の呼び出し
distinct_list(w_list)
まずは、pathlib
ライブラリを使用して、PDFファイルのパスを取得します。その後、ファイル名をリストで格納しました。
なぜ、こんなことをしているのかというと、PDFファイル分処理をループしたいという意図もありますが、翻訳したファイルの名前もPDFファイルと合わせたかったからです。
続くLAParams
とPDFResourceManager
はPDFからテキストのみを読み込むのに必要となるライブラリです。
※ 詳細は、記事の最下部の参考文献を参照ください。
続くTranslator
は翻訳をするためのライブラリです。
これで処理の準備は整ったのでメインの処理の解説に移ります。
PDFファイルをテキストデータにする
まずは、PDFファイルと出力先のファイルを定義します。
PDFの場合、バイナリーデータのためモードはrb
で読み込みます。
そして、PDFのデータをテキストに変換するためTextConverter
を作成します。
さらに続けて、PDFPageInterpreter
を作成し、PDFの内容を処理する準備をします。
続くfor文でようやくPDFの内容を処理します。
ページ分ループを回しPDFファイルの内容を処理内容に従い、出力先のファイルに書き込んでいきます。
翻訳処理
次に翻訳処理ですが、PDFから抽出したテキストデータを書きこんでいるテキストファイルのデータを読み込み、それを1行ずつ翻訳し、リストに格納するという処理を行います。
まずは、リスト内包表記でファイルの行数分をリストに格納します。
その後、そのリストをループさせ英字が含まれている場合のみ、翻訳し、翻訳後のテキストをリストに格納する処理を行いました。
ここでは翻訳するためにTranslator
のtranslate()
メソッドを使用し、引数に翻訳したい文字列と、翻訳後の言語を指定します。
そして、関数の返り値として翻訳後のテキストリストを返すようにします。
最後に、私の個人的に必要となった処理として添削前と添削後の英文で重複があったため、重複をなくす処理を実装しています。
このようにすると、以下のように日本語訳のスクリプトができ、これを利用して、日本語のみで英作をするという復習が可能となりました。
ただ、PDF内で改行があると単語として訳されるのが難点でした。
また、翻訳の精度もところどころ悪いので、大枠はこの処理を使用して、細かい部分は手を入れるということになりそうです。
面倒ですが、それでも1からスクリプトを作成するより多少、時短になるのではないでしょうか。