[{"data":1,"prerenderedAt":424},["ShallowReactive",2],{"content-/kindle-screenshot-import-noise-cleanup":3,"all-pages-for-dir":422,"og-image-/kindle-screenshot-import-noise-cleanup":423},{"id":4,"title":5,"body":6,"category":402,"description":403,"extension":404,"meta":405,"navigation":406,"ogImage":407,"path":408,"project_name":409,"published":410,"publishedAt":411,"seo":412,"stem":413,"tags":414,"todo":407,"unpublished":410,"updatedAt":407,"__hash__":421},"pages/2026-06/2026-06-24/kindle-screenshot-import-noise-cleanup.md","Kindleスクショ取込本52冊からノイズを一括除去した話 — 意味のないページ番号と書籍タイトル混入を独立cleanupフェーズで消す",{"type":7,"value":8,"toc":390},"minimark",[9,14,18,37,40,52,55,59,66,130,137,141,164,167,170,174,181,188,195,199,206,213,233,236,240,247,260,263,267,278,281,288,292,299,302,305,308,322,325,328,358,361,386],[10,11,13],"h2",{"id":12},"きっかけこのページ番号って何の意味があるんですか","きっかけ：「このページ番号って何の意味があるんですか？」",[15,16,17],"p",{},"引き継ぎセッションを開いて、まずは前日 restructure をかけ直した あるスクショ取込本 の DB が Web UI でちゃんと読めるか確認しに行った。\n書籍ビューアを開いて、ページのドロップダウンをスクロールした瞬間に手が止まった。",[15,19,20,21,25,26,29,30,36],{},"表紙が ",[22,23,24],"code",{},"1","、「はじめに」が ",[22,27,28],{},"2","、その次のページが ",[31,32,33],"strong",{},[22,34,35],{},"53","。",[15,38,39],{},"何だこの番号は、と引っかかった。\n紙の本ならページが飛ぶことは普通にあるが、これは Kindle Windows アプリのスクリーンショットを OCR して取り込んだ本だ。\n紙のページ番号は持っていない。",[15,41,42,43,45,46,45,48,51],{},"ということは、この ",[22,44,24],{}," も ",[22,47,35],{},[31,49,50],{},"PNG の連番","でしかない。\n表紙の PNG が1枚目、「はじめに」の PNG が2枚目、本文最初の PNG が53枚目。\n紙の本のページ番号でもなければ、Kindle の Location 番号でもない。\nただの撮影時のシャッター回数。",[15,53,54],{},"読者にとっても自分にとっても、この数字は完全に意味がない。\nむしろ「ページ53」と表示されると「え、52ページ分どこ行った？」と無駄な認知負荷を生む。",[10,56,58],{"id":57},"phase-0判定基準を確定する","Phase 0：判定基準を確定する",[15,60,61,62,65],{},"最初にやったのは「スクショ取込本」をどう判定するかの確定。\nDB のスキーマを Claude Code に確認させたら、",[22,63,64],{},"books.source_path"," を見れば一発で識別できると分かった。",[67,68,73],"pre",{"className":69,"code":70,"language":71,"meta":72,"style":72},"language-sql shiki shiki-themes vitesse-light vitesse-light","-- スクショ取込本: source_path が \"kindle:\" で始まる\n-- 通常の PDF/EPUB 取込本: source_path がファイルパス（\"C:/...\" 等）\nSELECT id, title FROM books WHERE source_path LIKE 'kindle:%';\n","sql","",[22,74,75,84,90],{"__ignoreMap":72},[76,77,80],"span",{"class":78,"line":79},"line",1,[76,81,83],{"class":82},"sxvE3","-- スクショ取込本: source_path が \"kindle:\" で始まる\n",[76,85,87],{"class":78,"line":86},2,[76,88,89],{"class":82},"-- 通常の PDF/EPUB 取込本: source_path がファイルパス（\"C:/...\" 等）\n",[76,91,93,97,101,104,107,110,113,116,120,124,127],{"class":78,"line":92},3,[76,94,96],{"class":95},"sHkkW","SELECT",[76,98,100],{"class":99},"sG7-3"," id, title ",[76,102,103],{"class":95},"FROM",[76,105,106],{"class":99}," books ",[76,108,109],{"class":95},"WHERE",[76,111,112],{"class":99}," source_path ",[76,114,115],{"class":95},"LIKE",[76,117,119],{"class":118},"sMJiu"," '",[76,121,123],{"class":122},"sdGka","kindle:%",[76,125,126],{"class":118},"'",[76,128,129],{"class":99},";\n",[15,131,132,133,136],{},"これで「PNG 連番ページ番号を持つ本」を 1 クエリで全部引ける。\n判定が ",[22,134,135],{},"prefix match"," だけで済むので、Web UI 側の computed もシンプルに書ける。",[10,138,140],{"id":139},"phase-1web-ui-側でページ番号バッジを非表示にする","Phase 1：Web UI 側でページ番号バッジを非表示にする",[15,142,143,144,147,148,151,152,155,156,159,160,163],{},"意味のない番号は、まずは見せないようにする。\n",[22,145,146],{},"web/app/pages/books/[bookId]/[page].vue"," に ",[22,149,150],{},"hasMeaningfulPageNumbers"," という computed を1個生やして、\n",[22,153,154],{},"book.source_path"," が ",[22,157,158],{},"kindle:"," で始まるときは ",[22,161,162],{},"false"," を返す。",[15,165,166],{},"ページ番号バッジの v-if にそれを噛ませて非表示にした。\n画像と本文だけが残るので、見た目もスッキリ。\nドロップダウンの選択肢は内部的には連番のままだが、表示上は「画像N枚目」という意味合いになる。",[15,168,169],{},"これで「ページ53って何？」問題は消えた。",[10,171,173],{"id":172},"ところがdb-をブラウジングしていたら別の問題が見えてきた","ところが…DB をブラウジングしていたら別の問題が見えてきた",[15,175,176,177,180],{},"UI 修正後、確認のために本の章末をブラウジングしていたら、\n今度は ",[31,178,179],{},"本文中にランニングヘッダー（書籍タイトル）そのものが混入している","のが目に入った。\nページの本文の合間に、ヘッダー由来の短い行が定期的に挟まっている状態。",[15,182,183,184,187],{},"これは Kindle アプリのページ上部に表示される ",[31,185,186],{},"ランニングヘッダー","を OCR が拾ってしまった結果。\nスクショ取込本だと避けられない構造的なノイズ。\n書籍タイトルだけじゃなく、章名やページのフッタ UI（「\u003C 戻る」みたいなボタンラベル）まで紛れ込んでいる本もあった。",[15,189,190,191,194],{},"UI で隠せばいいというレベルじゃない。\nこれは全文検索（FTS）の精度を下げるし、AI に書籍内容を引かせるときにもノイズになる。\n",[31,192,193],{},"DB 側から消すべき","だと判断した。",[10,196,198],{"id":197},"phase-2ノイズ集計dry-run","Phase 2：ノイズ集計（dry-run）",[15,200,201,202,205],{},"Claude Code に依頼して、スクショ取込本 ",[31,203,204],{},"52冊","から「ほぼ全頁に出現する短い行」を集計させた。\n書籍タイトルやランニングヘッダーは、その本のほぼ全ページに出現する性質を持つ。\n逆に本文はそうそう同じ行が繰り返されない。\nこの性質を使って「全頁出現率 ≧ N%」の行をノイズ候補として抽出する素朴な方法を取った。",[15,207,208,209,212],{},"dry-run の結果は ",[22,210,211],{},"memo/2026-06-24/kindle-noise-candidates.md"," に 273 行で出力。\nそれを目で眺めたら、",[214,215,216,223,226],"ul",{},[217,218,219,220],"li",{},"書籍タイトル100%混入の本が ",[31,221,222],{},"4冊",[217,224,225],{},"Kindle UI 由来の固定ノイズ（「マイライブラリ」「もっと見る」みたいな文字列）が多数",[217,227,228,229,232],{},"章タイトルが ",[22,230,231],{},"[第3章]"," のような prefix として section 名に紛れている本もあった",[15,234,235],{},"という構図が見えた。",[10,237,239],{"id":238},"phase-3再-restructureではなく独立-cleanup-フェーズに切る","Phase 3：「再 restructure」ではなく「独立 cleanup フェーズ」に切る",[15,241,242,243,246],{},"当初の計画書では、52冊を Workflow で並列に ",[31,244,245],{},"再 restructure"," する案を書いていた。\nが、書きながら気づいた。\nrestructure はセクション統合まで含む重めの手作業（章構造の再構築、見出し階層の整理）で、それを 52 冊全部やり直すのは現実的じゃない。\n既存の restructure 結果（章構造）は活かしたい。",[15,248,249,250,256,257,259],{},"そこで方針を切り替えた。\n",[31,251,252,255],{},[22,253,254],{},"apply_kindle_noise_filter"," という独立フェーズを実装して、行レベル削除 + section prefix → tags 移管だけをやる","。\n章構造には触らない。本文の chunk 単位で「ノイズ候補リストにマッチする行」だけを抜く。\nsection 名の ",[22,258,231],{}," みたいな prefix は tags に移管して、section 名自体をクリーンにする。",[15,261,262],{},"これなら既存資産が全部活きる。",[10,264,266],{"id":265},"phase-4単体適用-サンプル目視-一括適用","Phase 4：単体適用 → サンプル目視 → 一括適用",[15,268,269,270,273,274,277],{},"まず あるスクショ取込本 単体で適用させた。\ndry-run 出力で、151 chunks 全件で content が変わり、104 chunks の section から ",[22,271,272],{},"[XXX]"," prefix が tags へ移った。\n",[31,275,276],{},"2,168 行","削除。",[15,279,280],{},"before/after サンプルを目視確認。\npage 1 の冒頭16行あった UI ノイズと書籍タイトル混入が消えて、奥付相当の最小限の情報だけが残る。\npage 53「はじめに」の5行ノイズも消滅。本文だけが残った。\n読みやすい。",[15,282,283,284,287],{},"問題なさそうなので、残り 51 冊を ",[22,285,286],{},"--all"," でバックグラウンド一括適用させた。",[10,289,291],{"id":290},"phase-5結果","Phase 5：結果",[15,293,294,295,298],{},"完了通知を待っている間に他のことをやり、戻ってきたら全 52 冊終わっていた。\n累計で ",[31,296,297],{},"8,948 行","のノイズ削除。\n書籍タイトル100%混入だった 4 冊もすべてクリーンアップ。",[15,300,301],{},"検証クエリを回して、ノイズが残っていないかを確認。\n2冊だけ少数残っていたが、内容を見たら「本文の正当な言及」（書籍タイトルがそのまま本文中で言及されているケース）で、消すと逆に情報が消える。これは許容範囲として残した。",[15,303,304],{},"FTS の rebuild も走らせて、全文検索インデックスも最新化。",[15,306,307],{},"コミットは2本に分けた。",[214,309,310,316],{},[217,311,312,313,315],{},"Web UI 改修（",[22,314,150],{}," computed 追加 + ページ番号バッジの v-if 制御）",[217,317,318,319,321],{},"ノイズフィルタ実装（",[22,320,254],{}," モジュール + CLI）",[15,323,324],{},"scratchpad の作業ファイルは除外して、必要なものだけ。",[10,326,327],{"id":327},"学び",[214,329,330,336,342,348],{},[217,331,332,335],{},[31,333,334],{},"「再 restructure 全部やり直す」よりも「ノイズ除去だけ独立フェーズで切り出す」方が既存資産が活きる","。\n章構造の再構築は重い。本文の行レベル削除と section 名のクリーンアップだけなら、独立した小さい関数で完結する。\n「全部やり直す案」を最初に書いたが、書いている途中で「重すぎる」と気づいて方針を切り替えられたのが大きかった。",[217,337,338,341],{},[31,339,340],{},"Web UI の違和感を起点に、DB 側のノイズ問題まで芋づる式に拾えた","。\n「ページ番号が意味不明」という UI の違和感を直すために DB をブラウジングしたら、本文に書籍タイトルが混入しているのが目に入った。\n最初から「DB のノイズを掃除しよう」と思って入ったわけじゃない。UI を触っているうちに視界に入った。",[217,343,344,347],{},[31,345,346],{},"読んでて気持ち悪い違和感を放置せず拾うのは筆者本人の係","。\n「ページ53って何？」「本文の途中に書籍タイトルが挟まってる」は、AI には違和感として認識されにくい。\n実装の係はAIに振れるが、違和感の検知はこっちで持つしかない。",[217,349,350,353,354,357],{},[31,351,352],{},"判定基準が1個の prefix match で済むと、後続の実装が劇的にシンプルになる","。\n",[22,355,356],{},"source_path LIKE 'kindle:%'"," だけで全部分岐できるので、Web UI の computed もノイズフィルタの対象抽出も、同じ1行で済んだ。\nスキーマ設計の段階で source_path に prefix 規約を入れていた過去の自分に感謝。",[10,359,360],{"id":360},"関連ファイル",[214,362,363,369,375,380],{},[217,364,365,366],{},"計画書: ",[22,367,368],{},"memo/2026-06-24/kindle-screenshot-noise-removal-plan.md",[217,370,371,372,374],{},"dry-run 出力: ",[22,373,211],{},"（273行）",[217,376,377,378],{},"Web UI: ",[22,379,146],{},[217,381,382,383,385],{},"ノイズフィルタ実装: ",[22,384,254],{}," モジュール + CLI",[387,388,389],"style",{},"html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .sG7-3, html code.shiki .sG7-3{--shiki-default:#393A34;--shiki-dark:#393A34}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}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":72,"searchDepth":86,"depth":86,"links":391},[392,393,394,395,396,397,398,399,400,401],{"id":12,"depth":86,"text":13},{"id":57,"depth":86,"text":58},{"id":139,"depth":86,"text":140},{"id":172,"depth":86,"text":173},{"id":197,"depth":86,"text":198},{"id":238,"depth":86,"text":239},{"id":265,"depth":86,"text":266},{"id":290,"depth":86,"text":291},{"id":327,"depth":86,"text":327},{"id":360,"depth":86,"text":360},"dev","Web UIで表示される「表紙が1、はじめが2、その次が53」というページ番号への違和感を起点に、スクショ取込本52冊から累計8,948行のノイズを独立cleanupフェーズで一括除去するまで。","md",{},true,null,"/kindle-screenshot-import-noise-cleanup","book-knowledge-base",false,"2026-06-24T00:00:00.000Z",{"title":5,"description":403},"2026-06/2026-06-24/kindle-screenshot-import-noise-cleanup",[415,416,417,418,419,420],"Kindle","OCR","蔵書","Vue","ノイズ除去","restructure","2q9p6a-PA0hAcUgY8pvc0I1NZwimPWyZ-_6MfW7n2Fw",[],"https://log.eurekapu.com/og/blog/kindle-screenshot-import-noise-cleanup.png?v=2026-06-24T00%3A00%3A00.000Z&title=Kindle%E3%82%B9%E3%82%AF%E3%82%B7%E3%83%A7%E5%8F%96%E8%BE%BC%E6%9C%AC52%E5%86%8A%E3%81%8B%E3%82%89%E3%83%8E%E3%82%A4%E3%82%BA%E3%82%92%E4%B8%80%E6%8B%AC%E9%99%A4%E5%8E%BB%E3%81%97%E3%81%9F%E8%A9%B1%20%E2%80%94%20%E6%84%8F%E5%91%B3%E3%81%AE%E3%81%AA%E3%81%84%E3%83%9A%E3%83%BC%E3%82%B8%E7%95%AA%E5%8F%B7%E3%81%A8%E6%9B%B8%E7%B1%8D%E3%82%BF%E3%82%A4%E3%83%88%E3%83%AB%E6%B7%B7%E5%85%A5%E3%82%92%E7%8B%AC%E7%AB%8Bcleanup%E3%83%95%E3%82%A7%E3%83%BC%E3%82%BA%E3%81%A7%E6%B6%88%E3%81%99&author=Kei%20Komatsu&sig=0da004f98dc74272",1782364626239]