10 KiB
PDFスキャン監視・自動振り分けツール 設計書
日付: 2026-08-02 対象ブランチ: feature/process-flowchart-generator(ScanOCRプロジェクト)
概要
既存 extract_and_rename.py(CLI引数型・氏名/日付OCR抽出リネーム)全面改修。
バッチダブルクリック起動・固定フォルダ構成・同梱Python完結配布パッケージへ変更。
box_detector.py(テンプレート赤枠/青枠検出)無改修流用。
配布パッケージ構成
ホームディレクトリ = バッチ配置場所。フォルダごとコピーすればそのまま動作。
ScanOCR/
├── OCR仕分け実行.bat 起動バッチ
├── config.txt フォルダ名・動作パラメータ設定(必須ファイル。無ければ起動失敗)
├── スクリプト/
│ ├── extract_and_rename.py メイン処理
│ ├── box_detector.py テンプレート枠検出(変更なし)
│ ├── python/ Python embeddable本体 + site-packages同梱
│ └── tools/
│ ├── tesseract/ tesseract.exe + tessdata/jpn.traineddata
│ └── poppler/ pdftoppm.exe 等
├── テンプレート/ テンプレート画像置き場
├── スキャン/ 処理対象PDF投入先
├── アウトプット/ 成功時リネームコピー先(氏名フォルダ別)
├── 成功/ 処理済みオリジナルPDF退避先
├── 失敗/ 抽出失敗PDF退避先
├── ログ/ 実行ログ(日付別)
└── .lock 二重起動防止ロック(実行中のみ存在)
テンプレート/スキャン/アウトプット/成功/失敗/ログの6フォルダ、起動時に無ければ自動作成。
config.txt・スクリプト/(配下のpython/・tools/含む)は自動生成対象外(無ければエラー扱い)。
config.txt仕様
key=value形式・UTF-8。配布パッケージに必須同梱。存在しなければ起動失敗(自動生成しない)。
スクリプトフォルダ=スクリプト
テンプレートフォルダ=テンプレート
スキャンフォルダ=スキャン
アウトプットフォルダ=アウトプット
成功フォルダ=成功
失敗フォルダ=失敗
ログフォルダ=ログ
margin=0.10
DPI=300
ファイル安定待ち秒=1
ファイル安定待ちリトライ回数=5
- フォルダ名項目、ホームディレクトリ基準の相対パス
スクリプトフォルダはOCR仕分け実行.batがPython起動パスを組み立てる際にも参照する(後述)margin・DPIは既存スクリプト同名パラメータの外部化ファイル安定待ち秒・ファイル安定待ちリトライ回数は書き込み中PDF対策用(後述)
起動フロー
OCR仕分け実行.bat
- カレントディレクトリをバッチ配置場所に固定(
%~dp0) config.txt存在確認- 無 → 「config.txt が見つかりません。配布パッケージが不完全です」表示・pauseで終了
config.txtからスクリプトフォルダ=行を読み取り(for /f "tokens=1,2 delims==" %%a in (config.txt)、コードページはUTF-8=chcp 65001前提)、<スクリプトフォルダ>\python\python.exeと<スクリプトフォルダ>\extract_and_rename.pyの実パスを組み立てる<スクリプトフォルダ>\python\python.exe存在確認- 無 → 「配布パッケージが不完全です(pythonフォルダが見つかりません)。管理者に確認してください」表示・pauseで終了
<スクリプトフォルダ>\python\python.exe <スクリプトフォルダ>\extract_and_rename.py実行
方針転換点: 従来案(システムPython有無チェック→未導入ならインストール案内)は撤回。同梱Python完結配布のため、チェック対象は「システムのPython」でなく「同梱ファイル一式の充足」。
extract_and_rename.py 初期化順序
- 必要6フォルダ(テンプレート/スキャン/アウトプット/成功/失敗/ログ)存在チェック・自動作成
config.txt読込(バッチ側で存在確認済みだが、直接pyを叩いて実行されるケースに備えPython側でも存在チェック・無ければエラー終了)- 依存モジュール(cv2, numpy, PIL, pytesseract, pdf2image)import確認
- 失敗 → 不足モジュール名明示「配布パッケージが壊れています」表示・終了
<スクリプトフォルダ>/tools/tesseract/tesseract.exe・<スクリプトフォルダ>/tools/poppler/pdftoppm.exe存在確認- 無 → 該当ファイル名明示・終了
- 二重起動防止ロック(
.lock)確認- 存在・記録PID稼働中 → 「既に実行中です」表示・終了
- 存在するがPID非稼働(前回異常終了の残骸)→ 自動削除し続行
- 新規
.lock作成・自プロセスPID記録
- テンプレートフォルダから対象ファイル(拡張子 .png/.jpg/.jpeg/.bmp、ファイル名昇順)先頭1件採用
- 対象ファイル無 → エラー表示(ロック解除の上)終了
box_detector.detect_template_fieldsでテンプレート枠検出 → 氏名欄・日付欄の比率座標取得
メインループ
1件ずつ処理。1件処理毎に以下実施:
- スキャンフォルダ再glob(
*.pdf)でキュー更新- キュー空 → ループ終了(正常終了)
- キュー先頭ファイル取り出し
- キー入力チェック(
msvcrt.kbhit())- 入力あり → 「ユーザー操作により停止しました」ログ記録・ループ脱出
- ファイル存在チェック(他プロセスが移動・削除済みならスキップ・次周回へ)
- ファイルサイズ安定待ち(
ファイル安定待ち秒間隔でサイズ比較、ファイル安定待ちリトライ回数回試行)- 不安定 → 「サイズ不安定のためスキップ」ログ記録・今回見送り(次周回で再チェック)
- OCR処理実行
- 例外発生 → スタックトレース込みログ記録・"失敗"フォルダへ移動
- 氏名または日付いずれか欠如 → ログ記録・"失敗"フォルダへ移動
- 両方取得成功 →
a. ファイル名 =
氏名_YYYYMMDD.pdf。"アウトプット/氏名/" 配下に同名既存なら氏名_YYYYMMDD(2).pdf,(3)...連番付与 b. "アウトプット/氏名/" へコピー c. 元ファイルを "成功" フォルダへ移動(同名重複時も同様の連番ルール) d. ログに成功記録
終了処理
- ループ脱出後
.lock削除 - 「処理完了。何かキーを押すと終了します」表示・pause
ログ仕様
- 出力先:
ログ/YYYY-MM-DD.log(日付別、UTF-8 BOM付き) - 1件1行、フォーマット:
[YYYY-MM-DD HH:MM:SS] 結果=成功|失敗|スキップ|エラー | 元ファイル=xxx.pdf | 氏名=xxx | 日付=xxx | 備考=... - エラー時、備考欄にスタックトレース概要含める
ビルドスクリプト(素材自動調達・配布パッケージ生成)
開発者PC上で1回実行すれば dist/ScanOCR/ 配下に配布用一式(スクリプト/python/・スクリプト/tools/ 含む)を自動生成する別スクリプト。実行主体はリポジトリ管理下のシステムPython(ネット接続前提)。配布先PCはオフラインで動作するが、ビルド実行時のみネット接続必須。
配置: build/build_package.py(リポジトリ管理下、配布パッケージ本体には含めない)
リポジトリとdist/の役割分担:
- リポジトリ直下: コード類のみ管理(
OCR仕分け実行.bat・config.txt・スクリプト/extract_and_rename.py・スクリプト/box_detector.py) dist/: ビルド生成物置き場。.gitignoreに追加しコミット対象外とする
処理内容:
dist/ScanOCR/を作成(既存なら中身をクリアしてから再生成)- コード類をリポジトリから
dist/ScanOCR/配下へコピー - Python embeddable版取得・配置
- 固定バージョン(例: 3.11.9 windows embeddable amd64)をDL・展開 →
dist/ScanOCR/スクリプト/python/ python311._pth内の#import siteのコメントアウトを解除(site有効化、pip動作に必須)get-pip.pyをDLし実行してpip有効化python.exe -m pip install opencv-python pdf2image pytesseract pillow numpyを実行し同梱Python環境に直接インストール
- 固定バージョン(例: 3.11.9 windows embeddable amd64)をDL・展開 →
- tesseract-ocr for Windows取得・配置
- 固定バージョンのポータブル版一式(jpn言語データ含む)を
dist/ScanOCR/スクリプト/tools/tesseract/へ配置
- 固定バージョンのポータブル版一式(jpn言語データ含む)を
- poppler for Windows取得・配置
- 固定バージョンのビルド済みzipをDL・展開 →
dist/ScanOCR/スクリプト/tools/poppler/
- 固定バージョンのビルド済みzipをDL・展開 →
- 必要6フォルダ(テンプレート/スキャン/アウトプット/成功/失敗/ログ)の空フォルダを
dist/ScanOCR/直下に作成 - 完了メッセージ表示
バージョン固定方針: Python・tesseract-ocr・popplerとも具体バージョン番号をスクリプト内定数として固定(ピン留め)。互換性問題を避けるため、更新したい場合はスクリプト内の定数を手動で書き換える運用とする。具体的なバージョン番号は実装時に確定。
ライセンス: tesseract(Apache 2.0)・poppler(GPL系)とも再配布可能。社内限定配布であれば問題なし。ライセンス文書の同梱は本設計のスコープ外(必要になれば別途対応)。
対象外・既存仕様からの継承事項
- 複数ページPDFは1ページ目のみ対象(既存仕様継承)
- 和暦・昭和/平成表記非対応(既存
clean_date()の制約継承) - OCR誤読は完全には防げない。運用初期は "アウトプット" 配下の目視確認を推奨
今回のスコープ外(将来検討事項)
- 常時監視(デーモン化)は対象外。1回の起動で「その時点のキューを処理し尽くしたら終了」する設計