LoginSignup
11
13

PythonでPDFの表からデータを取得する(PyMuPDF)

Last updated at Posted at 2023-09-05

PDFの表からデータを取得したい

PDFの表からデータを取得したかったので、PyMuPDFを使ってデータを取得してみました。

ドキュメント

pip install

pip install PyMuPDF

コード

ドキュメントのコードです。
ChatGPTにコメントを日本語にしてもらいました。

import fitz
from pprint import pprint

# ドキュメントを開く
doc = fitz.open("test.pdf")

# ページを取得する
page = doc[0]

# ページ上にあるテーブルを検出する
tabs = page.find_tables()

# 検出されたテーブルの数を表示する
print(f"{len(tabs.tables)}個のテーブルが{page}上に見つかりました")

# 少なくとも1つのテーブルが見つかった場合
if tabs.tables:
    # 最初のテーブルの内容を表示する
    pprint(tabs[0].extract())

表からデータを取得する

1ページのPDFに1つの表があるとき

このようなPDFがあります。

image.png

表(テーブル)のデータを取得します。
PDFのファイルは同一ディレクトリに保存します。

from pprint import pprint

import fitz

# ドキュメントを開く
doc = fitz.open("recipe.pdf")

# ページを取得する
page = doc[0]

# ページ上にあるテーブルを検出する
tabs = page.find_tables()

# 検出されたテーブルの数を表示する
print(f"{len(tabs.tables)}個のテーブルが{page}上に見つかりました")

# 少なくとも1つのテーブルが見つかった場合
if tabs.tables:
    # 最初のテーブルの内容を表示する
    pprint(tabs[0].extract())

【出力結果】
リストとして出力されます。

1個のテーブルがpage 0 of recipe.pdf上に見つかりました
[['材料', '数量'],
 ['アボカド', '1個'],
 ['トマト', '適当(アボカドにあうくらい)'],
 ['大豆水煮缶', '1缶'],
 ['豆腐', '適当'],
 ['しらす', '適当'],
 ['ごま', '適当']]

1ページのPDFに複数の表があるとき

このPDFには、1ページのPDFに2つの表があります。

image.png

for文で複数の表のデータを取得します。

from pprint import pprint

import fitz

# ドキュメントを開く
doc = fitz.open("recipe.pdf")

# ページを取得する
page = doc[0]

# ページ上にあるテーブルを検出する
tabs = page.find_tables()

# 検出されたテーブルの数を表示する
print(f"{len(tabs.tables)}個のテーブルが{page}上に見つかりました")

# 少なくとも1つのテーブルが見つかった場合
if tabs.tables:
    # すべてのテーブルを抽出する
    for table in tabs:
        # テーブルのデータを抽出する
        pprint(table.extract())
        print()

【出力結果】
リストが2つ出力されました。

2個のテーブルがpage 0 of recipe.pdf上に見つかりました
[['材料', '数量'],
 ['アボカド', '1個'],
 ['トマト', '適当(アボカドにあうくらい)'],
 ['大豆水煮缶', '1缶'],
 ['豆腐', '適当'],
 ['しらす', '適当'],
 ['ごま', '適当']]

[['順番', '内容'],
 ['1', 'アボカドとトマトを切る'],
 ['2', '1と大豆の水煮缶をまぜて、ビタミン C を入れる'],
 ['3', 'お皿に豆腐を入れて2をのせる'],
 ['4', '3にしらす・ごま・亜麻仁油をかける']]

PDFが複数ページあるとき

PDFが複数ページあるときはpage = doc[0]でページ番号を指定します。
page = doc[0]は1ページ目です。

財務省の貿易統計から「令和5年7月分貿易統計(速報)の概要」をダウンロードしました。

1ページ目の最初の表を取得します。

image.png

1ページ目の1つ目の表のデータを取得します。
page = doc[0]は1ページ目、tabs[0]は1つ目の表です。

from pprint import pprint

import fitz

doc = fitz.open("gaiyo2023_07.pdf")
page = doc[0]
tabs = page.find_tables()
if tabs.tables:
    pprint(tabs[0].extract())

【出力結果】

[['輸 出', '金 額', '8兆 7,250億円', '▲ 0.3%', '29ヵ月ぶりの減少'],
 [None, '数量指数', '100.3', '▲ 3.2%', '10ヵ月連続の減少'],
 ['輸 入', '金 額', '8兆 8,037億円', '▲13.5%', '4ヵ月連続の減少'],
 [None, '数量指数', '96.9', '▲ 4.3%', '9ヵ月連続の減少'],
 ['差 引', '金 額', '▲787億円', '▲94.5%', '2ヵ月ぶりの赤字']]

1ページ目の2つ目の表のデータを取得します。
page = doc[0]は1ページ目、tabs[1]は2つ目の表です。

from pprint import pprint

import fitz

doc = fitz.open("gaiyo2023_07.pdf")
page = doc[0]
tabs = page.find_tables()
if tabs.tables:
    pprint(tabs[1].extract())

【出力結果】

[['輸 出', '1兆 7,912億円', '+13.5%', '22ヵ月連続の増加'],
 ['輸 入', '9,453億円', '▲11.2%', '2ヵ月連続の減少'],
 ['差 引', '8,459億円', '+65.0%', '6ヵ月連続の増加']]

PDFの表をExcelに出力する

pandasのデータフレームを作成して、Excelに出力します。

こちらの表を出力してみます。
image.png

pip install pandas
pip install openpyxl

pandasのデータフレームを作成してExcelに出力します。

import fitz
import pandas as pd

doc = fitz.open("gaiyo2023_07.pdf")
page = doc[3]
tabs = page.find_tables()
if tabs.tables:
    table_data = tabs[0].extract()

    # 列名を取得
    columns = table_data[0]

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

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

    # データフレームをExcelファイルに保存
    df.to_excel("output.xlsx", index=False)  # index=Falseを設定して行番号を含めない

    print("Excelファイルに保存しました: output.excel")

image.png

おまけ

ちょっと遊んでみました🎊

Python日記vol.20🐍PDFの表からデータを取得して叙勲受章者の表を作りたい

11
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
13