


Webページから本文を取り出すツールを作り、消えた本文の原因を探す
ブラウザ・サーバー・コマンドライン・エッジで動く、Webページの本文を取り出すツールを作る・直す時に使う。本文を整える手順の順番を守り、取り除いた物を全部記録し、ページのHTMLからのスクリプト注入を防ぎ、先に失敗する小さなテストで直ったことを示す。
このAIルールを使うには
## ブラウザでもサーバーでも、同じ取り出し方で動くようにする
特定のブラウザ実装ではなく、安定した文書インターフェースを中心に抽出器を設計する。
共有の解析動作を変更する前に、対応するすべての環境とその制約を列挙する。
- ブラウザ版はネイティブの文書モデルを使用できる。
- サーバー版は複数のDOM実装で作成された文書を受け入れ、非同期APIを提供する場合がある。
- コマンドライン版は、機械処理可能な形式とテキスト向け形式を提供しつつ、同じ抽出規則を維持しなければならない。
- エッジ実行環境は最も制約の厳しい文書実装になり得るため、互換性の最低基準として扱う。
- バンドルのエントリーポイントは、モジュール形式が異なっていても同じ公開動作を提供しなければならない。
環境アダプターは薄く保つ。
実行環境の制約による明示的な例外が必要な場合を除き、解析、採点、正規化、無害化、要素別の動作は共有層へ置く。
## 本文を整える手順の順番を守り、1つのサイトのために並べ替えない
抽出パイプラインを、交換可能な整理関数の集合ではなく、順序を持つアルゴリズムとして扱う。
各段階は、後続段階が利用する前提を作る場合がある。
次の順序を既定とする。
1. カプセル化された文書ツリーを平坦化する。
2. ストリーミングまたは遅延されたコンテンツを解決する。
3. 本文を自動選択するか、明示的なセレクターで指定する。
4. 削除規則によって隠れたり失われたりする構造を先に正規化する。
5. 認識したコールアウトを安定した意味表現へ変換する。
6. 小さすぎるメディアと非表示要素を削除する。
7. スコアの低いブロックを削除する。
8. 完全一致および部分一致の不要要素セレクターを適用する。
9. 繰り返される定型文などのコンテンツパターンを削除する。
10. 残った文書を正規化する。
11. 相対リンクとリソース位置を解決する。
段階同士の依存関係が明白でない場合は、なぜ一方を先に実行する必要があるかを文書化する。
特定サイトを直すために共有段階を並べ替える場合は、必要なすべての中間表現が新しい順序でも保たれることを、対象を絞ったテストで先に証明する。
## 取り除いた物の記録から、本文が消えた段階を探す
選択されたコンテンツルートと各削除について、段階、セレクター、理由、代表的なテキストを報告するデバッグモードを用意する。
デバッグモードでは、診断用属性を保持し、証拠を失わせる構造平坦化を避けてもよい。
期待するコンテンツが消えた場合は、次を行う。
1. 削除ログで失われたコンテンツを確認する。
2. 各段階を順番に無効化し、消失を引き起こす最初の段階を特定する。
3. セレクターが原因なら、完全一致セレクターと部分一致セレクターを区別する。
4. 誤ったルートが選ばれた場合は、明示的なセレクターで自動検出を迂回する。
5. 保護対象のコード領域や整形済み領域が、一般的な削除の対象外であることを確認する。
6. 修正を受け入れる前に、無関係なすべての段階を再び有効にする。
最終文書から推測するより、最初に誤った遷移の証拠を優先する。
限定的なセレクター、順序、要素規則で不具合を解決できる場合に、広範な整理処理を恒久的に無効化してはならない。
## ページのHTMLを信用せず、スクリプトの注入を防ぐ
スクリプトを実行せず、リソースも読み込まない安全な文書構築ヘルパーを通じてマークアップを解析する。
信頼できないマークアップをブラウザの解析受け口へ直接代入してはならない。
- リンク属性とメディア属性から、スクリプトを実行可能なURLスキームを除去する。
- フレームから埋め込み文書のソース内容を削除する。
- イベントハンドラー属性を削除する。
- ページ由来の値を生成マークアップへ埋め込む前に、すべてエスケープする。
- エスケープ要件が明確になる場合は、ノード作成と属性設定を優先する。
- 完成した結果の無害化は最後の防御として使い、安全な構築の代わりにしてはならない。
メディアURL、代替テキスト、メタデータ画像、説明文に含まれる攻撃者制御の引用符は、属性を途中で終わらせ、別の属性を注入できるものと想定する。
マークアップを生成するすべての抽出器に、悪意ある属性注入のテストを用意する。
## 先に失敗する小さなテスト用ページで、直ったことを示す
抽出の不具合では、失敗を再現できる最小の文書フィクスチャを作り、正確な期待結果と組み合わせる。
フィクスチャは決定的にし、個人や収集元を特定できる情報を含めない。
- 実在する名前、メールアドレス、URL、アカウント識別子、特徴的な文章を汎用プレースホルダーへ置き換える。
- 失敗したパイプライン段階を実行するために必要な構造だけを含める。
- セキュリティ修正では、悪意ある属性または同等の攻撃的入力を含める。
- 修正を適用する前に、フィクスチャが失敗することを確認する。
- フィクスチャを成功させる最小の動作変更を適用する。
- 対象フィクスチャと共有抽出テスト群を、対応するすべての環境で実行する。
実装変更の前後で成功するフィクスチャでは、回帰不具合を修正した証明にならない。
修正を元に戻すことが現実的でない場合は、期待結果または制御用の切り替えを使い、古い動作が失敗することを引き続き示す。
## 環境ごとのDOMとバンドルの違いをテストする
共有アルゴリズムが変わらなくても、文書実装とバンドル形式が異なる境界動作をテストする。
- 文書を変更する前に、動的な要素コレクションを静的配列へ変換する。
- 既定エクスポートだけを公開するバンドルでも、名前付きユーティリティへ到達できることを確認する。
- 非同期のサーバーアダプターを、同期のブラウザアダプターとは別にテストする。
- ブラウザと同等だと仮定せず、エッジ実行環境の動作を実際のリクエスト境界からテストする。
- コマンドラインのテキスト形式と構造化形式を、同じフィクスチャ群で検証する。
- 環境固有の回避策をアダプター内に限定し、それぞれに対象を絞った互換性テストを用意する。
環境固有の修正が共有結果を変える場合は、実行環境横断の動作変更として扱い、対応するすべてのアダプターを検証する。
パッケージング上の回避策によって、抽出器の公開契約が黙って再定義されることを許してはならない。
