請求書をAIの画像認識でCSV化|123項目中122正解の実測と検算ガード

2026.06.30 約 16 分で読めます

紙やPDFの請求書を、1枚ずつExcelに手入力する。月末のあの作業が、地味に消耗しますよね。Claudeの画像認識に「品目と金額をCSVで出して」と投げたら、表形式のまま吸い出せました。今回はレイアウト違い・低画質・回転・スマホ撮影の悪条件まで混ぜた7枚で、どこまで正確に読めるかを実測しています。結果はフィールド単位で99%。崩れたのはどこか、会計ソフトに取り込めるCSVを吐くスクリプトと一緒に、正直に書きます。

結論:デジタル請求書なら金額はほぼ完璧。崩れるのは日付など細部

答えはシンプルでした。きれいに発行されたPDFなら、金額の読み取りはほぼ間違えません。実際、今回の7枚で金額・数量・単価・合計の誤読はゼロでした。低画質にしても、4度傾けても、スマホで暗く撮った想定までやっても、金額は崩れません。

唯一こけたのは、いちばん汚した1枚の「日付の末尾1桁」だけ。123個のフィールドのうち、間違えたのはこれ1つです。だから「金額の表データ化はAIに任せて、合計の検算で守る」が現実解でした。順に見ていきましょう。

題材:意地悪に汚した請求書7枚を作った

本物の請求書は当然出せないので、現場の「読みにくさ」を仕込んだダミーをPythonで7枚生成しました。正解の品目・数量・単価・金額を持たせたうえで、画像だけをClaudeに渡しています。狙ったのは、きれいな1枚で終わらせないこと。わざと条件を散らしました。

  • レイアウト・フォント違い:ゴシック / 明朝 / 太字を混在。明細が3〜4行。
  • 税率と日付表記の揺れ:消費税10%と軽減8%、「2026-06-15」「2026/06/20」「令和8年6月10日」。
  • #5 低解像度+ブラー:FAXやコピーで潰れた想定。
  • #6 回転4°+ノイズ:雑にスキャンして斜めになった想定。
  • #7 強い低解像度+ブラー+JPEG劣化+傾き:スマホで暗所撮影した最悪条件。
Claudeに読み取らせた合成請求書サンプル。クリーンなデジタル発行、株式会社サクラ商事、税込10,296円の明細表
実際に生成したサンプルの1枚(#1・クリーンなデジタル発行)。この画像だけをClaudeに渡し、正解は見せずに読み取らせている。発行元・宛先とも架空の会社で、実在の取引情報は含まない。

合計で明細22行・検証フィールド123個。この123個をどれだけ正しく拾えるかが勝負です。

やってみた:123項目中122正解(99.19%)

Claudeに画像を渡し、発行元・日付・明細・小計・消費税・合計を構造化(JSON)で返させました。それを正解と1フィールドずつ突き合わせています。結果がこちらです。

指標結果
請求書7 枚
検証フィールド123 個
正解122 個
正解率99.19%
金額・数量・単価・合計の誤読0 件
唯一の誤り#7(強劣化)の日付 2026-06-18 → 2026-06-15

クリーンな4枚は完全一致でした。和暦の「令和8年6月10日」も、スラッシュ区切りの「2026/06/20」も、そのまま正しく解釈しています。驚いたのは低画質と回転の2枚。ブラーで潰れていても、4度斜めでも、金額と明細は1つも外しませんでした。

「本当に読めているの?」という人向けに、生の入出力を1組だけ見せます。さきほどの#1(サクラ商事)の画像を渡して、Claudeが実際に返したJSONがこれです。金額も明細も、正解と1文字も違いませんでした。

{
  "issuer": "株式会社サクラ商事",
  "date": "2026-06-15",
  "line_items": [
    {"name": "コピー用紙 A4 (500枚)", "qty": 12, "unit_price": 480, "amount": 5760},
    {"name": "ボールペン 黒 (10本入)", "qty": 5, "unit_price": 320, "amount": 1600},
    {"name": "クリアファイル A4 (20枚)", "qty": 8, "unit_price": 250, "amount": 2000}
  ],
  "subtotal": 9360, "tax": 936, "total": 10296
}
強く劣化させた合成請求書サンプル。スマホ暗所撮影を想定してぼかし・傾き・JPEG劣化をかけた佐藤工務店の請求書で、日付がぼやけて読みにくい
唯一こけた#7。スマホの暗所撮影を想定して、ブラー・傾き・JPEG劣化を強くかけた1枚。数字がにじんでいるが、金額(税込227,128円)はすべて正しく読めた。落ちたのは発行日の末尾だけ。

こけたのは、スマホ暗所撮影を想定して強烈に劣化させた#7だけ。それも金額は全部正しく、外したのは日付の末尾「18」を「15」と読んだ1か所です。金額が読めるのに日付の細部が落ちる。これが現実的な崩れ方でした。逆に言えば、いちばん怖い「金額の誤読」は今回出ていません。

#7の発行日
正解2026-06-18
Claudeの抽出2026-06-15(末尾を誤読)
上の劣化画像に対する唯一の誤り。123フィールド中この1か所だけ。

コピペで動く実装(Anthropic API・画像入力+構造化出力)

本番で使う形のスクリプトです。請求書画像をBase64で渡し、抽出スキーマ(列定義)を固定してJSONで受け取ります。最後に会計ソフト取り込み用のCSVを書き出し、合計の検算結果も列に付けています。

# -*- coding: utf-8 -*-
"""
請求書/領収書の画像から品目・金額・日付・合計を Claude の画像認識で抽出し CSV 化する。
実行: ANTHROPIC_API_KEY を設定して  python extract_invoices_with_claude.py
"""
import base64, csv, glob, json, os
import anthropic

MODEL = "claude-opus-4-8"   # 画像認識の精度重視。コスト優先なら claude-sonnet-4-6

SCHEMA = {
    "type": "object",
    "properties": {
        "issuer": {"type": "string"},
        "date": {"type": "string", "description": "YYYY-MM-DD 形式。和暦は西暦へ変換"},
        "line_items": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "qty": {"type": "integer"},
                    "unit_price": {"type": "integer"},
                    "amount": {"type": "integer"},
                },
                "required": ["name", "qty", "unit_price", "amount"],
                "additionalProperties": False,
            },
        },
        "subtotal": {"type": "integer"},
        "tax": {"type": "integer"},
        "total": {"type": "integer"},
    },
    "required": ["issuer", "date", "line_items", "subtotal", "tax", "total"],
    "additionalProperties": False,
}

PROMPT = ("この請求書画像から、発行元・日付・明細(品名/数量/単価/金額)・小計・消費税・合計を"
          "正確に読み取ってJSONで返してください。数字はカンマや¥を除いた整数で。")

client = anthropic.Anthropic()
rows = []
for path in sorted(glob.glob("invoice_*.png")):
    data = base64.standard_b64encode(open(path, "rb").read()).decode()
    resp = client.messages.create(
        model=MODEL,
        max_tokens=2000,
        output_config={"format": {"type": "json_schema", "schema": SCHEMA}},
        messages=[{"role": "user", "content": [
            {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": data}},
            {"type": "text", "text": PROMPT},
        ]}],
    )
    inv = json.loads(next(b.text for b in resp.content if b.type == "text"))
    calc_ok = inv["subtotal"] + inv["tax"] == inv["total"]   # 合計の検算でガード
    for it in inv["line_items"]:
        rows.append([os.path.basename(path), inv["issuer"], inv["date"],
                     it["name"], it["qty"], it["unit_price"], it["amount"],
                     inv["subtotal"], inv["tax"], inv["total"],
                     "OK" if calc_ok else "要確認(合計不一致)"])
    print(f"{path}: {inv['issuer']} 合計¥{inv['total']:,} 検算={'OK' if calc_ok else 'NG'}")

with open("invoices.csv", "w", encoding="utf-8-sig", newline="") as f:
    w = csv.writer(f)
    w.writerow(["ファイル","発行元","日付","品名","数量","単価","金額","小計","消費税","合計","検算"])
    w.writerows(rows)
print(f"-> invoices.csv に {len(rows)} 明細を出力")

ポイントは2つです。1つは output_config で列定義(スキーマ)を固定すること。これでパース時に崩れません。もう1つは、画像認識の精度を取りに行くならモデルを claude-opus-4-8 にすること。コストを抑えたいなら claude-sonnet-4-6 でも実用になります。(画像入力の公式ドキュメント)

ガードの作り方:合計の検算で「読み間違い」を機械で弾く

精度99%でも、残り1%をどう守るかが実務では効きます。いちばん簡単で強いのが、合計の検算です。スクリプトでは各データについて「小計+消費税=合計」が一致するかを確認し、合わなければ「要確認」フラグを立てています。

今回は金額の誤読がゼロだったので、検算で弾かれたものはありませんでした。これは裏を返すと、金額系のミスは検算で機械的に拾える、ということです。日付のように検算で守れないフィールドは、別の手当てが要ります。実装では日付に「低確信フラグ」を持たせ、その行だけ目視する運用にすると安全です。全件を端から見直すより、桁違いに軽くなります。

向かないケース・気をつけたいこと

良い数字だけ並べると嘘になるので、限界も書きます。

  • 今回は合成のデジタル請求書。実物はもっと厳しいです。手書き・感熱紙の薄れ・写真の影や反射が入ると、精度は確実に下がります。99%をそのまま自社に当てはめない方が安全です。
  • 崩れたのが日付で済んだのは運の要素もある。強い劣化では金額の桁を落とすこともありえます。だから検算と目視のガードを外さないこと。
  • 撮り方で精度は大きく変わる。スキャンは明るく・まっすぐ・高解像度。これだけで読み取りは安定します。暗所のスマホ撮影は最後の手段です。

逆に言えば、デジタル発行のPDFがそろっている会社なら、いちばんおいしい使いどころです。受信したPDFをそのまま流し込めば、月末の手入力がほぼ消えます。

まとめ

  • 請求書/領収書の表データ化は、Claudeの画像認識で 123項目中122正解(99.19%)
  • 金額・数量・単価・合計の誤読はゼロ。低画質・回転・スマホ撮影想定でも金額は崩れなかった。
  • 唯一の誤りは強劣化1枚の日付1桁(18→15)。金額より細部が落ちる。
  • 合計の検算(小計+税=合計)で金額ミスを機械的に弾き、日付は低確信フラグで目視。
  • 手書き・感熱紙・写真は精度が落ちる前提。スキャンは明るく・まっすぐ・高解像度で。

「AIで下ごしらえ、最後の確認だけ人」という形は、前に書いた 顧客リストの名寄せ記事 と同じ設計です。画像処理を自走で実測した WebP最適化の記事 もあわせてどうぞ。ほかの効率化ネタは 業務効率化実践のカテゴリ にまとめています。

経理の手入力を減らしたい方へ

「受け取った請求書を会計ソフトに自動で取り込みたいけど、検算やCSV変換の組み込みが不安」という方へ。経理・バックオフィスの自動化の導入支援もやっています。請求書の流し込みから検算ガードの設計まで、30分の無料相談から始められます。 → サービス詳細

こま

こま

元SE × AI開発 × 業務自動化の実践者

SE 4年 + プログラミング歴 8年。業務自動化と AI 組み込み開発を仕事にしながら、現場で使えるものだけを書いています。 最新のAIの現場を発信中!!