トミー PDFからテキスト出力してcsv化
No License Python
2022年05月05日
Copy Clone
# ファイル名 print_pdf_textboxes_csv.py
import sys
import csv
import os

from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LAParams, LTContainer, LTTextBox
from pdfminer.pdfinterp import PDFPageInterpreter, PDFResourceManager
from pdfminer.pdfpage import PDFPage

’’’
python print_pdf_textboxes_csv.py [pdfのパス]のようにコマンドプロンプトから実行する
’’’

# 再帰的にテキストボックス(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 = []

if len(sys.argv) == 1:
  print('パスを指定してください')
else:
  # 本来、パラメータがファイルパスであるかとか存在確認とかしないといけないが割愛
  pdfpath = sys.argv[1]
  base = os.path.splitext(pdfpath)[0]
  newpath = base + ".csv"

  # ファイルをバイナリ形式で開く
  with open(pdfpath, "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()])

  # 文字コードがUTF-8 With BOMだと、エクセルで開いたときに文字化けしません
  # テキストで開くと文字化けする・・・
  # BOM(byte order mark) Unicodeの符号化形式で符号化したテキストの先頭につける数バイトのデータのこと
  # encoding="utf_8_sig"とすることでBOM付きのUTF-8でCSVファイルを書き出すことが出来る
  with open(newpath, "wt", encoding="utf_8_sig") as fw:
      writer = csv.writer(fw, lineterminator="\n")
      writer.writerows(csv_data)
# ファイル名 print_pdf_textboxes_csv.py
import sys
import csv
import os

from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LAParams, LTContainer, LTTextBox
from pdfminer.pdfinterp import PDFPageInterpreter, PDFResourceManager
from pdfminer.pdfpage import PDFPage

’’’
python print_pdf_textboxes_csv.py [pdfのパス]のようにコマンドプロンプトから実行する
’’’

# 再帰的にテキストボックス(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 = []

if len(sys.argv) == 1:
  print('パスを指定してください')
else:
  # 本来、パラメータがファイルパスであるかとか存在確認とかしないといけないが割愛
  pdfpath = sys.argv[1]
  base = os.path.splitext(pdfpath)[0]
  newpath = base + ".csv"

  # ファイルをバイナリ形式で開く
  with open(pdfpath, "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()])

  # 文字コードがUTF-8 With BOMだと、エクセルで開いたときに文字化けしません
  # テキストで開くと文字化けする・・・
  # BOM(byte order mark) Unicodeの符号化形式で符号化したテキストの先頭につける数バイトのデータのこと
  # encoding="utf_8_sig"とすることでBOM付きのUTF-8でCSVファイルを書き出すことが出来る
  with open(newpath, "wt", encoding="utf_8_sig") as fw:
      writer = csv.writer(fw, lineterminator="\n")
      writer.writerows(csv_data)
本当はテキスト出力したい・・・

またこのコードでcsv出力しても、Excel以外で表示すると文字化けする(サクラエディタなど)
anonymous
Anonymous
2022年05月10日
とんでもねぇ
Output