FessクローラーのURLからURIへの置き換えで対応できないパターンへのフォールバック対応

Fessのクローラーでは、クロール対象のHTMLページからリンクURLを抽出する際に、java.net.URIを使って相対URLを絶対URLに解決しています。しかし、URI.resolve()はRFC準拠の厳密なパースを行うため、スペースなどの特殊文字を含む相対パスを正しく処理できないケースがありました。今回、この問題に対するフォールバック処理をPR #3056で追加しました。

問題

FessXpathTransformerでHTMLのアンカータグなどからURLを抽出する際、URI.resolve()で相対URLを絶対URLに変換しています。通常の相対パスであれば問題なく動作しますが、以下のようなケースではURIがスキームを検出できず、URLの解決に失敗していました。

  • スペースを含む相対パス(例: page 2.html
  • スペースを含む絶対パス(例: /path with space/page.html
  • スペースを含むプロトコル相対URL(例: //cdn.example.com/a b.js
  • スペースを含む親ディレクトリ参照(例: ../page 2.html

実際のWebサイトでは、こうしたURLは珍しくないため、クロール時にリンクが取りこぼされる原因になっていました。

対応内容

FessXpathTransformeraddChildUrlFromTagAttributeメソッドに、既存の絶対URL判定(スキーム検出)で処理できなかった場合のフォールバック処理を追加しました。ベースURIのスキームとオーソリティを利用して、以下の4パターンの相対URLを手動で絶対URLに変換します。

プロトコル相対URL(//で始まる場合)

// 例: //cdn.example.com/a b.js → http://cdn.example.com/a%20b.js
fallbackUrl = scheme + ":" + urlValue;

クエリ・フラグメントのみ(?または#で始まる場合)

// 例: ?q=test → http://example.com/page.html?q=test
fallbackUrl = uri.toString() + urlValue;

ルート絶対パス(/で始まる場合)

// 例: /path with space/page.html → http://example.com/path%20with%20space/page.html
// /../の正規化も行う

相対パス(上記以外)

// 例: ../page 2.html → http://example.com/dir/page%202.html
// ベースURIのパスから親ディレクトリを算出して結合

いずれのパターンでも、/../がルートを超える場合のパス正規化処理を行い、最終的にencodeUrlでパーセントエンコーディングを適用します。

テスト

6つのテストケースを追加して、各パターンの動作を検証しています。

  • page 2.htmlhttp://example.com/dir/page%202.html
  • /path with space/page.htmlhttp://example.com/path%20with%20space/page.html
  • //cdn.example.com/a b.jshttp://cdn.example.com/a%20b.js
  • ../page 2.html(深い階層から) → http://example.com/dir/page%202.html
  • /../page 2.htmlhttp://example.com/page%202.html
  • ../page 2.html(ルートから) → http://example.com/page%202.html

まとめ

今回の修正は、既存のURI.resolve()で処理できるURLには一切影響を与えず、これまで取りこぼしていたスペース等の特殊文字を含む相対URLを正しく解決できるようになりました。実際のWebサイトでは、CMSが生成するURLにスペースが含まれることもあるため、クロールの網羅性向上に寄与する修正です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です