[{"data":1,"prerenderedAt":421},["ShallowReactive",2],{"content-/yomitoku-and-textbook-ocr":3,"all-pages-for-dir":419,"og-image-/yomitoku-and-textbook-ocr":420},{"id":4,"title":5,"body":6,"category":401,"description":402,"extension":403,"meta":404,"navigation":77,"ogImage":405,"path":406,"project_name":407,"published":408,"publishedAt":409,"seo":410,"stem":411,"tags":412,"todo":405,"unpublished":408,"updatedAt":405,"__hash__":418},"pages/2026-05/2026-05-15/yomitoku-and-textbook-ocr.md","yomitoku 0.13.0 アップグレードと自炊書籍の OCR 取り込み",{"type":7,"value":8,"toc":393},"minimark",[9,13,17,22,34,37,97,107,110,113,116,123,267,270,273,277,284,287,290,294,301,304,336,339,342,346,352,363,366,369,386,389],[10,11,5],"h1",{"id":12},"yomitoku-0130-アップグレードと自炊書籍の-ocr-取り込み",[14,15,16],"p",{},"朝、GitHub の release ページを開いたら yomitoku の v0.13.0 が出ていた。手元のローカルは 0.10.1 のまま放置していたので、まず環境を上げるところから始めて、その勢いで自炊した1冊（235 ページの問題集）をまるごと取り込んだ。途中、torch の入れ替わりと章タブの混入と Amazon メタデータの古いデータと、3つ転んだ。",[18,19,21],"h2",{"id":20},"yomitoku-を-0130-に上げる","yomitoku を 0.13.0 に上げる",[14,23,24,25,29,30,33],{},"pyproject.toml の依存を書き換えて pip でインストール直してもらったつもりが、画面の進捗バーを見ていて違和感を拾った。",[26,27,28],"code",{},"Downloading torch-2.12.0-cp311-cp311-win_amd64.whl"," と表示されている。手元には CUDA 11.8 でビルドされた ",[26,31,32],{},"torch==2.7.1+cu118"," を入れていたはずなのに、CPU 版が降ってきていた。",[14,35,36],{},"GPU 推論が前提の処理を CPU で回すと、235 ページの本 1 冊で 1 時間コースになる。すぐ止めて、pyproject.toml を書き直してもらった。",[38,39,44],"pre",{"className":40,"code":41,"language":42,"meta":43,"style":43},"language-toml shiki shiki-themes vitesse-light vitesse-light","[[tool.uv.index]]\nname = \"pytorch-cu118\"\nurl = \"https://download.pytorch.org/whl/cu118\"\nexplicit = true\n\n[tool.uv.sources]\ntorch = { index = \"pytorch-cu118\" }\ntorchvision = { index = \"pytorch-cu118\" }\n","toml","",[26,45,46,54,60,66,72,79,85,91],{"__ignoreMap":43},[47,48,51],"span",{"class":49,"line":50},"line",1,[47,52,53],{},"[[tool.uv.index]]\n",[47,55,57],{"class":49,"line":56},2,[47,58,59],{},"name = \"pytorch-cu118\"\n",[47,61,63],{"class":49,"line":62},3,[47,64,65],{},"url = \"https://download.pytorch.org/whl/cu118\"\n",[47,67,69],{"class":49,"line":68},4,[47,70,71],{},"explicit = true\n",[47,73,75],{"class":49,"line":74},5,[47,76,78],{"emptyLinePlaceholder":77},true,"\n",[47,80,82],{"class":49,"line":81},6,[47,83,84],{},"[tool.uv.sources]\n",[47,86,88],{"class":49,"line":87},7,[47,89,90],{},"torch = { index = \"pytorch-cu118\" }\n",[47,92,94],{"class":49,"line":93},8,[47,95,96],{},"torchvision = { index = \"pytorch-cu118\" }\n",[14,98,99,100,102,103,106],{},"CUDA 版のインデックスを明示してから入れ直したら ",[26,101,32],{}," に戻った。今後同じ罠を踏まないように、作業の流れと地雷を ",[26,104,105],{},"memo/2026-05-15/yomitoku-upgrade-0.13.0.md"," にまとめて書き残してもらった。",[18,108,109],{"id":109},"自炊書籍を流し込む",[14,111,112],{},"自炊した1冊（235 ページ）を yomitoku にかけた。GPU で 362 秒、ほぼ 6 分で全ページ抽出が終わる。CPU 版に逆戻りしていたら昼までかかっていたはずなので、ここで CUDA を取り戻した効果が効いた。",[14,114,115],{},"抽出結果を眺めていて、すぐ次の問題に気づいた。各ページの紙面の端に、縦書きで「第 N 章 章名」というインデックスタブが印刷されている。OCR はこれを律儀に拾って、本文の途中に章名を 3 連、4 連と並べてくる。問題文の中に章タイトルが闖入してくるので、全文検索の精度が露骨に落ちる。",[14,117,118,119,122],{},"方針を「全部削除でいい」と決めて、",[26,120,121],{},"yomitoku_import.py"," の前処理に章タブブロック除去のロジックを足してもらった。",[38,124,128],{"className":125,"code":126,"language":127,"meta":43,"style":43},"language-python shiki shiki-themes vitesse-light vitesse-light","# 「第N章 章名」が3個以上連続するブロックを章タブとみなして除去\nCHAPTER_TAB = re.compile(\n    r\"(?:第\\s*\\d+\\s*章[^\\n]{0,30}\\n){3,}\", re.MULTILINE\n)\ntext = CHAPTER_TAB.sub(\"\", text)\n","python",[26,129,130,136,159,233,238],{"__ignoreMap":43},[47,131,132],{"class":49,"line":50},[47,133,135],{"class":134},"sxvE3","# 「第N章 章名」が3個以上連続するブロックを章タブとみなして除去\n",[47,137,138,142,146,150,153,156],{"class":49,"line":56},[47,139,141],{"class":140},"snbK4","CHAPTER_TAB",[47,143,145],{"class":144},"shFtX"," =",[47,147,149],{"class":148},"sG7-3"," re",[47,151,152],{"class":144},".",[47,154,155],{"class":148},"compile",[47,157,158],{"class":144},"(\n",[47,160,161,165,169,172,176,180,184,187,190,192,194,197,200,203,207,210,213,215,218,221,223,226,228,230],{"class":49,"line":62},[47,162,164],{"class":163},"stQ0i","    r",[47,166,168],{"class":167},"sMJiu","\"",[47,170,171],{"class":144},"(?:",[47,173,175],{"class":174},"sLkVR","第",[47,177,179],{"class":178},"sz8Xr","\\s",[47,181,183],{"class":182},"sM54T","*",[47,185,186],{"class":178},"\\d",[47,188,189],{"class":182},"+",[47,191,179],{"class":178},[47,193,183],{"class":182},[47,195,196],{"class":174},"章",[47,198,199],{"class":140},"[",[47,201,202],{"class":163},"^",[47,204,206],{"class":205},"svWSF","\\n",[47,208,209],{"class":140},"]",[47,211,212],{"class":182},"{0,30}",[47,214,206],{"class":205},[47,216,217],{"class":144},")",[47,219,220],{"class":182},"{3,}",[47,222,168],{"class":167},[47,224,225],{"class":144},",",[47,227,149],{"class":148},[47,229,152],{"class":144},[47,231,232],{"class":140},"MULTILINE\n",[47,234,235],{"class":49,"line":68},[47,236,237],{"class":144},")\n",[47,239,240,243,246,249,251,254,257,260,262,265],{"class":49,"line":74},[47,241,242],{"class":148},"text ",[47,244,245],{"class":144},"=",[47,247,248],{"class":140}," CHAPTER_TAB",[47,250,152],{"class":144},[47,252,253],{"class":148},"sub",[47,255,256],{"class":144},"(",[47,258,259],{"class":167},"\"\"",[47,261,225],{"class":144},[47,263,264],{"class":148}," text",[47,266,237],{"class":144},[14,268,269],{},"p30、p60、p100 あたりを目視で確認しながらしきい値を詰めていった。3 個以下に下げると、目次や章扉の正当な見出しまで削ってしまう。3 個連続を境にして、紙面のタブだけが落ちる位置に着地させた。",[14,271,272],{},"最終的に 235 ページが 211 チャンクに分かれて Turso（book-knowledge-base DB）に入った。ページあたり 1 チャンクではないのは、白紙ページと章扉ページが前処理で間引かれているため。",[18,274,276],{"id":275},"amazon-メタデータの古いデータが残っていた","Amazon メタデータの古いデータが残っていた",[14,278,279,280,283],{},"DB に入れたあと、",[26,281,282],{},"book_metadata"," テーブルの該当 file_no を覗いたら、まったく別の本のタイトル（テスト用ダミー）がそのまま居座っていた。前にテスト用に流し込んだダミーを消し忘れていたらしい。",[14,285,286],{},"WebFetch で Amazon を引きにいかせたら 403 が返ってきたので、最初から agent-browser に切り替えた。ログイン済みの Chrome で開けば書誌情報がそのまま読める。正しい ASIN と書影 URL、ページ数、出版社情報を引っ張ってきて、該当行を UPDATE で上書きしてもらった。",[14,288,289],{},"入口の DB を直さないと、あとで Claude Code に「○○について本棚から要約して」と頼んだとき、表紙だけ別の本になる事故が起きる。気づいた瞬間に書き換えてもらった。",[18,291,293],{"id":292},"restructure-book-でセクション粒度を整える","restructure-book でセクション粒度を整える",[14,295,296,297,300],{},"ページ単位の 211 チャンクをそのままにしておくと、横断検索したときに 1 ページずつ断片で返ってきて文脈が読めない。",[26,298,299],{},"/restructure-book"," を回して、ページ→セクションへ統合してもらった。",[14,302,303],{},"粒度の方針はこう決めた。",[305,306,307,316,323,330],"ul",{},[308,309,310,311,315],"li",{},"第 1 章〜第 9 章、第 11 章以降は ",[312,313,314],"strong",{},"章単位"," にまとめる",[308,317,318,319,322],{},"第 10 章は問題が独立しているので ",[312,320,321],{},"問題単位","（問 1、問 2…）で分ける",[308,324,325,326,329],{},"解答解説部分は ",[312,327,328],{},"章別"," で分ける",[308,331,332,333,329],{},"模試部分は ",[312,334,335],{},"大問単位",[14,337,338],{},"章境界は紙面の目次と章扉ページで自分の目で確認した。yomitoku は章扉のレイアウトをそれなりに保ってくれているので、ここの判別は手作業をほとんど挟まずに済んだ。結果として 211 チャンクが 45 セクションに落ち着いた。横断検索するにはちょうど扱いやすい粒度になった。",[14,340,341],{},"履歴ファイルを書き出してもらい、途中で使った一時スクリプトを片付けてもらって、午前の作業をここで閉じた。",[18,343,345],{"id":344},"章タブが残っているように見えた-45-件の検証","章タブが残っているように見えた 45 件の検証",[14,347,348,351],{},[26,349,350],{},"第N章"," で grep をかけ直したら、45 件のマッチが残っていた。一瞬「前処理が抜けていたか」と背筋が伸びたが、上位 3 件を中身まで開いて確認したら、いずれも正当な構造だった。",[305,353,354,357,360],{},[308,355,356],{},"目次ページの章名行",[308,358,359],{},"章扉ページの章タイトル見出し",[308,361,362],{},"解答解説の章別見出し",[14,364,365],{},"3 個連続の章名ブロックは消えていて、本文に紛れ込む形での残存はない。残った 45 件はむしろ消してはいけない構造なので、ここで前処理をいじり直す必要はないと判断した。",[18,367,368],{"id":368},"今日の落とし所",[305,370,371,374,377,383],{},[308,372,373],{},"yomitoku 0.13.0 でアップグレード時の torch CPU フォールバックを踏んだ。pyproject.toml に CUDA インデックスを明示しておけば再発しない",[308,375,376],{},"紙面の章タブは「3 連以上の繰り返し」というシグナルでだけ落とせば、正当な見出しを傷つけずに済む",[308,378,379,380,382],{},"DB の ",[26,381,282],{}," は agent-browser で Amazon を引いて整える運用にする。WebFetch で 403 が出たら粘らず agent-browser に切り替える",[308,384,385],{},"章単位だけで切るとセクションが大きくなりすぎる本がある（問題集型）。問題別・解答解説の章別・大問単位を混ぜると、検索体験が一段良くなる",[14,387,388],{},"「○○について本棚から横断検索して」と Claude Code に頼んだとき、過去問の該当箇所も一緒に出てくるようになった。教科書だけだった棚に、問題集の身が混ざった感触がある。",[390,391,392],"style",{},"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);}html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .snbK4, html code.shiki .snbK4{--shiki-default:#A65E2B;--shiki-dark:#A65E2B}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sG7-3, html code.shiki .sG7-3{--shiki-default:#393A34;--shiki-dark:#393A34}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sLkVR, html code.shiki .sLkVR{--shiki-default:#AB5E3F;--shiki-dark:#AB5E3F}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html pre.shiki code .sM54T, html code.shiki .sM54T{--shiki-default:#2F798A;--shiki-dark:#2F798A}html pre.shiki code .svWSF, html code.shiki .svWSF{--shiki-default:#BDA437;--shiki-dark:#BDA437}",{"title":43,"searchDepth":56,"depth":56,"links":394},[395,396,397,398,399,400],{"id":20,"depth":56,"text":21},{"id":109,"depth":56,"text":109},{"id":275,"depth":56,"text":276},{"id":292,"depth":56,"text":293},{"id":344,"depth":56,"text":345},{"id":368,"depth":56,"text":368},"dev","yomitoku を 0.13.0 にアップグレードしたら torch が CPU 版に置き換わって速度が落ちた話と、自炊した1冊を全文検索 DB に取り込むまでの試行錯誤。","md",{},null,"/yomitoku-and-textbook-ocr","book-knowledge-base",false,"2026-05-15T00:00:00.000Z",{"title":5,"description":402},"2026-05/2026-05-15/yomitoku-and-textbook-ocr",[413,414,415,407,416,417],"yomitoku","ocr","turso","pytorch","cuda","Evpy3id1b2E6oqaB2ciKWdbbNTHNAnSbrYuNddfYr6A",[],"https://log.eurekapu.com/og/blog/yomitoku-and-textbook-ocr.png?v=2026-05-15T00%3A00%3A00.000Z&title=yomitoku%200.13.0%20%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89%E3%81%A8%E8%87%AA%E7%82%8A%E6%9B%B8%E7%B1%8D%E3%81%AE%20OCR%20%E5%8F%96%E3%82%8A%E8%BE%BC%E3%81%BF&author=Kei%20Komatsu&sig=d92cf84ea2240367",1782528837109]