スクレイピング(クローリング)で「必要なURLだけを、最短で、漏れなく集めたい」と思っても、リンクを辿る方式だけでは遠回りになりがちです。そこで効くのがサイトマップ(XML Sitemap)。本記事では、サイトマップを起点にしたクロール設計の考え方と、実装時の注意点を、入門者向けに整理します。 サイトマップ(XML Sitemap)は、サイト内のURL一覧を検索エンジン等のクローラーに伝えるための仕組みです。スクレイピングでも同様に、対象URL群の「公式インデックス」として活用できます。 サイトマップの主要タグは
サイトマップの基礎
XMLサイトマップの要素
<loc>(URL)と、任意で <lastmod>(更新日)などです。仕様では <changefreq> や <priority> も定義されています。詳しくは仕様を参照してください。
押さえておきたい結論:スクレイピングで最も価値が高いのは、まず 「最短」を目指すなら、リンク探索よりも先に URLの母集団 を確定し、不要URLを早めに捨てるのが基本方針です。サイトマップはこの方針と相性が良い手段です。 次の順で優先度を決めると、業務用途でも事故が減ります。 注意:サイトマップに ただし、仕様上も「サイトマップ生成日」ではなく「対象ページの更新日」を入れることが前提です。誤った ここからが本題です。サイトマップを使ったURL収集の手順を、Pythonを例に示します(requests + 標準XMLパーサ)。 まずは <loc> によるURL集合の確定です。次に <lastmod> を活用できると差分クロールが楽になります。最短クロールの設計
まずURL集合を確定
/sitemap.xml や /sitemap_index.xml が典型)/product/ のみ)優先順位の付け方
<changefreq> や <priority> が入っていても、常に信頼できるとは限りません。スクレイピング設計では「自分の要件(重要URL)」を優先し、タグは参考情報として扱うのが安全です。差分クロールの考え方
<lastmod> が正しく運用されているサイトでは、前回クロール以降に更新されたURLだけを再取得できます。これにより、巡回時間・通信量・ブロックリスクをまとめて下げられます。<lastmod> が入っているケースもあるため、実データ(HTMLやAPI応答の更新日時)と突合して妥当性を検証してください。実装の最短手順
サイトマップを発見
robots.txt を見に行き、Sitemap: 行からサイトマップURLを拾うのが堅実です(複数行ある場合もあります)。
import re
import requests
def discover_sitemaps(base_url: str):
robots_url = base_url.rstrip("/") + "/robots.txt"
r = requests.get(robots_url, timeout=20)
r.raise_for_status()
sitemaps = []
for line in r.text.splitlines():
m = re.match(r"(?i)^sitemap:\s*(\S+)", line.strip())
if m:
sitemaps.append(m.group(1))
return sitemaps
print(discover_sitemaps("https://example.com"))サイトマップを解析
サイトマップは「URL一覧のXML(urlset)」だけでなく、「サイトマップの一覧(sitemapindex)」の場合があります。両方に対応して、最終的にURLのリストを返すようにします。
import requests
import xml.etree.ElementTree as ET
NS = {"sm": "http://www.sitemaps.org/schemas/sitemap/0.9"}
def fetch_xml(url: str) -> ET.Element:
r = requests.get(url, timeout=30)
r.raise_for_status()
return ET.fromstring(r.content)
def parse_sitemap(url: str):
root = fetch_xml(url)
# sitemapindex
if root.tag.endswith("sitemapindex"):
locs = [e.find("sm:loc", NS).text for e in root.findall("sm:sitemap", NS)]
urls = []
for loc in locs:
urls.extend(parse_sitemap(loc))
return urls
# urlset
if root.tag.endswith("urlset"):
out = []
for u in root.findall("sm:url", NS):
loc = u.find("sm:loc", NS).text
lastmod_el = u.find("sm:lastmod", NS)
lastmod = lastmod_el.text if lastmod_el is not None else None
out.append({"loc": loc, "lastmod": lastmod})
return out
raise ValueError(f"Unknown sitemap root: {root.tag}")
items = parse_sitemap("https://example.com/sitemap.xml")
print(len(items), items[:3])
実務のコツ:最初に「URL収集(サイトマップ)」と「ページ取得(クロール)」を分離してください。URL収集を先に完了させると、重複排除・優先順位付け・リトライ設計が簡単になります。
フィルタと正規化
サイトマップには、収集対象外のURL(タグ、検索結果、ヘルプ、言語別など)が混ざることがあります。そこで、パスプレフィックス等でフィルタします。
from urllib.parse import urlparse, urlunparse
def normalize_url(u: str) -> str:
p = urlparse(u)
# クエリやフラグメントを落とす(要件次第で保持)
p = p._replace(query="", fragment="")
# 末尾スラッシュ統一はサイト仕様に合わせる
return urlunparse(p)
def filter_urls(items, allow_prefixes):
out = []
for it in items:
loc = normalize_url(it["loc"])
path = urlparse(loc).path
if any(path.startswith(prefix) for prefix in allow_prefixes):
out.append({**it, "loc": loc})
return out
filtered = filter_urls(items, allow_prefixes=["/product/", "/item/"])
print(len(filtered))
よくある落とし穴
サイトマップが複数ある
大規模サイトでは、サイトマップを分割し「サイトマップインデックス」で束ねる構成が一般的です。実装では sitemapindex を必ず処理できるようにしておきましょう。
lastmodが信用できない
<lastmod> は差分クロールに有効ですが、運用が雑だと「全部が当日更新」になっていることもあります。その場合は以下の方針に切り替えるのが現実的です。
- HTTPの
ETag/If-Modified-Sinceを使う(サーバが対応していれば) - 重要ページだけは定期巡回、その他は低頻度にする
- ページ内の更新日時(例:商品更新日)を抽出して比較する
正規URLと重複
サイトマップには「正規URL(canonical)」のみを載せるのが推奨ですが、実際にはパラメータ付きURLや多言語URLが混在する場合もあります。URL正規化(クエリの扱い、末尾スラッシュ、大小文字、www有無)と重複排除は必須です。
robots.txtと衝突
サイトマップでURLを見つけても、robots.txt でクロールを禁止している領域は取得しないのが原則です。クロール対象の設計時に、robots.txt のルールを読み取り、禁止パスをキュー投入前に弾いてください。
注意:スクレイピングは対象サイトの利用規約・法令・技術的制限(レート制限等)に配慮が必要です。サイトマップが公開されていることは「何でも自由に取得してよい」ことを意味しません。
サイトマップ比較
最後に、URL収集の起点として「サイトマップ」「リンク探索」「サイト内検索(一覧ページ)」を比較します。最短設計では、サイトマップを主軸にしつつ、欠落補完として他手段を併用するケースが多いです。
| 手段 | 強み | 弱み | 向くケース |
|---|---|---|---|
| サイトマップ | URL収集が速い、網羅性が高い | 欠落・誤運用があり得る | 商品/記事などURLが多いサイト |
| リンク探索 | サイトマップが無い場合でも動く | 深い階層に時間がかかる | 小規模サイト、導線が整理されたサイト |
| 一覧ページ起点 | カテゴリ構造を反映しやすい | ページングやJSで欠落しやすい | カテゴリ別に収集したい場合 |
クロール設計を短縮しませんか?
サイトマップ起点の設計から運用まで整えると、収集の速度と安定性が上がります。要件に合わせたクロール設計の相談も可能です。
まとめ
- 最短クロールの第一歩は、リンク探索の前にサイトマップでURL集合を確定すること
<lastmod>が正しければ差分クロールに有効。ただし誤運用もあるため検証が必要- URL正規化・重複排除・robots.txt配慮まで含めて設計すると、運用が安定する
公式仕様や検索エンジンのガイドは、挙動の前提を確認するのに役立ちます。必要に応じて参照してください。