新着情報の自動収集を組むと、必ず「フィードを出していないサイト」に突き当たります。やっかいなのは、フィードが無いことがエラーとして表面化しない点です。404がHTMLで返り、パーサは0件を返し、0件は「新着なし」と見分けがつきません。2026年8月4日に実測した結果をもとに、この誤診を防ぐ収集設計を整理します。
curl で実際に取得した値です。サイト側の構成は変わるため、恒久的な仕様ではありません。再現手順は記事末尾に記載しています。
「フィードがあるはず」から始めると、静かに失敗する
新着情報の収集を組むとき、最初に試すのは /feed/ や /rss.xml といった慣習的なパスを当てにいくことでしょう。うまくいけば数分で終わります。問題は、うまくいかなかったときに何が返ってくるかです。
日本の日用品・食品メーカー数社のニュースルームに対して、慣習的なフィードURLを当てにいった結果が次のとおりです。
| 試したURL | ステータス | Content-Type | 本文サイズ |
|---|---|---|---|
www.lion.co.jp/ja/newsroom/feed/ | 404 | text/html | 5,938 B |
www.lion.co.jp/ja/rss.xml | 404 | text/html | 5,938 B |
www.kao.com/jp/newsroom/rss.xml | 404 | text/html | 20,304 B |
jp.pg.com/newsroom/feed/ | 404 | text/html | 170,141 B |
www.unicharm.co.jp/ja/rss.xml | 404 | text/html | 20,163 B |
注目してほしいのは本文サイズです。404 なのに空ではありません。デザインされた「ページが見つかりません」のHTMLが返っており、いちばん大きいものは 170,141 バイトもあります。これは、後述する実在するフィード4本のうち3本より大きいサイズです。
取得の成否は3つのシグナルで判定する
フィード収集では、次の3つを順に確認してから中身を見るべきです。どれか1つでも欠けると、上の罠を踏みます。
- HTTPステータス。 2xx 以外は即座に失敗として記録する。404 を「新着なし」に混ぜない。
- Content-Type。 実測では、実在するフィードは
application/rss+xmlまたはapplication/xmlを返し、404ページはtext/htmlを返しました。ただし正しく設定していないサイトもあるため、これ単独で弾くのではなく警告に使うのが現実的です。 - ルート要素。 中身の先頭が
<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/ | 200 | 0 |
www.kao.com/jp/newsroom/ | 200 | 0 |
jp.pg.com/newsroom/ | 200 | 0 |
prtimes.jp/ | 200 | 1 |
www.ryutsuu.biz/ | 200 | 0 |
ページ自体は 200 で取得できており、そのうえで自動検出のリンクが1つも無い、という状態です。これは「推測が外れた」よりは強い根拠になりますが、それでも完全な不在の証明ではありません。実際、www.ryutsuu.biz/ はトップページに自動検出のリンクを置いていませんが、/feed は 200 で 50 件を返しました。自動検出が無い=フィードが無い、でもないわけです。
結論として、書けることは次の範囲にとどめるのが正確です。「慣習的なパスは404で、ニュースルームのトップにも自動検出のリンクが無かった。したがって、機械的な発見手段では見つからなかった」。収集設計としては、これで十分に「フィード前提では追えない」と判断できます。
代替経路と、その取りこぼし
公式サイトにフィードが無い場合、実務ではプレスリリース配信サービスや業界専門メディアのフィードで代替します。同日に測った4本は次のとおりです。
| フィード | ステータス | Content-Type | 件数 |
|---|---|---|---|
prtimes.jp/index.rdf | 200 | application/xml | 200 |
www.ssnp.co.jp/feed/ | 200 | application/rss+xml | 30 |
www.ryutsuu.biz/feed | 200 | application/rss+xml | 50 |
diamond-rm.net/feed/ | 200 | application/rss+xml | 10 |
ここに2つめの罠があります。集約フィードは全量ではなく「窓」です。上の 200 件入りのフィードについて、含まれる日付の範囲と、消費財に関するキーワードの出現数を数えました。
- 日付の範囲: 2026-07-29T10:40:41+09:00 〜 2026-08-04T09:15:17+09:00(およそ6日ぶん)
- タイトルに含まれる語の件数(200件中): 洗剤 0、柔軟剤 0、洗濯 0、歯みがき 0、シャンプー 0、ビール 0、コーヒー 0
つまり、汎用の集約フィードにキーワード絞り込みをかけて特定カテゴリを追う設計にすると、その時点の窓にたまたまそのカテゴリが1件も入っていないという状況が普通に起きます。7語すべてで0件でした。これを「そのカテゴリの新着が無かった」と解釈すると誤診です。正しくは「この窓には入っていなかった」です。
窓の幅も重要です。約6日ぶんで 200 件ということは、収集の間隔が窓の入れ替わりより遅ければ、その差ぶんは永久に見えません。フィードの件数上限と流量から、必要なポーリング間隔を逆算しておく必要があります。
「0件」を3つに分解する
ここまでの罠は、すべて「0件」という同じ見た目に3つの異なる状態が混ざることから来ています。収集処理では、この3つを別々に記録してください。
| 状態 | 実際に起きていること | 見分け方 |
|---|---|---|
| 取得できていない | 404・タイムアウト・レート制限・DNS失敗など | HTTPステータス、例外、Content-Type、ルート要素 |
| 取得できたが対象外 | フィードは正常だが、絞り込み条件に合う項目が無い | フィルタ前の件数を必ず記録する |
| 本当に新着が無い | フィード自体の件数が0、または前回以降の更新が無い | フィルタ前の件数が0、または最新日時が前回と同じ |
実装上のポイントは単純で、絞り込みの前後で件数を2つ記録することです。フィルタ後の件数だけをログに残していると、上の3つが区別できません。
フィードが無いサイトを追う場合の注意
最終的にHTMLの一覧ページを定期取得して差分を取る、という選択になることがあります。その場合は最低限、次を守ってください。
- robots.txt と利用規約を読む。 禁止されているならやらない。
- 取得間隔を十分に空ける。 新着情報の更新頻度は高くありません。数分おきに取りにいく必要はまずないはずです。
- 条件付きリクエストを使う。
If-Modified-Since/If-None-Matchを送り、304 が返ったら本文を取らない。相手にも自分にも優しい方法です。 - User-Agent に連絡先を入れる。 問題があったときに相手が連絡できる状態にしておく。
- 差分の取り方を安定させる。 HTMLの些細な変更で全件が「新着」と判定されないよう、比較キーは記事URLやIDなど安定した値にする。本文のハッシュは壊れやすい選択です。
- 失敗を握りつぶさない。 構造が変わってセレクタが空振りしたとき、0件ではなくエラーとして扱う。
チェックリスト
- 収集ログに ステータス・Content-Type・バイト数・フィルタ前件数・フィルタ後件数 を残しているか。
- 2xx 以外を「新着なし」と同じ扱いにしていないか。
- フィードの件数上限と窓の期間を把握し、ポーリング間隔を逆算しているか。
- フィードの有無を、慣習的なパスの推測だけでなく自動検出のリンクでも確認したか。
- 対照フィードを1本、同じ経路で取得しているか。
- セレクタやパーサの空振りを、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件を「新着が無かった」と読むと誤診になります。