気になること

気になったことをChatGPTで調べて、その内容を書いてます。

PythonでPDFからExcelへのデータ抽出 ~Chatgptを使った作成プロセス~

1. 概要

PDFファイルからデータを抽出し、それをExcelファイルに出力する方法を紹介します。今回は、特定のPDFフォーマットから商品情報を抽出し、それをExcelに整理して保存するプロセスを実装します。

2. 必要なライブラリのインストール

 

まず、必要なライブラリをインストールします。PyMuPDFを使用してPDFからテキストを抽出し、Pandasを使用してデータを整形し、Excelに出力します。

 

 >|python|pip install PyMuPDF pandas openpyxl||<
 

3. PDFからテキストを抽出

PDFファイルからテキストを抽出するコードです。ここでは、各行をリストに格納し、抽出されたテキストの内容を確認します。

 

 >|python|

import fitz # PyMuPDF import pandas as pd # PDFファイルを開く pdf_path = '注文書.pdf' doc = fitz.open(pdf_path) # PDFの各行を抽出 lines = [] for page_num in range(len(doc)): page = doc.load_page(page_num) lines.extend(page.get_text("text").split('\n')) # 抽出した行を確認(デバッグ用) for i, line in enumerate(lines): print(f"Line {i}: {line}")||<

4. 特定の行からデータを抽出

特定の行から商品情報を抽出し、Pandasのデータフレームに格納します。PDFのフォーマットに基づき、行番号を指定してデータを抽出します。

 

 

>|python|

# データフレーム用のリストを初期化
data = {
    "商品名": ,
    "数量":
,
    "単価": ,
    "単位":
,
    "金額": []
}

 

# 特定の行からデータを抽出
try:
    product_positions = [19, 26]  # 最初の商品と2つ目の商品が始まる行の位置
    for pos in product_positions:
        product_name = lines[pos].strip()
        quantity = int(lines[pos + 1].strip())
        unit_price = int(lines[pos + 2].strip())
        unit = lines[pos + 4].strip()
        total_price = int(lines[pos + 5].strip().replace(',', '').replace('¥', ''))

 

        data["商品名"].append(product_name)
        data["数量"].append(quantity)
        data["単価"].append(unit_price)
        data["単位"].append(unit)
        data["金額"].append(total_price)
except (IndexError, ValueError) as e:
    print(f"データ抽出中にエラーが発生しました: {e}")

 

||<

 

5. データをExcelに書き出し

抽出したデータをデータフレームに変換し、Excelファイルに出力します。

 

>|python|

# データフレームに変換
df = pd.DataFrame(data)

 

# データフレームの内容を確認(デバッグ用)
print("データフレームの内容:")
print(df)

 

# Excelファイルに書き出し
excel_path = 'output.xlsx'
df.to_excel(excel_path, index=False)

 

print("Excelファイルに出力しました:", excel_path)

 

||<

 

6. 結果の確認

生成されたExcelファイルを確認し、データが正しく抽出されていることを確認します。

7. 失敗とやり直しの過程

最初の試み

最初は、PyMuPDF(fitz)を使用してPDFからテキストを抽出し、そのテキストを解析してExcelに出力する基本的なスクリプトを作成しました。しかし、抽出されたテキストが期待した形式ではなく、データが正しくExcelに出力されませんでした。 

 

>|python|

import fitz  # PyMuPDF
import pandas as pd

 

# PDFファイルを開く
pdf_path = '注文書.pdf'
doc = fitz.open(pdf_path)

 

# PDFのテキストを抽出
text = ""
for page_num in range(len(doc)):
    page = doc.load_page(page_num)
    text += page.get_text()

 

# テキストをデータフレームに変換
# 手動でテキストから必要な部分を抽出します
data = {
    "商品名": ["リンゴ", "イチゴ"],
    "数量": [5, 4],
    "単価": [200, 500],
    "単位": ["個", "個"],
    "割引": [0, 0],
    "金額": [1000, 2000]
}

 

df = pd.DataFrame(data)

 

# Excelファイルに書き出し
excel_path = 'output.xlsx'
df.to_excel(excel_path, index=False)

 

print("Excelファイルに出力しました:", excel_path)

 

||<

 

 

このアプローチでは、データを手動で設定していたため、動的にデータを抽出することができませんでした。

エラーとその対処

次に、PDFからのテキスト抽出の方法を改善し、抽出されたテキストの各行を表示してデバッグしました。しかし、行データの解析においてリストインデックスのエラーが発生しました。

 

>|python|

import fitz  # PyMuPDF
import pandas as pd

 

# PDFファイルを開く
pdf_path = '注文書.pdf'
doc = fitz.open(pdf_path)

 

# PDFの各行を抽出
lines =
for page_num in range(len(doc)):
    page = doc.load_page(page_num)
    lines.extend(page.get_text("text").split('\n'))

 

# 抽出した行を確認(デバッグ用)
for i, line in enumerate(lines):
    print(f"Line {i}: {line}")

 

# データフレーム用のリストを初期化
data = {
    "商品名": ,
    "数量": ,
    "単価":
,
    "単位": ,
    "金額":

}

 

# 特定の行からデータを抽出
try:
    product_positions = [19, 26]  # 最初の商品と2つ目の商品が始まる行の位置
    for pos in product_positions:
        product_name = lines[pos].strip()
        quantity = int(lines[pos + 1].strip())
        unit_price = int(lines[pos + 2].strip())
        unit = lines[pos + 4].strip()
        total_price = int(lines[pos + 5].strip().replace(',', '').replace('¥', ''))

 

        data["商品名"].append(product_name)
        data["数量"].append(quantity)
        data["単価"].append(unit_price)
        data["単位"].append(unit)
        data["金額"].append(total_price)
except (IndexError, ValueError) as e:
    print(f"データ抽出中にエラーが発生しました: {e}")

 

# データフレームに変換
df = pd.DataFrame(data)

 

# データフレームの内容を確認(デバッグ用)
print("データフレームの内容:")
print(df)

 

# Excelファイルに書き出し
excel_path = 'output.xlsx'
df.to_excel(excel_path, index=False)

 

print("Excelファイルに出力しました:", excel_path)

 

||<

 

このエラーに対処するため、エラーハンドリングを追加し、データ抽出が失敗した場合に適切に対処するようにしました。また、商品のデータが特定の行から始まることを前提にしていたため、動的にデータを抽出できるように改善しました。

まとめ

このプロセスにより、PDFファイルから特定のフォーマットに基づいたデータを抽出し、Excelファイルに出力することができました。試行錯誤を繰り返しながら、エラーハンドリングや動的なデータ抽出の方法を改善することで、最終的に成功しました。このブログ記事が、PDFからExcelへのデータ抽出における参考になれば幸いです。

注意点

  • PDFのフォーマットが変わった場合、行番号などの調整が必要です。
  • エラーハンドリングを追加し、データ抽出中の問題を適切に処理するようにします。