paperless-ngxで日本語の請求書を貯める——定番とされる jpn+eng 設定が見出しを『Ake』に壊す実測と、日本語で自動分類を効かせる正解
紙とPDFの書類を、検索できる形で一箇所に貯めるオープンソース paperless-ngx を、日本語の請求書と契約書で実用になるところまで詰めました。
結論を先に書きます。日本語の全文検索はそのままで十分に効きます。 一方で OCRは3か所直さないと日本語が読めず、自動分類は設定を1つ変えないと当たりません。 しかも間違えたときにエラーが出ないものが2つあります。黙って読めていないだけです。
実機で測った結果だけを書きます。
環境
公式イメージ、PostgreSQL 18 + Valkey + Tika + Gotenberg の構成です。日本語の請求書と契約書、それにスキャン相当の画像PDFを流し込んで確認しました。
つまずき0: 公式のファイルをコピーしても起動しない
本題の前に。公式が配布している設定ファイルには、こう書かれています。
PAPERLESS_SECRET_KEY=change-me
そして本体は、この値が change-me のままだと起動を拒否します。
django.core.exceptions.ImproperlyConfigured: PAPERLESS_SECRET_KEY is not set or is
the default 'change-me' value.
つまり公式のファイルをそのままコピーすると、必ず起動しません。 しかもコンテナは再起動を繰り返すだけなので、docker compose up -d は成功したように見えます。ログを見るまで気づけません。
鍵を自分で作って入れれば解決します。
python3 -c "import secrets; print(secrets.token_urlsafe(64))"
つまずき1: 日本語のOCRデータは入っていない
起動したら、コンテナの中を見てみます。
$ docker compose exec webserver tesseract --list-langs
List of available languages (7): deu eng fra ita jpn osd spa
英語・ドイツ語・イタリア語・スペイン語・フランス語だけです。日本語はありません。環境変数で追加します。
PAPERLESS_OCR_LANGUAGES=jpn
ここまでは説明どおりです。
つまずき2: 縦書きは、1文字違うと黙って無視される
日本語には縦書きがあります。縦書き用のデータの名前は jpn_vert です。素直にこう書きたくなります。
PAPERLESS_OCR_LANGUAGES=jpn jpn_vert
起動ログを見ると、こうなっていました。
[init-tesseract-langs] Installed tesseract-ocr-jpn
[init-tesseract-langs] Skipped tesseract-ocr-jpn_vert: Package not found! :(
そしてコンテナはそのまま healthy になります。画面も開きます。横書きの書類は読めます。縦書きだけが読めない状態が、気づかれないまま続きます。
原因は名前の食い違いでした。
| 何の名前か | 表記 |
|---|---|
| Debianのパッケージ名 | tesseract-ocr-jpn-vert(ハイフン) |
| OCRの言語コード | jpn_vert(アンダースコア) |
この環境変数に書くのはパッケージ名の側です。
PAPERLESS_OCR_LANGUAGES=jpn jpn-vert
直すと8言語になりました。
List of available languages (8): deu eng fra ita jpn jpn_vert osd spa
書くときはハイフン、できあがるのはアンダースコア。 覚えにくいうえに間違えても何も起きないので、ここは確認してください。
つまずき3: jpn+eng が日本語を壊す
ここが最も見つけにくい問題でした。
日本語の書類にも英数字は混ざるので、「両方指定しておけば安全だろう」と jpn+eng にしたくなります。日本語の解説記事の多くもそう書いています。逆効果でした。
日本語の請求書を画像にして、OCRの設定だけを変えて読み比べた結果です。
| 設定 | 見出しの読み取り結果 |
|---|---|
jpn(既定のページ分割) |
求書 |
jpn+eng(既定のページ分割) |
Ake |
jpn + ページ分割 6 |
請求書 |
jpn+eng にすると、見出しの「請求書」が Ake というアルファベットになりました。英語の候補が混ざることで、日本語の文字が形の似たアルファベットに引きずられます。
本文の部分(取引先名・金額・日付・口座番号)は jpn+eng でも正しく読めていました。壊れるのは大きな文字だけです。
そして書類の中で最も大きい文字は、たいてい「請求書」「見積書」「契約書」という書類の種類そのものです。ここが読めないと、後で述べる自動分類も効きません。
日本語が主体の書類なら、PAPERLESS_OCR_LANGUAGE=jpn 単独にしてください。
つまずき4: 見出しの先頭の文字が落ちる
jpn 単独にしても、まだ「求書」でした。「請」が落ちています。
原因はページの分割方法でした。OCRは最初にページを段組みや図に分けますが、既定の自動分割は、ぽつんと大きく置かれた見出しの扱いが苦手です。ページ全体を「ひとかたまりの文章」として扱わせると直ります。
PAPERLESS_OCR_USER_ARGS={"tesseract_pagesegmode": 6}
この設定で取り込み直すと、本文の1行目が「請求書」になりました。
日本のビジネス書類はほぼ1段組みなので、6を既定にして問題ありません。段組みのある冊子を主に扱う場合だけ、既定に戻してください。
結果
3か所直したあとの読み取りです。
請求書
株式会社サンプル商事 御中
件名 倉庫管理システム保守運用
請求番号 2026-0912
発行日 2026年9月5日
お支払期限 2026年10月31日
保守運用費 1式 単価550,000円
消費税 55,000円
合計金額 605,000円
振込先 名古屋銀行 本店 普通 1234567
社名・件名・日付・金額・口座番号まで、すべて正確に読めました。
日本語の全文検索は、そのままで効く
ここは良い知らせです。追加の設定は要りません。
日本語には単語の区切りに空白がないため、海外製の検索機能はしばしば日本語で使いものになりません。文全体がひとかたまりとして扱われ、「請求書」で探しても「これは請求書です」が見つからない、という壊れ方をします。
paperless-ngx にはこの問題がありませんでした。まず、文書に無い言葉は正しく0件でした。
| 検索語 | 結果 |
|---|---|
| 沖縄 / 賃貸借 / 領収書 / ラーメン | すべて0件 |
そのうえで、長い語の一部でも引けました。
| 検索語 | 元の文中での姿 | 結果 |
|---|---|---|
| 商圏 | 商圏分析システム導入支援 | ヒット |
| 委託 | 業務委託契約書 | ヒット |
| 保持 | 機密保持義務 | ヒット |
| 名古屋銀行 | 振込先 名古屋銀行 本店 | ヒット |
そして複合語の分解もできています。
| 検索語 | 結果 |
|---|---|
| 業務委託 / 委託契約 / 契約書 / 業務委託契約書 | すべてヒット |
「業務委託契約書」という1つの語から、「業務委託」でも「委託契約」でも「契約書」でも引けます。実務では短い言葉で探すので、ここが効かないと使えません。
社内wiki用のオープンソースには、まさにここが抜けている製品があります。paperless-ngx は問題ありませんでした。
落とし穴: 自動分類は「単語一致」では当たらない
全文検索が効くので、タグや書類の種類の自動判定も当然効くだろうと思いました。効きませんでした。
paperless-ngx の一致方法には「単語のいずれか」「単語のすべて」「完全一致」「正規表現」などがあります。一般的な案内は「単語のいずれか」を勧めます。
日本語では当たりません。単語を空白で区切って判定しているからです。
契約書の本文は「株式会社エクスブリッジ 業務委託契約書」で始まります。この文書に対して測りました。
| 一致方法 | 指定した語 | 結果 |
|---|---|---|
| 単語のいずれか | 業務委託 | 当たらない |
| 単語のいずれか | 株式会社エクスブリッジ | 当たる |
| 正規表現 | 業務委託 | 当たる |
「業務委託」は「業務委託契約書」の一部で、前後に空白がありません。だから単語として認識されず、当たりません。「株式会社エクスブリッジ」は後ろに空白があるので当たります。
請求書でも同じでした。「振込先 名古屋銀行 本店」に対して、「名古屋」は当たらず、「名古屋銀行」は当たります。
つまり単語一致は、書類の中でたまたま空白に囲まれている語にしか効きません。どこに空白が入るかはOCRの気分次第です。設計の土台にはできません。
日本語では一致方法を「正規表現」にしてください。 本文の途中でも当たります。書く内容は語をそのまま書くだけで、正規表現らしいことをする必要はありません。
一致方法: 正規表現
内容: 請求書|ご請求書|御請求書
日本の書類12種類ぶんの定義を作って当ててみたところ、正しく分類されました。
keiyaku 種類=契約書
seikyu 種類=請求書
再取込テスト 種類=請求書
OCRの失敗は、分類の失敗として現れる
上の一覧に、もう1件ありました。
scan_seikyu 種類=(なし)
これは、jpn+eng の設定で取り込んだ、見出しが ARS と誤読された請求書です。見出しが読めていないので、種類も当たりません。
同じPDFを、設定を直して取り込み直したのが「再取込テスト」で、そちらは正しく請求書に分類されました。
分類が当たらない原因の多くは、分類の設定ではなくOCRです。 タグの条件をいじる前に、その書類の本文を見てください。
まとめ
日本語で使うために必要な設定は、結局この3行でした。
PAPERLESS_OCR_LANGUAGES=jpn jpn-vert
PAPERLESS_OCR_LANGUAGE=jpn
PAPERLESS_OCR_USER_ARGS={"tesseract_pagesegmode": 6}
そして分類は、一致方法を正規表現にすること。
| 項目 | 結果 |
|---|---|
| 日本語の全文検索 | そのまま効く。複合語も分解できる |
| 日本語のOCR | 3か所の設定が要る |
| 縦書き | jpn-vert(ハイフン)。間違えても無言で飛ばされる |
jpn+eng |
日本語には有害。見出しが英字に化ける |
| 自動分類 | 一致方法を正規表現にする |
| 画面の日本語 | 利用者が使う画面は1,422項目中1,420項目が日本語 |
| 管理画面の日本語 | 665項目中205項目が未訳。新機能の設定に偏る |
手書きは tesseract では読めません。手書きが混ざる書類は、外部のAI-OCRで文字にしてからAPIで本文ごと投入する構成になります。そうすると、AI-OCRの利用料が本当に必要な書類だけで済みます。
paperless-ngx は、設定さえ合わせれば日本語の書類管理に十分使えます。全文検索が最初から効くのが一番大きい利点でした。
導入から日本語OCR、分類の設計、運用までをまとめた手順書をKurage App Storeで配布しています。日本の書類12種類の分類定義、動作を判定するスクリプト、OCR確認用の日本語見本PDFを同梱しています。