2.10 CrawlSpider 和 Rule Scrapy CrawlSpider 与 Rule 详解 Scrapy 提供了多种 Spider 基类,其中 是一个非常强大的 Spider,特别适用于需要从网站上抓取多个页面,并遵循特定链接模式的情况。 依赖于 对象来定义抓取规则,从而实现自动化的页面发现和抓取。 CrawlSpider 简介 继承自 类,并添加了一些新的功能,使其能够根据预定义的规则自动发现和抓取链接。与需要手动解析每个页面并提取链接的 不同, 可以根据 自动完成这些任务。 CrawlSpider 的主要特点: 规则驱动: 通过 对象定义链接提取和页面处理规则。 自动化链接发现: 自动从匹配规则的页面中提取链接。 可配置性: 可以灵活配置链接提取规则和回调函数。
Scrapy 提供了多种 Spider 基类,其中 CrawlSpider 是一个非常强大的 Spider,特别适用于需要从网站上抓取多个页面,并遵循特定链接模式的情况。CrawlSpider 依赖于 Rule 对象来定义抓取规则,从而实现自动化的页面发现和抓取。
CrawlSpider 继承自 Spider 类,并添加了一些新的功能,使其能够根据预定义的规则自动发现和抓取链接。与需要手动解析每个页面并提取链接的 Spider 不同,CrawlSpider 可以根据 Rule 自动完成这些任务。
CrawlSpider 的主要特点:
规则驱动: 通过 Rule 对象定义链接提取和页面处理规则。
自动化链接发现: 自动从匹配规则的页面中提取链接。
可配置性: 可以灵活配置链接提取规则和回调函数。
避免重复抓取: 默认情况下,会过滤掉重复的链接。
Rule 对象定义了如何从页面中提取链接以及如何处理提取到的链接。Rule 对象包含以下几个重要的参数:
link_extractor (Link Extractor 对象): 用于从页面中提取链接的 Link Extractor 对象。
callback (callable): 当 Link Extractor 提取到链接时,用于处理 response 的回调函数。
cb_kwargs (dict): 传递给回调函数的关键字参数。
follow (boolean): 指定是否跟随提取到的链接。如果为 True,则会递归地抓取提取到的链接;如果为 False,则只抓取当前页面。
process_links (callable): 用于过滤链接的回调函数。
process_request (callable): 用于处理请求的回调函数。
Link Extractor 负责从页面中提取链接。Scrapy 提供了多种内置的 Link Extractor,最常用的是 LxmlLinkExtractor。
LxmlLinkExtractor 的常用参数:
allow (regex or string): 允许提取的链接的 URL 必须匹配的正则表达式或字符串。
deny (regex or string): 禁止提取的链接的 URL 必须匹配的正则表达式或字符串。
allow_domains (str or list): 允许提取的链接的域名。
deny_domains (str or list): 禁止提取的链接的域名。
restrict_xpaths (str or list): 限制链接提取的 XPath 表达式。
restrict_css (str or list): 限制链接提取的 CSS 选择器。
tags (str or list): 提取链接的标签。默认为 ('a', 'area')。
attrs (str or list): 提取链接的属性。默认为 ('href',)。
下面是一个使用 CrawlSpider 和 Rule 抓取博客文章的示例:
import scrapy from scrapy.spiders import CrawlSpider, Rule from scrapy.linkextractors import LxmlLinkExtractor class BlogSpider(CrawlSpider): name = 'blogspider' allowed_domains = ['example.com'] start_urls = ['http://example.com/blog'] rules = ( Rule(LxmlLinkExtractor(allow=r'/blog/\d+/\d+/\d+/'), callback='parse_item', follow=True), Rule(LxmlLinkExtractor(allow=r'/blog/page/\d+/'), follow=True), # 抓取分页链接 ) def parse_item(self, response): item = {} item['title'] = response.css('h1.entry-title::text').get() item['content'] = response.css('div.entry-content::text').getall() item['url'] = response.url return item
代码解释:
name: Spider 的名称,用于在 Scrapy 中标识 Spider。
allowed_domains: 允许抓取的域名列表。
start_urls: Spider 启动时要抓取的 URL 列表。
rules: 一个包含 Rule 对象的元组,定义了抓取规则。
第一个 Rule 使用 LxmlLinkExtractor 提取 URL 匹配 r'/blog/\d+/\d+/\d+/' (例如 /blog/2023/10/26/) 的链接,并使用 parse_item 方法处理 response。follow=True 表示会继续抓取这些链接指向的页面。
第二个 Rule 使用 LxmlLinkExtractor 提取 URL 匹配 r'/blog/page/\d+/' (例如 /blog/page/2/) 的链接,follow=True 表示会继续抓取这些分页链接指向的页面。 这个规则没有指定 callback,所以只是提取链接并继续抓取,不会调用任何解析函数。
parse_item: 回调函数,用于处理抓取到的页面。在这个例子中,它提取文章的标题、内容和 URL,并将它们存储在一个字典中。
CrawlSpider 会按照 rules 列表中 Rule 对象的顺序依次应用规则。如果一个 URL 匹配多个 Rule,则会按照规则的顺序依次执行。
可以通过在 Rule 对象中设置 priority 参数来调整规则的优先级。priority 值越大,优先级越高。
CrawlSpider 默认使用 RFPDupeFilter 中间件来过滤重复的请求。这意味着如果一个 URL 已经被抓取过,CrawlSpider 就不会再次抓取它。
可以通过设置 dont_filter=True 来禁用重复请求过滤。但是,通常情况下不建议这样做,因为它可能导致无限循环和大量的重复抓取。
process_links 和 process_requestprocess_links 和 process_request 是 Rule 对象中两个非常有用的参数,可以用于更精细地控制链接提取和请求处理。
process_links: 接受一个回调函数,该函数接收一个链接列表作为参数,并返回一个过滤后的链接列表。这可以用于在链接被添加到抓取队列之前对其进行过滤或修改。
def filter_links(links): filtered_links = [] for link in links: if 'example.com' in link.url: filtered_links.append(link) return filtered_links rules = ( Rule(LxmlLinkExtractor(allow=r'/blog/\d+/\d+/\d+/'), callback='parse_item', follow=True, process_links=filter_links), )
process_request: 接受一个回调函数,该函数接收一个 Request 对象作为参数,并返回一个 Request 对象。这可以用于在请求被发送之前对其进行修改,例如添加 headers 或 cookies。
def add_header(request): request.headers['My-Header'] = 'My-Value' return request rules = ( Rule(LxmlLinkExtractor(allow=r'/blog/\d+/\d+/\d+/'), callback='parse_item', follow=True, process_request=add_header), )
优势:
简化开发: 自动化的链接发现和抓取,减少了手动解析和提取链接的工作量。
高效抓取: 可以高效地抓取大型网站,并遵循特定的链接模式。
可扩展性: 可以通过自定义 Rule 对象来扩展抓取规则。
局限性:
规则复杂性: 当抓取规则非常复杂时,Rule 对象的配置可能会变得困难。
动态内容: 对于大量使用 JavaScript 动态加载内容的网站,CrawlSpider 可能无法有效地抓取链接。
下面是一个 Mermaid 图表,展示了 CrawlSpider 的工作流程:
图表解释:
Start URLs 是 Spider 启动时要抓取的 URL 列表。
CrawlSpider 根据 Rule 对象定义的规则,从页面中提取链接。
Link Extractor 负责从页面中提取链接。
如果链接匹配 Rule 的 allow 规则,则会调用 callback 函数处理 response。
callback 函数提取数据并将其传递给 Item Pipeline。
Item Pipeline 处理数据并将其存储到数据库或文件中。
CrawlSpider 会继续抓取提取到的链接,直到所有链接都被抓取完毕。
CrawlSpider 是 Scrapy 中一个非常强大的 Spider,特别适用于需要从网站上抓取多个页面,并遵循特定链接模式的情况。通过 Rule 对象,可以灵活地配置链接提取规则和回调函数,从而实现自动化的页面发现和抓取。掌握 CrawlSpider 和 Rule 的使用方法,可以大大提高 Scrapy 爬虫的开发效率。
在实际应用中,需要根据网站的结构和抓取需求,灵活地配置 Rule 对象的参数,例如 allow、deny、restrict_xpaths、restrict_css 等。同时,还需要注意避免重复抓取和处理动态内容等问题。