[{"data":1,"prerenderedAt":275},["ShallowReactive",2],{"content-/book-knowledge-base-batch-import":3,"all-pages-for-dir":252,"related-/book-knowledge-base-batch-import":253,"og-image-/book-knowledge-base-batch-import":274},{"id":4,"title":5,"body":6,"category":232,"concepts":233,"description":234,"extension":235,"meta":236,"navigation":237,"ogImage":233,"path":238,"project_name":239,"published":240,"publishedAt":241,"seo":242,"source":243,"stem":244,"tags":245,"todo":233,"unpublished":240,"updatedAt":233,"__hash__":251},"pages/2026-08/2026-08-18/book-knowledge-base-batch-import.md","書籍ナレッジベースに7冊を追加取り込みして、文字化けとKindleキャプチャの誤検知を直した日",{"type":7,"value":8,"toc":220},"minimark",[9,13,16,20,23,36,39,42,45,49,52,55,66,69,72,75,78,81,96,107,110,117,127,130,134,137,140,143,151,154,157,161,164,175,178,181,184,187,190,193,196,199],[10,11,12],"p",{},"朝いちばんに考えていたのは、運営しているサイトの中身を増やすことだった。手を動かす前に、手元の蔵書DBに何が入っているかを数えさせた。386冊。思っていたより溜まっている。",[10,14,15],{},"ところが、その一覧が読めない。Windowsのコンソールがcp932で書名を吐き出すので、画面が化けた文字で埋まった。UTF-8のファイルに書き出させて開き直したら普通に読めた。数分の回り道で済んだが、この日はもう一度、同じ理由で同じことをやり直すことになる。",[17,18,19],"h2",{"id":19},"どの本なら自動取り込みを通せるか",[10,21,22],{},"コンテンツの元にしたい本を10冊まで絞ったところで、原本の在処を確認させた。ここで数が減った。",[24,25,26,30,33],"ul",{},[27,28,29],"li",{},"PDFで手元にある6冊は、そのまま通せる",[27,31,32],{},"Kindleの4冊のうち2冊は、ブラウザのCloud ReaderでもPCアプリでも開けない。スマホとタブレットのアプリ専用で、過去に取り込みを試したときの除外マークが残っていた",[27,34,35],{},"Kindleの残る2冊のうち1冊は未購入だった。DBにはサンプルだけが入っていて、そのフラグが立っていた",[10,37,38],{},"実行できるのは7冊。Kindleのライブラリに入っていることと、自動取り込みのパイプラインを通せることは別だった。",[10,40,41],{},"作業の置き場所も決めた。抽出と成果物づくりはサイト側のセッションに残し、取り込みそのものは蔵書DB側のリポジトリで別セッションを立てる。",[10,43,44],{},"決まったところで、この日やることをGoogleタスクに2件積ませた。取り込みの作業そのものと、その計画が存在すること。期日は今日。ところが2件目に期日が付いていない。見たらタスクリストのIDを打ち間違えていた。正しいIDで入れ直させ、2件とも実在と期日をAPIで確認した。",[17,46,48],{"id":47},"ocrを回している50分の使い方","OCRを回している50分の使い方",[10,50,51],{},"取り込みの本体は蔵書DB側のセッションで始めた。最初にやらせたのは重複チェック。ここでまた画面が化けた。DBの照合結果が読めないので、文字化けしない形でやり直させた。7冊とも未登録だった。",[10,53,54],{},"OCRは1ページあたり1.8秒ほどで進む。6冊で50分。GPUに空きがあり、しかもOCRが工程のなかで最も長い。6冊を直列で回すバッチを先にバックグラウンドへ流し、待ち時間を別の作業に充てた。",[24,56,57,60,63],{},[27,58,59],{},"Amazon側のメタデータ収集（原本ファイルの番号が取れればPDFを開かずに済む）",[27,61,62],{},"図のリネームと目次抽出のヘルパー作り",[27,64,65],{},"Kindle1冊のキャプチャ開始",[10,67,68],{},"メタデータで1つ気づいたことがある。6冊のうち2冊は、Amazon側の登録が後年の別版を指していた。手元のスキャンは旧版なので、書誌はOCRのあと奥付で取り直すことにした。実際、1冊目は表紙に刷られた出版社が事前の想定と違っていて、実物に合わせて直した。",[17,70,71],{"id":71},"章の見出しで4回つまずいた",[10,73,74],{},"OCRが終わった本は、まず素のチャンクとしてDBに入る。1冊目は170チャンク、図219枚。これを目次と突き合わせて章と節にまとめ直す工程で、ずっと足を取られた。",[10,76,77],{},"最初の設計は素直だった。チャンクの章フィールドに節見出しがそのまま入っているので、目次テキストと自動照合すればいい。汎用のスクリプトを書かせて回した。",[10,79,80],{},"そこから先が、直すたびに別の壊れ方をする。",[82,83,84,87,90,93],"ol",{},[27,85,86],{},"マッチ率を上げようと本文冒頭の短い行も見出し候補に入れたら、誤マッチが出た。候補を「チャンクの冒頭にあり、かつ一致率が高いもの」に限定した",[27,88,89],{},"2冊目では、ページ上部の柱（ランニングヘッダー）が章タイトルと誤マッチした。柱は連続したページに繰り返し出るので、章見出しは短いチャンクだけに限る条件を足した",[27,91,92],{},"それでも足りず、章エントリの照合そのものをやめた。節だけで区切り、章扉は境界検出で分ける方式に変えたら、88/100が一致して章境界も正しく取れた",[27,94,95],{},"4冊目は目次エントリが「フェーズ名＋サブタイトル」の合成になっていて、本文中の見出しと一致しない。目次ファイルの記法を変え、表示名と照合キーを分けられるようにした",[97,98,103],"pre",{"className":99,"code":101,"language":102},[100],"language-text","# 目次ファイルの1行（表示名|照合キー）\n第2フェーズ 数字で確かめる|数字で確かめる\n","text",[104,105,101],"code",{"__ignoreMap":106},"",[10,108,109],{},"途中で、まとめた結果のチャンクが大きくなりすぎることにも気づいた。統合に6000字の上限を入れ、上限を入れる前に通していた1冊目と3冊目は取り込みからやり直した。1冊目は170チャンクが41にまとまった。",[17,111,113,116],{"id":112},"の入ったファイル名で1冊だけバッチが落ちた",[104,114,115],{},"["," の入ったファイル名で、1冊だけバッチが落ちた",[10,118,119,120,123,124,126],{},"6冊のバッチのうち、4冊目だけが",[104,121,122],{},"rc=1","で落ちていた。ログを見るとファイル名の照合ミス。実ファイル名を確かめたら、名前に",[104,125,115],{},"が入っていた。Git BashのMSYS2はパスを自動変換するが、この文字を含む引数では変換が効かず、渡した先が別のパスとして扱われていた。",[10,128,129],{},"走っているバッチの邪魔をしたくないので、6冊目のOCR完了を待って4冊目を自動で流すジョブを組み、そちらはWindowsのパス表記で渡した。これで通った。",[17,131,133],{"id":132},"kindleが進んでいないと言い張る","Kindleが「進んでいない」と言い張る",[10,135,136],{},"並行して走らせていたKindleのキャプチャが、この日いちばん時間を食った。",[10,138,139],{},"1回目は位置56/258で止まった。「位置が進んでいない」という判定で自動停止したらしい。ただ、画面のページ自体は進んでいた。",[10,141,142],{},"PDFを片付けてから再開させ、また止まった。今度は位置53。実際の画面を見たら、見開き2ページ表示で印刷ページの60から61を映している。手でページを送ってみると、ページはちゃんと進む。それなのに位置の表示は53のまま動かない。",[10,144,145,146,150],{},"原因はここだった。固定レイアウトの本では、位置の数字がページ送りに追従しない。",[147,148,149],"strong",{},"停滞の判定を位置だけで見ていたので、ページが進んでいるのに止まったと誤検知していた","。ブラウザ拡張の判定を最小限だけ直させ、拡張をリロードしてタブを読み込み直したら、36ページ、129ページと進み続けた。",[10,152,153],{},"最後は奥付に到達して正常に終わった。137ページ取れた。ただし3回に分けて走らせていたので、結合が要る。中身を確かめたら、3回目のバッチが表紙から始まる完全な1周だった。リロードで先頭に戻っていたためで、結局そのバッチだけを採用した。",[10,155,156],{},"見開き画像は1ページあたりの解像度が落ちる。心配だったので、1枚だけOCRにかけて品質を見てから全部を流した。この誤検知はその場しのぎで済ませたくなかったので、issueとして記録に残させた。",[17,158,160],{"id":159},"マンガ本で消してはいけないもの","マンガ本で、消してはいけないもの",[10,162,163],{},"7冊目のマンガ本では、逆に「やらなくていいこと」をやりかけた。",[24,165,166,169,172],{},[27,167,168],{},"図のファイル名パターンが他と違ったので専用のリネームを走らせたが、インポータ側がKindleの命名を内部で処理していたので不要だった。誤って変えた2件を元に戻した",[27,170,171],{},"章扉が見出し記法になっておらず、前のチャンクに吸収されていた。分割しようとしたら、分割対象を目次のテキストのほうに当ててしまった。手で継ぎ接ぎせず、取り込みからやり直してクリーンな状態に戻した",[27,173,174],{},"クリーンアップで装飾図の除去は行わなかった。マンガはパネル自体が本文なので、消すと中身が消える",[10,176,177],{},"PDFの6冊は、図の判定用にコンタクトシートを31枚作らせ、目視で装飾図を選り分けた。装飾図のリストを作ってから6冊まとめてクリーンアップし、全文検索インデックスの再構築は最後に1回だけ回した。仕上げに残ノイズを見ると2冊に柱が残っていたので、パターンを確認して除去した。適用前に差分を目で見て確かめてから通した。",[10,179,180],{},"Web側の表示も見て、6冊とも「整」「済」のバッジが付き、図がR2から出ていることを確認した。これで7冊すべてが終わった。",[17,182,183],{"id":183},"買う理由を思い出せない本があった",[10,185,186],{},"昼前、別のところでつまずいた。Googleタスクに前から積んであった「買って読む」グループの中身を確認したときのことだ。3グループで7〜8冊ある。1冊はすでに電子化済みで買う必要がなく、1冊は手持ちが古い版だと分かった。",[10,188,189],{},"引っかかったのは投資情報誌だった。なぜこれを買うことにしたのか、自分で思い出せない。競合として見るつもりだったのだろうか。",[10,191,192],{},"調べさせたら、理由は競合ではなかった。読者リサーチ用の資料として挙がっていた。しかもその必要性は、まだ確定していない読者像の仮置きにぶら下がっていた。いらない気がしていたのは、根拠のほうが浮いていたからだった。",[10,194,195],{},"この経緯をメモに残させた。「加えて」と頼んだので、既存の記述は1文字も消さず、該当項目の下とタスクのメモ末尾の2か所に足す形にしてもらった。",[17,197,198],{"id":198},"学び",[24,200,201,208,211,214,217],{},[27,202,203,204,207],{},"文字化けは2回起きた。",[147,205,206],{},"Windowsのコンソールに日本語を吐かせず、最初からUTF-8のファイルに書き出させる","のが結局いちばん早い",[27,209,210],{},"見出しの自動照合は、条件を足して精度を上げるより、当てにいく対象を減らしたほうが効いた。章をあきらめて節だけで区切った瞬間に一致率が上がった",[27,212,213],{},"「止まった」という自動判定は、何を根拠に止まったと言っているかを疑う。位置の数字が動かないことと、ページが進んでいないことは同じではない",[27,215,216],{},"Kindleのライブラリに入っている本が、自動取り込みを通せるとは限らない。買う前に経路を確かめる",[27,218,219],{},"買う予定の本は、書名だけでなく「何のために要るのか」をメモに残しておかないと、あとから自分で判断できない",{"title":106,"searchDepth":221,"depth":221,"links":222},2,[223,224,225,226,228,229,230,231],{"id":19,"depth":221,"text":19},{"id":47,"depth":221,"text":48},{"id":71,"depth":221,"text":71},{"id":112,"depth":221,"text":227},"[ の入ったファイル名で、1冊だけバッチが落ちた",{"id":132,"depth":221,"text":133},{"id":159,"depth":221,"text":160},{"id":183,"depth":221,"text":183},{"id":198,"depth":221,"text":198},"dev",null,"蔵書386冊のDBに7冊を足す作業で、コンソールの文字化け、章見出しの誤マッチ、固定レイアウト本での停滞誤検知に順につまずいた。詰まるたびに直していった一日の記録","md",{},true,"/book-knowledge-base-batch-import","book-knowledge-base",false,"2026-08-18T00:00:00.000Z",{"title":5,"description":234},"make-diary","2026-08/2026-08-18/book-knowledge-base-batch-import",[246,247,248,249,250],"ナレッジベース","OCR","Kindle","タスク管理","Turso","nauwNdOJZzzp5aSOmU2LyyGnjPnMyF-9kfWqJIjI3hQ",[],[254,258,262,266,270],{"title":255,"path":256,"publishedAt":257},"584ページのスキャンPDFをOCRしてナレッジベースに入れ、サイトの解説コンテンツに変えるまで","/book-ocr-to-web-content","2026-08-02T00:00:00.000Z",{"title":259,"path":260,"publishedAt":261},"Kindle蔵書のOCR取り込みを複数バッチ並列で回した一日","/kindle-ocr-batch-pipeline","2026-06-22T00:00:00.000Z",{"title":263,"path":264,"publishedAt":265},"Kindle取込パイプラインを並列化して1日に8冊取り込んだ","/kindle-import-8books-parallel-pipeline","2026-06-21T00:00:00.000Z",{"title":267,"path":268,"publishedAt":269},"Kindle 5冊を yomitoku-kindle で並列パイプラインに流して1時間で完走させた話","/yomitoku-kindle-batch-import","2026-06-19T00:00:00.000Z",{"title":271,"path":272,"publishedAt":273},"Kindle Cloud Readerを巡回スクショ→OCR→Tursoまで自動化する/yomitoku-kindleパイプライン完成","/yomitoku-kindle-pipeline","2026-06-18T00:00:00.000Z","https://log.eurekapu.com/favicon.svg",1787123773135]