尧图精选

Scrapy 如何用 SitemapSpider 从站点地图批量发现 URL 并发起爬取?

🕒 发布时间:2026/9/15 19:12:13 📁 来源:尧图网络
Scrapy 如何用 SitemapSpider 从站点地图批量发现 URL 并发起爬取【免费下载链接】scrapyScrapy, a fast high-level web crawling scraping framework for Python.项目地址: https://gitcode.com/GitHub_Trending/sc/scrapy当你已经知道目标站点的站点地图sitemap.xml地址但不知道页面 URL 的具体列表时Scrapy 内置的SitemapSpider可以直接下载站点地图、批量提取其中的 URL 条目并对匹配到的 URL 发起爬取请求。它还支持站点地图是指向多个子站点地图的索引文件Sitemap index file以及站点地图地址声明在robots.txt里的情况。本文给出从创建项目、编写这类 spider、到运行爬取并核对结果的完整操作路径。适用前提Python 3.10CPython 或 PyPy并已安装 Scrapy。安装文档建议把 Scrapy 装进专用虚拟环境避免与系统包冲突。准备安装 Scrapy 并创建项目python -m venv .venv source .venv/bin/activate pip install Scrapy然后用scrapy startproject创建项目并进入项目根目录即scrapy.cfg所在目录scrapy startproject myproject cd myproject默认项目结构里有一个myproject/spiders/目录见 命令工具文档spider 代码文件就放在这个目录里。scrapy genspider只提供basic、crawl、csvfeed、xmlfeed四种模板没有 SitemapSpider 模板所以需要自己新建文件。编写 SitemapSpider在myproject/spiders/下新建文件例如example_sitemap.py。最简单的形态是把sitemap_urls指向站点地图站点地图里发现的所有 URL 都会交给parse回调处理省略sitemap_rules时的默认行为见 spiders 文档from scrapy.spiders import SitemapSpider class ExampleSitemap(SitemapSpider): name example_sitemap sitemap_urls [http://www.example.com/sitemap.xml] def parse(self, response): yield {url: response.url}几个要点name是 spider 的唯一标识scrapy crawl靠它定位 spider必须唯一sitemap_urls是一组指向站点地图的 URL 列表是发出起始请求的依据yield {url: response.url}这种产出形式与仓库测试代码 tests/test_spider_sitemap.py 中的用法一致目的是让每个被发现的 URL 都产出一条 item方便后面用输出文件核对结果。实际项目里换成你要提取的字段即可。用 sitemap_rules 按 URL 模式分配回调如果只关心站点地图中的部分 URL或者不同 URL 要用不同方法解析用sitemap_rules。它是(regex, callback)元组的列表规则按定义顺序匹配只有第一条命中的规则会被使用regex可以是字符串或编译后的正则对象callback可以是 spider 方法名字符串或可调用对象from scrapy.spiders import SitemapSpider class MySpider(SitemapSpider): sitemap_urls [http://www.example.com/sitemap.xml] sitemap_rules [ (/product/, parse_product), (/category/, parse_category), ] def parse_product(self, response): pass # ... scrape product ... def parse_category(self, response): pass # ... scrape category ...入口是 robots.txt或站点地图是索引文件sitemap_urls也可以直接指向robots.txtScrapy 会解析它并提取其中的 sitemap 地址。如果站点使用指向其他站点地图文件的 Sitemap index file还可以用sitemap_follow一组正则限定要跟随哪些子站点地图默认是全部跟随from scrapy.spiders import SitemapSpider class MySpider(SitemapSpider): sitemap_urls [http://www.example.com/robots.txt] sitemap_rules [ (/shop/, parse_shop), ] sitemap_follow [/sitemap_shops] def parse_shop(self, response): pass # ... scrape shop here ...上面示例的效果是跟随robots.txt里声明的、URL 中包含/sitemap_shops的站点地图并用parse_shop处理匹配/shop/的 URL。可选按条目属性过滤如果站点地图里每个条目带属性如lastmod可以重写sitemap_filter(entries)。entries是逐个产出的 dict键是标签名值是其文本内容。文档给出的示例按日期过滤from datetime import datetime from scrapy.spiders import SitemapSpider class FilteredSitemapSpider(SitemapSpider): name filtered_sitemap_spider allowed_domains [example.com] sitemap_urls [http://example.com/sitemap.xml] def sitemap_filter(self, entries): for entry in entries: date_time datetime.strptime(entry[lastmod], %Y-%m-%d) if date_time.year 2005: yield entry使用这个方法时注意三条规则没有loc标签的条目会被丢弃alternate links 存放在键alternate的列表中XML 命名空间前缀会被去掉{namespace}tagname只剩tagname。可选与站点地图之外的 URL 来源组合需要额外爬取站点地图里没有的 URL 时重写start方法先迭代父类的结果再追加自己的请求from scrapy import Request from scrapy.spiders import SitemapSpider class MySpider(SitemapSpider): sitemap_urls [http://www.example.com/robots.txt] sitemap_rules [ (/shop/, parse_shop), ] other_urls [http://www.example.com/about] async def start(self): async for item_or_request in super().start(): yield item_or_request for url in self.other_urls: yield Request(url, self.parse_other) def parse_shop(self, response): pass # ... scrape shop here ... def parse_other(self, response): pass # ... scrape other here ...运行爬取并核对结果先确认 spider 被识别scrapy list输出是每行一个 spider 名。刚写的example_sitemap必须出现在列表里如果没出现说明文件没放进spiders/目录或代码有语法错误先修正再运行。运行爬取并把 item 写入文件scrapy crawl -O items.json example_sitemap-O FILE把抓到的 item 写入 FILE 并覆盖已有内容-o是追加模式。也可以在输出 URI 末尾加冒号显式指定格式例如-O items:json。运行完成后检查items.json按本文的最小示例文件里应包含若干{url: ...}条目每个条目对应站点地图里被发起爬取的一个 URL这就是“批量发现 URL 并发起爬取”的直接证据。用 fetch 确认站点地图本身能否下载如果列表正常但items.json是空的先单独确认站点地图是否可访问scrapy fetch http://www.example.com/sitemap.xmlfetch命令用 spider 下载页面的同一套方式下载并打印内容见 命令工具文档可以用它“看到”spider 实际拿到了什么。如果这里就拿不到 XML 内容问题在网络或站点地图地址本身而不是 spider 逻辑。站点地图无效时的日志现象当站点地图响应体为空或内容不是可识别的 sitemapurlset/sitemapindex时spider 不会从它发出任何请求并记录一条警告。仓库测试代码断言的日志形式如下示例Ignoring invalid sitemap: 200 http://www.example.com/sitemap.xml这条警告来自 scrapy/spiders/sitemap.py 的_parse_sitemap。看到它时回到上一步用fetch检查该 URL 返回的实际内容。边界与限制站点地图中缺少loc标签的条目会被直接丢弃xhtml:link relalternate声明的语言版本链接默认不会被抓取。sitemap_alternate_links默认关闭开启后同一个url块里的 loc 和 alternate 链接都会发起请求关闭时只取 locsitemap_rules按定义顺序匹配只有第一条命中的规则生效后面的规则不会再参与该 URL 的判定以.xml.gz结尾或实际为 gzip 压缩的站点地图会在解析前解压缩响应体是 gzip 文件时自行解压若由 HttpCompression 中间件已按Content-Encoding: gzip解好则直接按纯 XML 处理见 scrapy/spiders/sitemap.py 的_get_sitemap_body及 tests/test_spider_sitemap.py 中的相应用例。完成上述步骤后items.json或你替换后的输出文件中出现的 URL 集合就是本次从站点地图批量发现并爬取的结果需要扩大范围时调整sitemap_rules的正则、放宽sitemap_follow或在sitemap_urls里追加站点地图地址即可。【免费下载链接】scrapyScrapy, a fast high-level web crawling scraping framework for Python.项目地址: https://gitcode.com/GitHub_Trending/sc/scrapy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →