SitemapSpider 怎么从 robots.txt 找到 sitemap、怎么处理索引和压缩、怎么用正则分流到不同回调?哪些响应会被认定为 sitemap?这篇在一个带索引、gz、备用链接的假站点上逐项验证。
服务器收到(按顺序):['/robots.txt', '/sitemap_index.xml', '/extra.html', '/sm/products.xml', '/sm/blog.xml.gz', '/sm/news.xml', '/p/1', '/p/2', '/p/3', '/blog/a', '/blog/b', '/news/1'] parse 回调的页面:['/blog/a', '/blog/b', '/news/1', '/p/1', '/p/2', '/p/3'] 警告:[scrapy.spiders.sitemap] WARNING: Ignoring invalid sitemap: <200 http://127.0.0.1:9960/extra.html>
sitemap_urls 可以直接是 sitemap,也可以是 robots.txt:后者读取其中的 Sitemap: 行。sitemapindex 里的子 sitemap 会递归请求,.xml.gz 和即时压缩的响应都能解开。
规则 [(/p/, parse_product), (/blog/, parse_blog)]:回调 [('blog', 'a'), ('blog', 'b'), ('product', '1'), ('product', '2'), ('product', '3')];服务器收到页面请求 ['/blog/a', '/blog/b', '/p/1', '/p/2', '/p/3'](/news/1 没有规则匹配,没有请求)sitemap_rules 按顺序取第一个匹配的正则,没匹配的 URL 不请求。
sitemap_follow=["products","news"]:服务器收到 sitemap 请求 ['/sitemap_index.xml', '/sm/products.xml', '/sm/news.xml'];parse 页面 ['/news/1', '/p/1', '/p/2', '/p/3'](blog.xml.gz 没有被请求)
sitemap_follow 决定索引里哪些子 sitemap 要跟,默认全部。
entry p/1 lastmod=2025-01-01 键=['alternate', 'lastmod', 'loc'] entry p/2 lastmod=2025-02-01 键=['alternate', 'lastmod', 'loc'] entry p/3 lastmod=2025-03-01 键=['alternate', 'lastmod', 'loc'] entry blog/a lastmod=2024-01-01 键=['lastmod', 'loc'] entry blog/b lastmod=2025-06-01 键=['lastmod', 'loc'] entry news/1 lastmod=2025-09-01 键=['lastmod', 'loc'] 只保留 lastmod ≥ 2025-02 的:parse 页面 ['/blog/b', '/news/1', '/p/2', '/p/3']
重写 sitemap_filter 可以按 lastmod 等字段筛选条目。
False(默认):parse 页面 ['/p/1', '/p/2', '/p/3'] True:parse 页面 ['/p/1', '/p/1?lang=en', '/p/2', '/p/2?lang=en', '/p/3', '/p/3?lang=en']
sitemap_alternate_links = True 会把 xhtml:link 的备用地址也当作页面。
/sm/products.xml → parse 页面 ['/p/1', '/p/2', '/p/3'] /sitemap.php → parse 页面 ['/y/1'] /sm/plain-ct → parse 页面 [] [警告:Ignoring invalid sitemap] /sm/news.xml → parse 页面 ['/news/1'] /sm/blog.xml.gz → parse 页面 ['/blog/a', '/blog/b']
响应必须是 XmlResponse、gzip 或 URL 以 .xml/.xml.gz 结尾,否则被当作无效 sitemap 忽略。服务器发 text/plain 的 sitemap 要特别留意。