自炊した本のOCR取り込みで手順が1つ抜けていた。3コマンドの連鎖に直して、スキャンPDFも一括リネームした

開発book-knowledge-base

自炊した本のOCR取り込みで手順が1つ抜けていた。3コマンドの連鎖に直して、スキャンPDFも一括リネームした

朝いちばんに、連番で管理しているフォルダにある裁断済みの本のPDFを3本並べて、取り込み済みかどうかを確認させた。 2本は前日に済んでいて、1本だけが手つかずだった。

残った1本を取り込むよう指示を出したものの、3つ目のコマンド名が出てこなかった。 OCRにかけるコマンドと、章節に再構成するコマンドまでは言える。 そのあとにもう1つあったはずなのに、名前を思い出せない。

忘れていたのは3つ目のコマンドだった

前の3冊の作業記録を漁らせたら、3つ目は後始末のコマンドだった。 OCRで読む、章節に組み直す、ノイズを落とす。 この3段でひとまとまりになっている。

3冊も通したのに、3つ目を覚えていなかった。 覚え直すより、忘れても困らない形にしたほうがいい。 OCRのコマンド定義そのものを、3つを順に呼ぶ連鎖に書き換えさせた。 電子書籍から取り込む側の手順にも後始末が入っていなかったので、そちらにも足させた。

OCRの16分でスクリプトを汎用化する

今回の1冊は354ページあった。 奥付を確認させてからOCRをバックグラウンドで走らせた。 44ページまで進んだ時点で、完了まであと16分ほどと出た。

その待ち時間を、周辺のスクリプトの整備に充てた。 図の一覧シートを作るスクリプトは書籍IDが直書きされていて、他の本に使えない。 後始末のほうも、毎回その本専用の書き捨てスクリプトを作って回していた。 どちらも本を引数で指定できる形に直させた。

汎用化して怖いのは、削りすぎることだ。 新しいコードで、すでに後始末を通してある3冊に dry-run をかけさせた。 差分は2件。 中身を開かせて確かめたら、ページ上部に繰り返し出る節名が本文の行として残っていた箇所だけを消していた。 本文は1文字も減っていない。

349チャンクを61に畳み直す

OCRが354ページぶん終わった。 図が150枚、本文が349チャンクになった。 チャンクをDBに入れ、図はオブジェクトストレージへ上げさせた。

ここまでは1ページが1チャンクで、章も節もない。 目次と本文を突き合わせて、章と節の開始ページを特定させた。 そこで、DBのページ番号が印刷ページ番号より10だけ大きいことが分かった。 このずれを確定させてから、目次の全項目で対応が合うかを検証させた。

再構成は元に戻せない。 走らせる前に、この本のチャンクだけをバックアップさせた。 そのうえで実行して、349チャンクが61に畳まれた。

図の8割は飾りだった

150枚の図を7枚の一覧シートにまとめさせ、1枚ずつ装飾か情報かを判定させた。 出てきた装飾のパターンは、チェックマーク、アイコン、ローマ数字の飾り、無地のブロック。

装飾と判定されたのは80枚だった。 ただし節見出しを画像として切り出したものが混ざっていて、これを消すと見出しごと消える。 削除の前に、その画像の直後に本文のテキスト見出しがあるかを確認させた。 あった。 79枚を削除した。 残る1枚は、目次チャンクの置き換えですでに消えていた。

「IIII」がどこから来たのか

検索テストを通したら、本文に「第」「章」「IIII」という断片が散っていた。 章扉の飾り文字を、OCRが1文字ずつ本文として拾っていた。

判定ルールを足して当て直し、残った2箇所は個別に直させた。 内訳は、縦組みのタイトルが崩れた箇所と、章番号の断片だった。 その個別補正がいつまでも返ってこなくて、固まったかと思った。 接続方式を確認させたら、2箇所とも直り終わっていた。

devサーバーを立ててブラウザで実物を確認させた。 章と節のナビゲーション、図の配信、処理の状態を示すバッジ。 どれも動いている。

それでも本文に「IIII」が残っていた。 分布を出させたら、すべて節番号の飾りで、直後が見出しになっていた。 条件を書いて汎用ルールとして後始末に足させた。 1回目は取りこぼしがあった。 飾りと見出しの間に節番号の数字行が挟まるケースを見て、条件を緩めさせた。

書誌情報も、この待ち時間にウェブから取らせてDBに紐づけた。 最後に、履歴ファイルの記載を実態に合わせ、依存パッケージとスクリプト構成のドキュメントも更新させた。

直したルールは過去の本にも当て直す

新しいルールは、今回の1冊だけのものではない。 先に取り込んだ3冊にも同じ断片が残っているはずだった。

改良版で3冊とも差分を出させた。 1冊目は2件だった。 2冊目は1件で、消えるのが「V」1文字だけだった。 周辺の文脈を広めに出させたら、チェックマークをOCRが読み違えたもので、本文ではなかった。 3冊目は取りこぼしゼロ。

全文検索インデックスの再構築を待つ間に履歴ファイルを書かせ、待ち終わってから表示を確認させた。 スクリーンショットが1回タイムアウトしたので、撮り直させた。

後始末の判定を足すたびに、過去の全冊へ当て直す作業がついてくる。 ルールを1冊ぶんで止めると、蔵書のなかで品質がまだらになる。

スキャン済みPDF6件を中身から一括リネームする

同じ朝、スキャナの保存先に溜まっていたPDFを6件まとめてリネームさせた。

やっていることは単純で、先頭ページを画像に起こし、画像認識で書名を読み、連番のファイル名に付け直す。 6件を並列で処理させた。 全件で表紙の書名と奥付の書名が一致していて、誤判定はゼロだった。

ついでに、コマンドが引数なしで見にいくフォルダを、いま使っているスキャナの保存先に更新させた。 次からはパスを渡さずに済む。

取り込み作業から残ったこと

  • 3冊通しても3つ目のコマンド名を忘れていた。手順を頭で覚える運用は、その時点で失敗している。連鎖にして初めて手順になる
  • 汎用化したコードの検証は、処理済みのデータへの dry-run が一番安い。差分がゼロか、説明のつく差分だけかを見ればいい
  • 消す作業には、消す前に「消えたら何が失われるか」を確かめる手を1つ挟む。節見出しの画像は、本文側に見出しが残っていることを確かめてから消した