見出し画像

PDFから表を抽出してエクセルに保存する Python


今回やりたいこと

図1の請求書の表データを抜き取って、Excelに保存したい。

図1 請求書の例

ライブラリ

PDFの表データを抽出するためにPyMuPDFというライブラリを使用する。
pipでのインストールは下記の通り。

pip install PyMuPDF

PDFから表の抽出

PyMuPDFライブラリは、importする際、fitzという名前でimportする。ライブラリ名とimportの名前が異なるのは、歴史的経緯によるものらしい。

PDFファイルの読み込みは、fitzのopen関数を用いる。

import fitz

# PDFの読み込み
doc = fitz.open("請求書.pdf")

次にPDFファイルの表データを探す。

# ページの指定
page = doc[0]

# 表データの検索
tables = page.find_tables()

今回は1ページのみのファイルを想定しているので、docのところは、0を指定する。2ページ目や3ページ目がある場合は、docのところの数字をページ番号から1引いた値にすればよい。
find_tablesはページ内の表を検索する。

表データをExcelに保存

tablesで取得した表データの中身は

tables[0].extract()

で取得できる。表データが複数ある場合は、tables[数値]の数値を変更することで取得できる。実際にtablesを表示すると、

[['品目', '数量', '単価', '金額'],
 ['アイテム1', '100', '200', '20000'],
 ['アイテム2', '5', '1000', '5000'],
 ['アイテム3', '30', '400', '12000'],
 ['アイテム4', '3', '9990', '29970'],
 ['', '', '', ''],
 ['', '', '', ''],
 ['', '', '', ''],
 ['', '', '', ''],
 ['', None, '合計', '66970']]

のようにリストとなって取得できる。
1番最初の行をカラム名として、pandasを用いてデータフレームを作成する。

# 列名にするデータを取得
columns = table_data[0]

# 表のデータを取得
data_rows = table_data[1:]

# データフレームを作成
df = pd.DataFrame(data_rows, columns=columns)

作成したデータフレームを表示すると、

      品目    数量    単価     金額
0  アイテム1   100   200  20000
1  アイテム2     5  1000   5000
2  アイテム3    30   400  12000
3  アイテム4     3  9990  29970
4
5
6
7
8         None    合計  66970

となる。このまま保存してもよいが、空白行はない方が見栄えがいいので、削除する。
空白行を削除するには、空白セルをnanに置き換えると、dropnaを用いて簡単に削除できる。

df1 = df.replace("", np.nan)  # nanに置き換え
df2 = df1.dropna(how="all")  # すべての列がnanの行を削除

これによって、

      品目    数量    単価     金額
0  アイテム1   100   200  20000
1  アイテム2     5  1000   5000
2  アイテム3    30   400  12000
3  アイテム4     3  9990  29970
8    NaN  None    合計  66970

となり、空白行を消すことができた。
あとは、to_excelを用いてExcelファイルに保存すればよい。

# データフレームをExcelに保存
df2.to_excel("請求書.xlsx", index=False)

コード全体

import fitz
import pandas as pd
import numpy as np


# PDFの読み込み
doc = fitz.open("請求書.pdf")

# ページの指定
page = doc[0]

# 表データの検索
tables = page.find_tables()

if tables.tables:
    table_data = tables[0].extract()
    # 列名にするデータを取得
    columns = table_data[0]

    # 表のデータを取得
    data_rows = table_data[1:]

    # データフレームを作成
    df = pd.DataFrame(data_rows, columns=columns)
    
    df1 = df.replace("", np.nan)  # nanに置き換え
    df2 = df1.dropna(how="all")  # すべての列がnanの行を削除
    
    # データフレームをExcelに保存
    df2.to_excel("請求書.xlsx", index=False)

サイト

https://sites.google.com/view/elemagscience/%E3%83%9B%E3%83%BC%E3%83%A0


この記事が気に入ったらサポートをしてみませんか?