[{"data":1,"prerenderedAt":405},["ShallowReactive",2],{"content-/kaikei-5th-batch-import":3,"all-pages-for-dir":403,"og-image-/kaikei-5th-batch-import":404},{"id":4,"title":5,"body":6,"category":385,"description":386,"extension":387,"meta":388,"navigation":389,"ogImage":390,"path":391,"project_name":392,"published":393,"publishedAt":394,"seo":395,"stem":396,"tags":397,"todo":390,"unpublished":393,"updatedAt":390,"__hash__":402},"pages/2026-06/2026-06-19/kaikei-5th-batch-import.md","会計書籍10冊を一気にDB取り込み — 紛らわしい3冊のPDF実体確認とOCRバッチ運用",{"type":7,"value":8,"toc":376},"minimark",[9,22,25,29,32,42,45,49,56,68,71,109,120,123,127,134,141,251,258,262,265,268,290,299,302,305,311,321,325,332,339,346,349,369,372],[10,11,12,13,17,18,21],"p",{},"朝5時40分、コーヒーをいれる前にターミナルを開いて ",[14,15,16],"code",{},"/import-batch"," を叩いた。会計5thバッチ、10冊を一気にDBへ突っ込む回。終わったのは7時50分。約2時間で ",[14,19,20],{},"+3,354 チャンク","、DB全体は 268冊 / 39,129 チャンクに着地した。",[10,23,24],{},"毎回バッチを回すたびに違う罠に踏むので、今回踏んだ罠と、それを避けるためにスクリプトに仕込んだ仕掛けを残しておく。",[26,27,28],"h2",{"id":28},"取り込んだ10冊",[10,30,31],{},"会計系の参考書・教科書類が中心。書名はぼかしておくが、内訳は以下の book_id。",[33,34,39],"pre",{"className":35,"code":37,"language":38},[36],"language-text","choukousoku-kaikei-benkyo\nbca-2kyu-koshiki-4th\nmba-yori-kantan-kessan\nsetsurei-shihon-renketsu\nfusei-kaikei-chosa-manual\nshin-kaikei-zukai-jiten\nsukkiri-boki-3kyu\nboki-kiso-1-2-gekan\natarashii-boki-3kyu\njissen-zaimu-sosa\n","text",[14,40,37],{"__ignoreMap":41},"",[10,43,44],{},"合計PDF サイズは約1GB。OCR バッチで md 化したあと、Turso にチャンク分割して投入する流れは前回と同じ。",[26,46,48],{"id":47},"罠1-ファイル名と-amazon-タイトルが食い違う3冊","罠1: ファイル名と Amazon タイトルが食い違う3冊",[10,50,51,52,55],{},"着手前、",[14,53,54],{},"amazon_metadata"," テーブルから PDF パスを引き当てるところで違和感を覚えた。No117 / No240 / No315 の3冊が、ファイル名から想像できるタイトルと Amazon 側のタイトルが噛み合っていない。",[10,57,58,59,63,64,67],{},"そのまま投入すると、",[60,61,62],"strong",{},"別書籍を重複として弾いてしまう","か、",[60,65,66],{},"同じ書籍を二重登録する","かのどちらかをやらかす。Claude Code に「PDF の中身（1ページ目）をテキスト抽出して実体タイトルを確認して」と頼んで、3冊それぞれの実物を当てに行ってもらった。",[10,69,70],{},"結果、こうだった。",[72,73,74,85,99],"ul",{},[75,76,77,80,81,84],"li",{},[60,78,79],{},"No117"," = 『スッキリわかる日商簿記3級 第10版』 → ",[14,82,83],{},"sukkiri-boki-3kyu","（Amazonと一致）",[75,86,87,90,91,94,95,98],{},[60,88,89],{},"No240"," = 『新しい日商簿記3級 テキスト&問題集』 → ",[14,92,93],{},"atarashii-boki-3kyu","（",[60,96,97],{},"別書籍。重複ではない","）",[75,100,101,104,105,108],{},[60,102,103],{},"No315"," = 『簿記基礎 I・II 下巻』 → ",[14,106,107],{},"boki-kiso-1-2-gekan","（ファイル名通り）",[10,110,111,112,115,116,119],{},"特に No117 と No240 は両方とも「簿記3級の教科書」というカテゴリで近接していたので、ファイル名の ",[14,113,114],{},"boki-3kyu"," 部分を見て「これ重複じゃないか？」と一瞬疑った。中身を見たら、章立ても出版社も違う ",[60,117,118],{},"完全に別の書籍"," だった。",[10,121,122],{},"ファイル名・Amazon メタデータ・PDF 本文の3点で照合しないと、こういう「似ているが別物」は絶対取りこぼす。今回は3冊とも別物として正しく登録できた。",[26,124,126],{"id":125},"罠2-ocr-中間-jpg-がディスクを食い潰す","罠2: OCR 中間 jpg がディスクを食い潰す",[10,128,129,130,133],{},"前回バッチで ",[14,131,132],{},"disk full"," を踏んでいた。yomitoku が PDF ページを一旦 jpg に展開してから OCR にかける構造で、4000ページ規模だと中間ファイルが10GB単位で残る。",[10,135,136,137,140],{},"今回は OCR バッチスクリプトに、",[60,138,139],{},"1冊終わるたびに中間 jpg を削除する処理"," を組み込んだ。方針はシンプルで、こんな雰囲気。",[33,142,146],{"className":143,"code":144,"language":145,"meta":41,"style":41},"language-bash shiki shiki-themes vitesse-light vitesse-light","for book_id in \"${BOOKS[@]}\"; do\n  run_yomitoku \"$book_id\"\n  rm -rf \"$WORK_DIR/$book_id/jpg/\"  # ← これだけ\n  echo \"[cleanup] $book_id intermediate jpg removed\"\ndone\n","bash",[14,147,148,195,210,231,245],{"__ignoreMap":41},[149,150,153,157,161,164,168,172,176,179,183,186,189,192],"span",{"class":151,"line":152},"line",1,[149,154,156],{"class":155},"sHkkW","for",[149,158,160],{"class":159},"s4oTP"," book_id",[149,162,163],{"class":155}," in",[149,165,167],{"class":166},"sMJiu"," \"",[149,169,171],{"class":170},"shFtX","${",[149,173,175],{"class":174},"sdGka","BOOKS",[149,177,178],{"class":170},"[",[149,180,182],{"class":181},"stQ0i","@",[149,184,185],{"class":170},"]}",[149,187,188],{"class":166},"\"",[149,190,191],{"class":170},";",[149,193,194],{"class":155}," do\n",[149,196,198,202,204,207],{"class":151,"line":197},2,[149,199,201],{"class":200},"senZ8","  run_yomitoku",[149,203,167],{"class":166},[149,205,206],{"class":174},"$book_id",[149,208,209],{"class":166},"\"\n",[149,211,213,216,220,222,225,227],{"class":151,"line":212},3,[149,214,215],{"class":200},"  rm",[149,217,219],{"class":218},"snbK4"," -rf",[149,221,167],{"class":166},[149,223,224],{"class":174},"$WORK_DIR/$book_id/jpg/",[149,226,188],{"class":166},[149,228,230],{"class":229},"sxvE3","  # ← これだけ\n",[149,232,234,238,240,243],{"class":151,"line":233},4,[149,235,237],{"class":236},"sz8Xr","  echo",[149,239,167],{"class":166},[149,241,242],{"class":174},"[cleanup] $book_id intermediate jpg removed",[149,244,209],{"class":166},[149,246,248],{"class":151,"line":247},5,[149,249,250],{"class":155},"done\n",[10,252,253,254,257],{},"1時間40分の OCR の間、ディスクは94GB空きで安定し続けた。前回みたいに途中で ",[14,255,256],{},"No space left on device"," を吐かれて、原因切り分けに30分溶かす展開を避けられた。",[26,259,261],{"id":260},"ocr-進行とチャンク化の結果","OCR 進行とチャンク化の結果",[10,263,264],{},"OCRバッチを 06:06 にバックグラウンド起動して、07:46 に全10冊完走。バッチ起動中はずっと別のことができるので、待ち時間の体感はゼロに近い。",[10,266,267],{},"完了後のチャンク数を眺めて、面白い偏りに気づいた。",[72,269,270,279],{},[75,271,272,273,275,276],{},"最大: ",[14,274,107],{}," 490md → ",[60,277,278],{},"465 chunks",[75,280,281,282,285,286,289],{},"最小: ",[14,283,284],{},"choukousoku-kaikei-benkyo"," 175md → ",[60,287,288],{},"28 chunks","（merged 18, skip 11）",[10,291,292,294,295,298],{},[14,293,284],{}," は元のページ数も短く、かつ1ページあたりの文字密度も薄いので、",[14,296,297],{},"/restructure-book"," のセクション集約が強めにかかった。md 175枚 → チャンク 28個まで圧縮されている。短い本に対しては「むやみに細切れにせず、章単位でまとめる」挙動になっていて、検索体験としても正しい。",[10,300,301],{},"逆に簿記基礎の下巻は仕訳例が大量に並ぶ構造で、ページ単位の独立性が高い。結果として md 枚数とチャンク数がほぼ1:1で対応する形に落ち着いた。",[26,303,304],{"id":304},"バッチ後の状態",[33,306,309],{"className":307,"code":308,"language":38},[36],"DB全体: 268冊 / 39,129 チャンク\n今回追加: +10冊 / +3,354 チャンク\n所要時間: 約2時間（05:40 → 07:50）\n",[14,310,308],{"__ignoreMap":41},[10,312,313,316,317,320],{},[14,314,315],{},"9cdb6c7"," でコミットして、会計5thはクローズ。次の候補として残っていた ",[60,318,319],{},"税務3rd（残15冊）"," が同じペースで回せそうな分量なので、続けて投げる気でいた。",[26,322,324],{"id":323},"次は税務3rdじゃなく-kindle-に切り替え","次は税務3rdじゃなく Kindle に切り替え",[10,326,327,328,331],{},"終わったあと「次どれ行きます？」と聞いたら、税務3rdじゃなくて ",[60,329,330],{},"Kindle 蔵書の取り込みを進めたい"," という返事だった。",[10,333,334,335,338],{},"そっちは PDF 自炊した本ではなく、Kindle Cloud Reader からスクショ経由で取り込む別パイプライン（",[14,336,337],{},"/yomitoku-kindle","）。未OCR は464冊残っていて、ベイズ加重評価の上位から優先取り込みする戦略になっている。",[10,340,341,342,345],{},"最初に試運転として『会計の世界史』（★4.6・1,517レビュー）を選んで取り込みに入ろうとしたが、Chrome DevTools MCP の接続でつまずいて止まった。そこからは「Kindle 蔵書全体の優先順位付けをどう設計するか」の戦略計画書を書く方向に切り替えて、",[14,343,344],{},"memo/2026-06-19/kindle-import-priority-plan.md"," にまとめ直した。",[26,347,348],{"id":348},"このバッチ運用で固まってきたこと",[72,350,351,357,363],{},[75,352,353,356],{},[60,354,355],{},"3点照合は最初にやる",": ファイル名・Amazon メタ・PDF 本文。1冊でもズレていたら、その時点で止めて確認する。バッチが2時間走った後に「実は重複でした」が一番つらい",[75,358,359,362],{},[60,360,361],{},"中間ファイルの寿命をスクリプトに織り込む",": 「手で消せばいい」は手が回らなくなる。1冊終わるたびに自動で消すフックを入れておく",[75,364,365,368],{},[60,366,367],{},"OCR はバックグラウンド前提で組む",": 90〜120分かかる処理を待つ時間に他のタスクを進められると、体感の所要時間が半分以下になる",[10,370,371],{},"朝一の2時間で10冊片付くと、その日の残り時間の使い方がだいぶ自由になる。",[373,374,375],"style",{},"html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .snbK4, html code.shiki .snbK4{--shiki-default:#A65E2B;--shiki-dark:#A65E2B}html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":41,"searchDepth":197,"depth":197,"links":377},[378,379,380,381,382,383,384],{"id":28,"depth":197,"text":28},{"id":47,"depth":197,"text":48},{"id":125,"depth":197,"text":126},{"id":260,"depth":197,"text":261},{"id":304,"depth":197,"text":304},{"id":323,"depth":197,"text":324},{"id":348,"depth":197,"text":348},"dev","/import-batchで会計5thバッチ10冊を約2時間で取り込んだログ。ファイル名とAmazonタイトルが食い違う3冊のPDF実体を先に確認し、中間jpg自動削除でディスク枯渇を回避。OCR1時間40分で+3,354チャンク。","md",{},true,null,"/kaikei-5th-batch-import","book-knowledge-base",false,"2026-06-19T00:00:00.000Z",{"title":5,"description":386},"2026-06/2026-06-19/kaikei-5th-batch-import",[392,398,399,400,401],"OCR","yomitoku","Turso","import-batch","mZxnXefq-6ywngVZZwOJbyT4Kml4ejAXyFcggyFnKok",[],"https://log.eurekapu.com/og/blog/kaikei-5th-batch-import.png?v=2026-06-19T00%3A00%3A00.000Z&title=%E4%BC%9A%E8%A8%88%E6%9B%B8%E7%B1%8D10%E5%86%8A%E3%82%92%E4%B8%80%E6%B0%97%E3%81%ABDB%E5%8F%96%E3%82%8A%E8%BE%BC%E3%81%BF%20%E2%80%94%20%E7%B4%9B%E3%82%89%E3%82%8F%E3%81%97%E3%81%843%E5%86%8A%E3%81%AEPDF%E5%AE%9F%E4%BD%93%E7%A2%BA%E8%AA%8D%E3%81%A8OCR%E3%83%90%E3%83%83%E3%83%81%E9%81%8B%E7%94%A8&author=Kei%20Komatsu&sig=ad256ceb7f09428d",1782176331260]