PDFスクレイピングよりテキストのみだったので座標とページ数を追加しCSVに保存できるように変更
良いところ
- Python
- 縦書きも取り込める
不便なところ
- 座標がfloatで細かい
- 行が違う場合もまとめて取ってしまう。line_marginで調整できそう。
- 取得できないテキストもある。pdf2txt.pyだと取れるので設定しだいかも。
インストール
pip install pdfminer
ソース
import sys import csv from pdfminer.converter import PDFPageAggregator from pdfminer.layout import LAParams, LTContainer, LTTextBox from pdfminer.pdfinterp import PDFPageInterpreter, PDFResourceManager from pdfminer.pdfpage import PDFPage # 再帰的にテキストボックス(LTTextBox)を探して、テキストボックスのリストを取得する。 def find_textboxes_recursively(layout_obj): # LTTextBoxを継承するオブジェクトの場合は1要素のリストを返す。 if isinstance(layout_obj, LTTextBox): return [layout_obj] # LTContainerを継承するオブジェクトは子要素を含むので、再帰的に探す。 if isinstance(layout_obj, LTContainer): boxes = [] for child in layout_obj: boxes.extend(find_textboxes_recursively(child)) return boxes # その他の場合は空リストを返す。 return [] # Layout Analysisのパラメーターを設定。縦書きの検出を有効にする。 laparams = LAParams(detect_vertical=True) # 共有のリソースを管理するリソースマネージャーを作成。 resource_manager = PDFResourceManager() # ページを集めるPageAggregatorオブジェクトを作成。 device = PDFPageAggregator(resource_manager, laparams=laparams) # Interpreterオブジェクトを作成。 interpreter = PDFPageInterpreter(resource_manager, device) csv_data = [] # ファイルをバイナリ形式で開く。 with open(sys.argv[1], "rb") as f: # PDFPage.get_pages()にファイルオブジェクトを指定して、PDFPageオブジェクトを順に取得する。 # 時間がかかるファイルは、キーワード引数pagenosで処理するページ番号(0始まり)のリストを指定するとよい。 for i, page in enumerate(PDFPage.get_pages(f), start=1): # ページを処理する。 interpreter.process_page(page) # LTPageオブジェクトを取得。 layout = device.get_result() # ページ内のテキストボックスのリストを取得する。 boxes = find_textboxes_recursively(layout) # テキストボックスの左上の座標の順でテキストボックスをソートする。 # y1(Y座標の値)は上に行くほど大きくなるので、正負を反転させている。 boxes.sort(key=lambda b: (-b.y1, b.x0)) for box in boxes: # ページ数、X座標、Y座標、テキスト csv_data.append([i, box.x0, box.y1, box.get_text().strip()]) with open("data.csv", "wt") as fw: writer = csv.writer(fw, lineterminator="\n") writer.writerows(csv_data)