Skip to content

About

書類の写真やPDFのフォルダを選んでまとめて読み取り、確認してCSVへ書き出すWindowsアプリ(space ocr API 活用デモ)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

書類まるごとCSV — space ocr API 活用デモ

初期バージョン制作:Blue Basket(Windows向け業務自動化デスクトップアプリ開発者) 以降の開発・保守:space ocr(ビョルビ合同会社)

space ocr 活用デモプログラムの公募により、有償で制作を依頼した作品です。著作権は Blue Basket に帰属します。 space ocr は、著作権者から本ソースコードを改変・複製し、自社製品として無償/有償を問わず配布・販売する許諾 (非独占・期間の定めなし)を得ています。一般的なオープンソースライセンスではありません → LICENSE

不具合の報告や使い方のご質問など、お問い合わせの窓口は space ocr です(→ 8. クレジット・ライセンス・お問い合わせ)。 初期バージョン制作者は保守・サポートを行っていません。

請求書・納品書の写真やPDFが入ったフォルダを選び、「まとめて読み取り」を1回押すと、 必要な項目が表に並び、CSVで書き出せるWindowsアプリです。

space ocr API(https://api.space-ocr.com)を使っています。 開発者向けのAPIを、経理・総務の人がそのまま使える形(exe 1個)にするとどうなるか、 というのがこのデモの狙いです。

  • 抽出する項目:日付/取引先/件名/金額/税額(core/fields.py で定義)
  • 出力:CSV(UTF-8 BOM付き)。Excel でも会計ソフトでもそのまま開けます
  • 動作環境:Windows 10 / 11。Python のインストールは不要(exe に同梱)

動作するアプリ本体(exe 一式)は Releases からダウンロードできます。


1. 使う人向け(exe を渡された方へ)

初回だけ:APIキーの入力

書類まるごとCSV.exe を起動してフォルダを選ぶと、キーの入力欄が出ます (残量を表示するために、読み取りより先にキーが必要になります)。 入力したキーは この PC の %APPDATA%\SpaceOcrDemo\spaceocr.env にだけ保存されます。 (環境変数の設定は不要です。次回からは聞かれません)

使い方は3ステップ

  1. ① フォルダを選ぶ — 書類の写真(PNG/JPEG/TIFF等)やPDFが入ったフォルダを選びます
    • 選んだ直後に「画像3枚+PDF1本=5ページ/このあと5回消費します(無料枠の残り○回・残高○回)」 と表示されます。1ページ=1回なので、PDFはページ数で数えます
    • 子フォルダは見に行きません(気づかないうちに去年の書類まで課金されるのを防ぐため)
  2. ② まとめて読み取り — 6ページずつ並列で読み取ります(50ページで約2分)
  3. ③ CSVで書き出す — 保存先を選ぶだけです

画面の見方

場所 何が出るか
左(全件の表) 全ページ・全項目。確認が必要なセルだけ色が付きます。セルはその場で直せます
左(順に確認) 確認が必要な項目を1件ずつ順番に出します
右(原本) 選んだセルの該当箇所を、原本全体を出したまま枠で囲みます。下に拡大を添えます

セルの色は「人が何をすればいいか」で分かれています。

色 意味 すること
赤 打つ 値が取れていません。原本を見て入力してください
橙 選ぶ 同じ値がページ内に複数あるなど、場所が定まりません。どれが正しいか決めてください
黄 見比べる 値も場所もありますが、文字が疑わしいです。原本と1文字ずつ照合してください
緑 直した あなたが入力し直した値です(CSVにはこの値が出ます)
青 確認済み 直さずに「このままでよい」と確認した項目です

大事なこと:色が付いていない=正しい、ではありません

色は「見たほうがよい場所」を示しますが、「見なくていい場所」を保証しません。 そのため、このアプリは

  • 「完了しました」と言い切りません(「4ページを読み取りました。要確認 打つ2件…」と出します)
  • 全件の表をいつでも見られる場所に置いています(色付きだけを見る画面にしていません)

「もう一度読み取る」ボタンはありません

同じ画像を送り直すと、違う結果が返ることがあります(実測で確認しました)。 読み取った時点の結果を固定して、確認作業の途中で値が変わらないようにしてあります。 値を変えたいときは、人が直してください。それが確認作業そのものです。


2. 外に出るもの・出ないもの

通信先 https://api.space-ocr.com のみ。ほかのサーバーへは何も送りません
送るもの 書類の画像と、抽出したい項目の定義だけ
保存されるか Idempotency-Key を使っていません。このヘッダーを付けると応答が最大24時間サーバーに保持されるため、あえて使わず、重複送信の防止はアプリ側で持っています
APIキー %APPDATA%\SpaceOcrDemo\spaceocr.env にのみ保存。exe にもソースにも埋め込んでいません
読み取り結果 %APPDATA%\SpaceOcrDemo\sent_pages.json(ハッシュと応答だけ。書類そのものは保存しません)
クラウド 使いません。アプリを消せば残りません

3. 開発者向け:動かし方

# Python 3.12 系で確認しています
pip install -r requirements.txt

# 開発中はここにキーを置きます(リポジトリには入れません)
#   C:\Users\<user>\secrets\spaceocr.env
#     SPACEOCR_API_KEY=...
#     SPACEOCR_API_BASE=https://api.space-ocr.com

python main.py

キーの探索順は 環境変数 SPACEOCR_API_KEY → %APPDATA%\SpaceOcrDemo\spaceocr.env → ~/secrets/spaceocr.env です(core/config.py)。

テスト

pytest            # 73本。APIは呼びません(偽クライアントと記録済みの応答を使います)

並列処理・台帳・振り分け表・CSV・異常系を固定しています。 実機で試すと1ページごとに課金されるため、壊れ方の検証はすべてテスト側に寄せています。

exe のビルド

pyinstaller --noconfirm 書類まるごとCSV.spec

書類まるごとCSV.spec は手書きです。使っていない Qt モジュールを1件ずつ理由付きで除外 しており(opengl32sw.dll 20.6MB、Qt Quick/Qml/Pdf、AVIF、lxml など)、 85.8MB → 57.8MB になっています。

ビルドした exe は、起動するかどうかを画面なしで確認できます。

dist\書類まるごとCSV.exe --selftest

結果は標準出力と %TEMP%\spaceocr_demo_selftest.txt の両方に出ます (--windowed の exe は標準出力を持たないため)。Qt の読み込みに加えて、 HTTPS が通るかも GET /amount で確認します(このエンドポイントは無料で、スキャンを消費しません)。


4. フォルダ構成

app/
├─ main.py                  入口(--selftest で自己診断)
├─ core/                    business logic(画面なしで動く/テスト対象)
│  ├─ config.py             APIキーの読み書き
│  ├─ spaceocr.py           API クライアント(薄い)
│  ├─ fields.py             抽出する5項目の定義
│  ├─ pages.py              フォルダ → ページ列(PDF分割・ページ番号)
│  ├─ images.py             送る前の縮小(長辺4000px)
│  ├─ batch.py              並列実行・順序保証・失敗の隔離
│  ├─ ledger.py             送信済みページの台帳(二重課金の防止+結果の固定)
│  ├─ triage.py             flag理由12種 →「打つ/選ぶ/見比べる」の割り付け
│  ├─ sheet.py              応答 → 人が直せる表(画面は印字のまま/CSVは normalized)
│  ├─ csvout.py             CSV書き出し(UTF-8 BOM/CRLF)
│  └─ overlay.py            座標を画像に描く(検証用)
├─ ui/                      画面(PySide6)
│  ├─ main_window.py        全件の表+順に確認+原本
│  └─ image_view.py         原本の表示(拡大・パン・quadの枠)
├─ tools/                   検証・資料作成(納品物ではないが再現用に同梱)
├─ tests/                   pytest 73本
├─ samples/                 自作のダミー請求書(実在の情報は含みません)
├─ probe_out/               APIの生の応答(フィードバックの根拠)
└─ 書類まるごとCSV.spec     PyInstaller の設定

core/ は UI を一切 import しません。画面が無い環境(CI・テスト)でも全部動きます。


5. 設計で決めたこと(要点)

理由の詳細は docs/何を作ったか・なぜ選んだか.md に書いています。ここは索引です。

決めたこと 理由(短く)
枠は quad(4隅)で描く。box は使わない 傾いた行を軸平行の矩形で囲むと隣の文字を飲み込む。実物で確認済み
原本は全体表示のまま囲む。拡大は別枠 拡大だけ見せると「隣の行の似た数字を拾った」間違いに気づけない
flag理由ではなく行動で3つに分ける 画面を使うのは経理・総務。overwide_box と ambiguous_occurrence の違いに意味はない
優先順位は 打つ > 選ぶ > 見比べる 場所が決まっていないのに文字を照合させると、人は違う場所と見比べて「合っている」と判断する
verified=false は flag が無くても「見比べる」へ 2エンジンが食い違った値は、拾わないと誰の目にも触れずCSVへ出る
値が空の項目は、APIが何も言ってこなくても「打つ」へ 実測で、見つからない項目は cells にも flagged にも現れなかった。放置すると空欄が黙って流れる
画面は印字のまま/CSVは normalized 印字のままは回ごとに揺れる(¥165,000-/165,000)。normalized は一定(165000)
縮小はドキュメントの1.5MBでなく長辺4000px サーバー側が長辺4000pxに縮小している。1.5MBに合わせると通る画質を自分で捨てる
Idempotency-Key を使わない 応答が24時間保持される。重複防止は台帳(core/ledger.py)で持つ
「もう一度読み取る」を付けない 同じ画像で結果が変わるため。台帳が読み取り時点の結果を固定する
CSVは UTF-8 BOM Shift_JIS では API が返す半角 ¥(U+00A5)を書けない。BOM無しUTF-8は Excel が化けさせる

6. 資料の作り直し方(API課金なし)

python tools/preview_ui.py     # 記録済みの応答で画面を開く(API未使用)
python tools/make_demo.py      # 動作説明の動画とGIFを作り直す(API未使用・要 ffmpeg)
python tools/make_sample.py    # ダミー請求書を作り直す
python tools/make_demo_data.py # デモ用の読み取り結果を取り直す(★ここだけAPIを消費)

デモの映像は demo_data/ に固定したある1回の読み取り結果から作っています。 実測で結果は回ごと・時刻ごとに変わるため、資料側を固定しないと数字が動いてしまうためです。


7. 既知の制約

  • PDFはAPIが受け付けないので、アプリ側でページ画像に分けて1枚ずつ送っています(PyMuPDF・300dpi)
  • HEIC(iPhoneの標準形式)は未対応です。PNG/JPEG/TIFF/BMP/WebP に対応しています
  • 子フォルダは読みません(意図しない課金を避けるため)
  • exe の起動に約4秒かかります(1ファイルにまとめた展開の時間)
  • 抽出項目は5つ固定です。画面から項目を足す機能はデモの範囲外にしています (core/fields.py を編集すれば増やせます)
  • 元ファイルが小さい大きな画像は、縮小後に PNG で送られて送信量がかえって増えることがあります。 core/images.py が保存形式を「送信するデータの大きさ」ではなく「元ファイルの大きさ」で決めているためです。 実測では 8000×8000・9〜12MB の JPEG が base64 で約28〜29MB になり、API の JSON ボディ上限(28MB)に 達する/超えることがあります(14MB の JPEG は JPEG のまま 2.5MB で送られます)。正式公開前に修正予定です

8. クレジット・ライセンス・お問い合わせ

クレジット

初期バージョン制作 Blue Basket — v1.0(2026年8月22日公開)までの設計・実装・検証・資料
以降の開発・保守 space ocr(ビョルビ合同会社) — v1.0 より後の修正・機能追加・配布

v1.0 より後に加えられた変更は space ocr によるもので、Blue Basket の制作物ではありません。 確認が必要な項目を「打つ/選ぶ/見比べる」の3つに分けて優先順位を付ける考え方(core/triage.py)は、 初期バージョンで Blue Basket が設計したものです。

ライセンス

  • 著作権は Blue Basket に帰属します
  • space ocr は、本ソースコードを改変・複製し、自社製品として無償/有償を問わず配布・販売する許諾を、 非独占・期間の定めなしで得ています(2026年8月25日 合意)
  • MIT や Apache などのオープンソースライセンスではありません。 space ocr 以外への利用許諾は行っていません。 リポジトリの公開は、制作内容を閲覧できるようにするためのものです
  • 全文は LICENSE をご覧ください

お問い合わせ

不具合の報告・使い方のご質問・その他のお問い合わせは、すべて space ocr が窓口です。

初期バージョン制作者(Blue Basket)は保守・サポートを行っていません。直接のお問い合わせはご遠慮ください。

About

書類の写真やPDFのフォルダを選んでまとめて読み取り、確認してCSVへ書き出すWindowsアプリ(space ocr API 活用デモ)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages