TL;DR
pdfminer3kを用いてpdfから単語一覧と対応するリスト番号を抽出します。
成果物
https://github.com/musaprg/celese_tools/blob/master/pour_words_from_pdf/pour.py
pdfminer3kとは
今回使用したのは、pdfファイルから情報を抽出することのできるpdfminer3k
というライブラリです。正確には、pdfminer
というライブラリのPython3対応バージョンです。
これを使うと、htmlのスクレイピングのような要領で、pdfから情報を簡単に抽出することができます。
手順
インストール
PyPIに登録されてるので、サクサクとインストールできます。
pip install pdfminer3k
抽出&CSV出力
こちらのサイトに掲載されているコードを参考にさせていただきました。
from argparse import ArgumentParser import re from pdfminer.pdfparser import PDFParser from pdfminer.pdfparser import PDFDocument from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.pdfparser import PDFPage from pdfminer.pdfdevice import PDFDevice from pdfminer.converter import PDFPageAggregator from pdfminer.converter import TextConverter from pdfminer.layout import LAParams from pdfminer.layout import LTTextBoxHorizontal def main(path_to_pdf): fp = open(path_to_pdf, 'rb') parser = PDFParser(fp) document = PDFDocument() parser.set_document(document) password="" document.set_parser(parser) document.initialize(password) rsrcmgr = PDFResourceManager() laparams = LAParams() device = PDFPageAggregator(rsrcmgr, laparams=laparams) intepreter = PDFPageInterpreter(rsrcmgr, device) pages = list(document.get_pages()) words = [] numbers = [] for i,page in enumerate(pages): print("---------page %d----------" % i) intepreter.process_page(page) layout = device.get_result() for l in layout: if isinstance(l, LTTextBoxHorizontal): texts = re.sub(r"\s+", " ", l.get_text()) texts = texts.strip("\n") texts = texts.split(" ") texts = [t for t in texts if t != ''] numbers = numbers + [int(t) for t in texts if t.isdigit()] words = words + [t for t in texts if not t.isdigit()] print(numbers) print(words) save_as_csv(words, numbers) def save_as_csv(words, numbers): import csv with open("output.csv", "w") as f: writer = csv.writer(f, lineterminator='\n') header = [] header.append("word") header.append("list_number") writer.writerow(header) for a,b in zip(words, numbers): writer.writerow([a,b]) if __name__ == '__main__': parser = ArgumentParser( description='Unpacking word lists from pdf files.') parser.add_argument("path_to_pdf", type=str, help='Path to pdf files') args = parser.parse_args() main(args.path_to_pdf)
すると、以下のpdfから、単語と、その単語が属するリスト番号がペアになってcsvとして吐きだされます。
https://github.com/musaprg/celese_tools/blob/master/pour_words_from_pdf/awl.pdf
pdfminer3kを使用する上での注意事項
pdfは、htmlと違ってあまりキレイに構造化されていません。
レイアウト重視のpdfの場合は、抽出する際に、予想される順序で抽出がされない場合がほとんどです。
今回は、抽出されたテキストを
- 空白や改行文字を除去する
- 単語や数字ごとに分割して配列に格納
- 配列を全走査して数字と文字の配列にそれそれ分割
- csv出力時にzipで結合する
といった感じでうまく処理しています。
これは、pdfによるので、まずは対話シェル等で、どのように抽出されるかをチェックしてから、事後処理の方法を検討するとうまくいくと思います。
参考文献
https://sitest.jp/blog/?p=12170 http://cartman0.hatenablog.com/entry/2017/08/26/022957