Kindle電子書籍をOCRで蔵書DBに取り込む新コマンドを作った
手元にあるKindle書籍の一冊が、蔵書DBにもう入っているのかどうか、急に怪しくなった。スクリーンショットを渡し、まず取り込み済みかを確認してもらう。
返ってきたのは、検索対象351冊のどこにも見当たらない、という答えだった。取り込んだつもりで、実は手つかずのままだった一冊が見つかった。
二系統のルートを持つ新コマンド
Kindle書籍のOCR取り込みには、これまで決まった型がなかった。そこで、二系統のルートを持つ新しいコマンドを設計することにした。
- (A) Kindle Cloud Readerが普通に開ける書籍は、Chrome拡張でページを巡回しながら撮影するルート
- (B) Cloud Readerが「申し訳ありません」と拒否してくる書籍は、Kindle for PCアプリとスクリーンショットアプリを組み合わせて、1ページ目から最終ページまで手動で巡回撮影するルート
どちらを通っても、最終的には既存のOCR→DB登録パイプラインに合流させる。取り込み後は蔵書棚(シェルフ)とAmazonの書誌情報にも紐付ける。
最後に必ず目次整形とセクション統合のコマンドまで通す。ここを省略すると、章と章の境目が崩れたまま棚に並ぶことになる。
撮影の手段は書籍によって変わる。だが後工程の行き先を一本化しておけば、どちらのルートを通っても困らない。
拒否されると思っていたら
対象の書籍はASINから未取り込みだと確定した。Cloud Readerのタブがまだ開いていなかったので、新規に開いて読み込み状態を確認する。
普通に開いた。フローティングパネルの表示も問題ない。拒否されるルートBを覚悟していたぶん、拍子抜けした。ルートAで進める。
表示をLightテーマに切り替え、横書きの技術書だったのでページ送りの向きをltrに設定した。
別ウィンドウで撮影を開始する。全523ロケーション、見積もりは200ページ前後、所要10〜15分。バックグラウンドで完了通知を待つ体制に入った。
100枚を過ぎたところで
撮影の進捗が100枚に達したタイミングで、待つのをやめたくなった。200ページ前後の見積もりなら、ちょうど半分。ここまでの分だけ先にOCRを回して、非同期で進められないか。そう切り出した。
理屈のうえでは分割できそうに見えた。撮影済みの前半だけをOCRに回し、残り半分は後追いで処理すればいい。
だが確認してもらうと、そう単純な話ではなかった。OCR後のセクション統合処理は「章末のページ」と「次章冒頭のページ」をまたいで結合するロジックで動いている。撮影を前半・後半で区切ってDB投入まで進めてしまうと、その境目にちょうど章の切れ目が来ていた場合、統合が正しくかからない恐れがある。分割はおすすめしない、という結論だった。
一括処理で進めることにして、了解した。ただ、それでも少しだけ食い下がって、OCRだけは先にやってもらえないかと頼み直した。DB投入やセクション統合まで進めず、OCRの実行だけを前倒しする案だった。
ところが、その判断が意味を持つ前に、通知が鳴った。523ロケーションぶん、262ページの撮影が、ちょうど終わっていた。分割の是非を検討している間に、本体の作業のほうが先にゴールしていた。部分OCRの出番は結局なかった。
一気通貫で流す
262枚の画像は正規の保存先へ移動させた。撮影中はDownloadsフォルダに溜まっていくだけだったものを、蔵書DBが参照する場所へ移して、書籍IDを決めた。
OCRをバックグラウンドで開始させる。見積もりは5〜6分。
終わったところで、方向の誤判定がないかだけ確認してもらう。1ページ目が表紙になっていれば向きは合っている。合っていた。
中間で生成されたjpgの削除と、抽出した図版309枚のリネームも済ませてもらう。DB投入の前に、出版年などの書誌情報はAmazonのページで確認した。ここはagent-browserスキルでブラウザを操作させ、目次のページまで辿ってもらった。
目次が確認できたところで、DB投入を実行させる。262ページが110チャンクに整理され、図版309枚がストレージにアップロードされた。蔵書棚とAmazon書誌情報への紐付けを済ませ、検索が機能しているかをテストする。2文字の単語で検索が0件になったが、これはFTSのトライグラム制約による仕様通りの挙動で、バグではない。
目次整形とセクション統合のコマンドは、サブエージェントにバックグラウンドで任せた。一度、「バックグラウンドスクリプトの完了待ち」の状態で止まっているのに気づき、再開させて完了まで見届けた。
完了報告を書いてもらう前に、DBの中身とissueファイルの点検も挟ませることにした。すると1箇所だけノイズが混入していたことが分かった。直させたうえで、取り込み完了を報告してもらった。
クリーンアップとブラウザでの目視確認
取り込みが終わったところで、続けてクリーンアップとアプリの起動もまとめて頼んだ。OCR済みの内容を分析して検索品質を上げる後処理コマンドを走らせる番だった。
対象は33チャンク。5バッチに分割し、それぞれのサブエージェントには担当するページ範囲だけを渡した。中身はDBから各自読ませる設計にして、メインの文脈を圧迫しないようにした。
5バッチとも並列で起動させる。同時に、空いていたポートでdevサーバーを立ち上げ、書籍ページをブラウザで開いて進捗を目で追えるようにした。
先に終わったバッチは、対象チャンクに図版がなく更新0件。初回コンパイルに時間がかかっていたdevサーバーを開き直すと、表紙と目次はどちらも正しく表示されていた。
別のバッチでは8ページ目のノイズが1件だけ除去されたと報告が来た。実物を確認しに行く。「よさそ」で途切れていた地の文が「際に立って」へ、違和感なくつながっていた。
残りのバッチも、181枚の画像がすでに適正だったものを含めて、次々と完了報告が届く。
5バッチすべてが終わったところで数えると、更新は8ページ目のノイズ除去1件だけだった。検索テストとクリーンアップ履歴の記録を済ませ、最後にもう一度ブラウザで8ページ目を開いた。ノイズは消え、地の文はやはり自然につながっていた。
残ったままの疑問
一冊が無事に棚へ収まった。目次は整い、ノイズも消え、検索も効く。
ただ、100枚のところで「分割したい」と思った判断そのものは、間違っていたとは言い切れない。急かしたのは自分で、待たせたのはパイプラインの都合だった。
今回はたまたま撮影の完了とタイミングが重なって、部分OCRを出す必要がなくなっただけだ。次にもっと分厚い本が来て、撮影に数十分かかるようなら、同じように運任せで済むとは思えない。章の境目を避けて安全に分割できる仕組みを、いずれ作ることになる気がしている。