Pythonで請求書からデータを抽出する

Portrait of Sylvain Josserand
執筆者 Sylvain Josserand
2 分で読了
最終更新日

主なポイント:

  • Pythonは請求書からのデータ抽出を自動化できますが、すべてに対応できる万能なソリューションではありません
  • ParseurはPythonを活用して請求書データの自動抽出にも対応しています
  • PDFはデータフォーマットではなく、紙の書類の印刷レイアウトを電子的に再現するものです

PDFフォーマットとは

PDFフォーマットは、請求書のような紙の書類を正確にデジタルで表現できる柔軟なフォーマットです。元々、紙印刷の再現を目的に設計されており、印刷ページをそのままデジタルに反映します。 このため、PDF作成者は独自の表現を行いやすく、様々な業界基準や規制にも対応できます。

一方、PDFの中にデータが閉じ込められていると、後から情報を抽出するのは手間がかかります。 フォーマットが自由で複雑になりやすく、日々大量に処理される業務用途では、構造化データとして管理しづらい場合があります。

A screen capture of PDF file format layers
PDF file format layers

請求書からデータを抽出する手順

請求書は一般的にPDFフォーマットでやりとりされます。 請求書は、供給者と顧客の間で、商品やサービスの対価を正式に記録するための書類です。 この請求書から必要なデータを抽出する場合、下記の手順を踏みます:

  1. 抽出したいデータ項目(スキーマ)を決める
  2. 請求書ファイルを画像からテキストに変換する
  3. テキストからスキーマに沿ってデータを取得する
  4. 抽出したデータをまとめる

A screen capture of Invoice data extraction process
Invoice data extraction process

請求書データのスキーマを定義する

請求書はサプライヤーごとに異なるレイアウトで作られるものの、根本的に必要な情報はほぼ同じです。一般的には「供給者」「顧客」「請求書番号」「日付」「商品リスト(数量・説明・単価・金額)」などが含まれます。 スキーマ設定の際は、最終的に会計システムやデータベースで管理しやすい形式を意識するのがポイントです。

もし汎用性の高いデータ定義が必要であれば、schema.orgInvoiceの標準フォーマットも掲載されていますので参考になります。 Parseurでは請求書用の標準データスキーマを用意しており、 要件に合わせてカスタマイズも可能です。 スキーマが決まれば、次は画像データのテキスト化に進みましょう。

例えば、請求書用のデータスキーマを下記のようなJSON(Swagger形式)で表すことが出来ます:

{
    "InvoiceNumber": {
        "type": "string",
        "description": "The invoice number"
    },
    "InvoiceIssueDate": {
        "type": "string",
        "description": "The invoice date"
    },
    "Items": {
        "type": "array",
        "description": "The list of items in the invoice",
        "items": {
            "type": "object",
            "properties": {
                "quantity": {
                    "type": "number",
                    "description": "The quantity of the item"
                },
                "description": {
                    "type": "string",
                    "description": "The description of the item"
                },
                "unit_price": {
                    "type": "number",
                    "description": "The unit price of the item"
                },
                "price": {
                    "type": "number",
                    "description": "The total price of the item"
                }
            }
        }
    }
}

請求書を画像からテキストに変換する

A screen capture of an invoice taken from a smartphone
Picture of an invoice taken from a smartphone

PDFファイルにはスキャン画像が含まれている場合があります。たとえば、社員がスマートフォンで請求書を撮影してPDFにし、経理担当者へ送るケースです。 経理担当者はこの請求書からミスなく情報を抜き出し、会計システムに手入力しなければなりません。 このような画像からデータを抽出するには、光学文字認識 (OCR)を使いテキスト化する必要があります。 有名なOCRにTesseractがあります。TesseractはC/C++で書かれていますが、Pythonから使う場合はPyTesseractなどのライブラリ経由で使用します。 他にも多くのOCRエンジンがあり、それぞれ結果や精度が異なります。 Parseurは文書が画像かどうかを自動判別し、自動でテキスト抽出します。テキスト化されたら、データ抽出の準備が整います。

データスキーマに従って請求書内のテキストを抽出する

PDFがテキスト検索可能な状態なら、pdftotextというPythonライブラリでテキスト取り出しが可能です。 以下は、PDFからテキストを抽出する基本的なサンプルコードです:

import pdftotext

# 請求書を読み込む
with open("invoice.pdf", "rb") as file_handle:
    pdf = pdftotext.PDF(file_handle)

# 全ページをループ処理
for page in pdf:
    print(page)

このスクリプトを convert_pdf_to_text.py として保存し実行すると、標準出力にPDFのテキストが表示されます。 テキストをファイルに書き出したい場合は下記コマンドを利用します:

$ python convert_pdf_to_text.py > invoice.txt

このテキストから必要な情報を抽出する主な方法は下記の通りです:

  • 正規表現でのパターン抽出。強力ですがフォーマット変更に弱く、表形式データには向きません。
  • 動的OCRゾーンOCRなど視覚的なテンプレート解析。堅牢ですが設定や運用は複雑になります。
  • 機械学習型システム。柔軟ですが、大量データでの学習や人による確認が必要となります。

Python標準の re モジュールで請求書番号を抽出するサンプル:

import re

# 請求書テキストを読み込み
with open("invoice.txt", "r") as file_handle:
    invoice = file_handle.read()

# 請求書番号を抽出
invoice_number = re.search(r"Invoice number: (\w+)", invoice).group(1)
print(invoice_number)

このスクリプトを extract.py に保存し実行すると、請求書番号が出力されます:

$ python extract.py

例として、

INV-1234

が表示されます。

注意:この正規表現は、「Invoice number: INV-1234」のような表記の請求書にしか対応していません。 レイアウトやフォーマットが異なる場合は、都度パターンを修正する手間が生じます。 異なる形式の請求書が混在する場合、このメンテナンスは大きな負担になります。

こうした場合はParseurが有効です。

無料アカウントを作成
Parseurで時間と労力を節約。ドキュメント処理を自動化しましょう。

正規表現による解析を選んでも、Parseurではテンプレートベースの管理が容易であり、過去に作成した豊富なテンプレートライブラリも活用できます。 正規表現、ビジュアルテンプレート(OCR)、機械学習(AI)など必要に応じて抽出方式を選択・組み合わせ可能で、抽出結果も簡単に確認・補正できます。

抽出したデータを収集する

Pythonを活用することで、指定フォルダ内の複数の請求書PDFからデータを一括して抽出できます。 たとえば請求書番号と合計金額を抜き出してCSVとして出力するには次のようにします:

import os
import re

import pdftotext

# フォルダ内のPDFを繰り返し処理
for filename in os.listdir("invoices/"):
    if not filename.endswith(".pdf"):
        continue

    # 請求書PDF読み込み
    with open("invoices/" + filename, "rb") as file_handle:
        pdf = pdftotext.PDF(file_handle)

    # CSVヘッダ出力
    print("InvoiceNumber,TotalAmount")

    # 全ページループ
    for page in pdf:
        # 請求書番号・合計金額を抽出
        invoice_number = re.search(r"Invoice number: (\w+)", page).group(1)
        total_amount = re.search(r"Total amount: (\w+)", page).group(1)
        print(invoice_number, total_amount, sep=",")

このスクリプトを extract_to_csv.py で保存・実行すると、請求書番号と合計金額がCSV形式で出力されます。 ファイルにリダイレクトすればExcel等で活用できます:

$ python extract_to_csv.py > invoices.csv

Parseurを使えば、抽出済みデータはそのままスプレッドシートとしてダウンロード可能で、 Webhook連携MakeZapierMicrosoft Power Automateによる会計ソフト等への直接連携も対応しています。 また、API経由でJSON形式データの取得も可能です。

まとめ

いかがでしたか? pythonで請求書からデータを自動抽出するには様々な手順が必要ですが、仕組みを作れば自動化も十分可能です。 ただし請求書のフォーマットが一定であることや開発・検証の時間が取れることが前提となります。 労力や精度の確保にお困りの方は、Parseurを活用することで、どんな請求書にも柔軟かつ正確にデータ抽出でき、業務効率化を実現できます。

最終更新日

AIによるデータ抽出ソフトウェア。
今すぐParseurを始めよう。

メール、PDF、スプレッドシートからのテキスト抽出を自動化。
手作業の工数を数百時間削減。
AIによる業務自動化を体験しましょう。

Parseur rated 5/5 on Capterra
Parseur.com has the highest adoption on G2
Parseur.com has the happiest users badge on Crozdesk
Parseur rated 5/5 on GetApp
Parseur rated 4.5/5 on Trustpilot