RSSが無いサイトの新着をどう追うか — 404がHTMLで返る罠と「0件」の誤診

新着情報の自動収集を組むと、必ず「フィードを出していないサイト」に突き当たります。やっかいなのは、フィードが無いことがエラーとして表面化しない点です。404がHTMLで返り、パーサは0件を返し、0件は「新着なし」と見分けがつきません。2026年8月4日に実測した結果をもとに、この誤診を防ぐ収集設計を整理します。

この記事の実測について: 以下のステータス・バイト数・件数は、2026年8月4日に筆者が curl で実際に取得した値です。サイト側の構成は変わるため、恒久的な仕様ではありません。再現手順は記事末尾に記載しています。

「フィードがあるはず」から始めると、静かに失敗する

新着情報の収集を組むとき、最初に試すのは /feed//rss.xml といった慣習的なパスを当てにいくことでしょう。うまくいけば数分で終わります。問題は、うまくいかなかったときに何が返ってくるかです。

日本の日用品・食品メーカー数社のニュースルームに対して、慣習的なフィードURLを当てにいった結果が次のとおりです。

試したURLステータスContent-Type本文サイズ
www.lion.co.jp/ja/newsroom/feed/404text/html5,938 B
www.lion.co.jp/ja/rss.xml404text/html5,938 B
www.kao.com/jp/newsroom/rss.xml404text/html20,304 B
jp.pg.com/newsroom/feed/404text/html170,141 B
www.unicharm.co.jp/ja/rss.xml404text/html20,163 B

注目してほしいのは本文サイズです。404 なのに空ではありません。デザインされた「ページが見つかりません」のHTMLが返っており、いちばん大きいものは 170,141 バイトもあります。これは、後述する実在するフィード4本のうち3本より大きいサイズです。

ここが最初の罠: ステータスコードを見ずに「本文が取れたかどうか」で成否を判断している収集処理は、この170KBのHTMLをフィードとして受け取り、パースに失敗して「0件」を返します。そして0件は、多くの実装で「今日は新着が無かった」と同じ扱いになります。エラーは1件も記録されず、収集対象が丸ごと抜け落ちたまま何日も気づけません。

取得の成否は3つのシグナルで判定する

フィード収集では、次の3つを順に確認してから中身を見るべきです。どれか1つでも欠けると、上の罠を踏みます。

  1. HTTPステータス。 2xx 以外は即座に失敗として記録する。404 を「新着なし」に混ぜない。
  2. Content-Type。 実測では、実在するフィードは application/rss+xml または application/xml を返し、404ページは text/html を返しました。ただし正しく設定していないサイトもあるため、これ単独で弾くのではなく警告に使うのが現実的です。
  3. ルート要素。 中身の先頭が <rss> / <feed> / <rdf:RDF> のいずれかか。HTMLなら <!DOCTYPE html><html> で始まります。
# 1回のリクエストで3つのシグナルをまとめて取る
curl -sL --max-time 25 -o /tmp/f.xml \
     -w 'status=%{http_code} type=%{content_type} bytes=%{size_download}\n' \
     "$FEED_URL"

# ルート要素の確認(先頭200バイトを見るだけで十分)
head -c 200 /tmp/f.xml

「見つからない」と「存在しない」は別物

ここで踏みとどまる必要があります。慣習的なURLを当てにいって404だったことは、そのサイトにフィードが無いことの証明にはなりません。単にパスの推測が外れただけかもしれません。

正しい探し方は、HTMLの フィード自動検出(autodiscovery) を見ることです。フィードを持つサイトは、通常 <head> に次のようなリンクを置きます。

<link rel="alternate" type="application/rss+xml"
      href="https://example.com/index.rdf" title="Example Feed">

先ほどのメーカー各社のニュースルームのトップページを取得し、この記述の有無を数えた結果です。

ページステータスautodiscovery のリンク数
www.lion.co.jp/ja/newsroom/2000
www.kao.com/jp/newsroom/2000
jp.pg.com/newsroom/2000
prtimes.jp/2001
www.ryutsuu.biz/2000

ページ自体は 200 で取得できており、そのうえで自動検出のリンクが1つも無い、という状態です。これは「推測が外れた」よりは強い根拠になりますが、それでも完全な不在の証明ではありません。実際、www.ryutsuu.biz/ はトップページに自動検出のリンクを置いていませんが、/feed は 200 で 50 件を返しました。自動検出が無い=フィードが無い、でもないわけです。

結論として、書けることは次の範囲にとどめるのが正確です。「慣習的なパスは404で、ニュースルームのトップにも自動検出のリンクが無かった。したがって、機械的な発見手段では見つからなかった」。収集設計としては、これで十分に「フィード前提では追えない」と判断できます。

代替経路と、その取りこぼし

公式サイトにフィードが無い場合、実務ではプレスリリース配信サービスや業界専門メディアのフィードで代替します。同日に測った4本は次のとおりです。

フィードステータスContent-Type件数
prtimes.jp/index.rdf200application/xml200
www.ssnp.co.jp/feed/200application/rss+xml30
www.ryutsuu.biz/feed200application/rss+xml50
diamond-rm.net/feed/200application/rss+xml10

ここに2つめの罠があります。集約フィードは全量ではなく「窓」です。上の 200 件入りのフィードについて、含まれる日付の範囲と、消費財に関するキーワードの出現数を数えました。

つまり、汎用の集約フィードにキーワード絞り込みをかけて特定カテゴリを追う設計にすると、その時点の窓にたまたまそのカテゴリが1件も入っていないという状況が普通に起きます。7語すべてで0件でした。これを「そのカテゴリの新着が無かった」と解釈すると誤診です。正しくは「この窓には入っていなかった」です。

窓の幅も重要です。約6日ぶんで 200 件ということは、収集の間隔が窓の入れ替わりより遅ければ、その差ぶんは永久に見えません。フィードの件数上限と流量から、必要なポーリング間隔を逆算しておく必要があります。

「0件」を3つに分解する

ここまでの罠は、すべて「0件」という同じ見た目に3つの異なる状態が混ざることから来ています。収集処理では、この3つを別々に記録してください。

状態実際に起きていること見分け方
取得できていない404・タイムアウト・レート制限・DNS失敗などHTTPステータス、例外、Content-Type、ルート要素
取得できたが対象外フィードは正常だが、絞り込み条件に合う項目が無いフィルタ前の件数を必ず記録する
本当に新着が無いフィード自体の件数が0、または前回以降の更新が無いフィルタ前の件数が0、または最新日時が前回と同じ

実装上のポイントは単純で、絞り込みの前後で件数を2つ記録することです。フィルタ後の件数だけをログに残していると、上の3つが区別できません。

対照(コントロール)を1本置く: 収集の対象とは別に、ほぼ確実に何かが流れているフィードを1本、同じ経路・同じコードで毎回取得すると、切り分けが一気に楽になります。対象が0件でも対照が正常に取れていれば「相手側または条件の問題」、対照まで0件やエラーなら「自分側(ネットワーク・ユーザーエージェント・レート制限・パーサの破損)の問題」と即断できます。監視の世界でいうカナリアと同じ発想で、外部データを取りにいくバッチ全般に効きます。

フィードが無いサイトを追う場合の注意

最終的にHTMLの一覧ページを定期取得して差分を取る、という選択になることがあります。その場合は最低限、次を守ってください。

チェックリスト

  1. 収集ログに ステータス・Content-Type・バイト数・フィルタ前件数・フィルタ後件数 を残しているか。
  2. 2xx 以外を「新着なし」と同じ扱いにしていないか。
  3. フィードの件数上限と窓の期間を把握し、ポーリング間隔を逆算しているか。
  4. フィードの有無を、慣習的なパスの推測だけでなく自動検出のリンクでも確認したか。
  5. 対照フィードを1本、同じ経路で取得しているか。
  6. セレクタやパーサの空振りを、0件ではなくエラーとして検出できるか。

実測の再現手順(2026年8月4日)

  • フィード候補URLに対して curl -sL --max-time 25 -o /tmp/f.xml -w 'status=%{http_code} ctype=%{content_type} bytes=%{size_download}' を実行し、保存した本文の <item> / <entry> 数を数えた
  • 各サイトのニュースルームのトップページを取得し、<link rel="alternate"> のうち type に rss / atom を含むものを数えた
  • 集約フィードについて、<dc:date> の最小・最大と、タイトルに特定の語を含む件数を数えた

数値はすべて測定時点のものです。特定の企業がフィードを提供していないことの証明ではなく、機械的な発見手段では見つからなかったという測定結果として扱ってください。

よくある質問(FAQ)

フィードのURLが404のとき、本文は空ですか?

空とは限りません。2026年8月4日の実測では、慣習的なフィードURLに対する404がすべて text/html のHTMLで返り、本文サイズは 5,938 バイトから 170,141 バイトまでありました。ステータスコードを見ずに本文の有無で成否を判定すると、このHTMLをフィードとして受け取ってしまいます。

フィードの取得成否はどう判定すればよいですか?

HTTPステータスが2xxであること、Content-Type が application/rss+xml や application/xml であること、本文のルート要素が rss / feed / rdf:RDF のいずれかであることの3つを順に確認します。Content-Type は正しく設定していないサイトもあるため、単独で弾かず警告に使うのが現実的です。

あるサイトにフィードが無いことは、どう確かめますか?

慣習的なパスを試して404だっただけでは不在の証明になりません。HTMLの自動検出(link rel=alternate で type に rss や atom を含むもの)を確認します。ただし自動検出が無くてもフィードが存在する例は実際にあるため、言えるのは「機械的な発見手段では見つからなかった」までです。

集約フィードにキーワード絞り込みをかければ、特定カテゴリを追えますか?

取りこぼします。集約フィードは全量ではなく直近の一定件数の窓です。2026年8月4日に測った200件入りのフィードは約6日ぶんで、消費財に関する7つのキーワードすべてで該当が0件でした。0件を「新着が無かった」と読むと誤診になります。

← 技術ブログ一覧へ戻る