Scrapy爬虫利器:CrawlSpider详解
SCrapy框架扩展内容
CrawlSpider
CrawlSpider
是 Scrapy 框架中一个非常重要且强大的内置 Spider 类。它继承自基础的 Spider
类,但专门为一种常见爬虫任务而设计:遵循特定规则(Rules),从页面中提取所有符合要求的链接并跟进,持续地对整个网站进行有规律的、广度优先或深度优先的爬取。
你可以把它想象成一个设置了自动化导航规则的爬虫。
1. CrawlSpider 与基础 Spider 的核心区别
基础 Spider (
scrapy.Spider)
:你需要手动在
parse
方法或自定义的回调函数中提取链接,然后使用yield scrapy.Request(url, callback)
来发起新的请求。灵活性高,但编写跟踪大量链接的代码会非常繁琐和重复。
CrawlSpider:
它引入了一套规则系统 (
Rule
) 和链接提取器 (LinkExtractor
)。你只需要定义规则(Rules),告诉爬虫“哪些链接可以跟进”以及“跟进后用什么方法解析”。爬虫会自动根据这些规则发现和请求链接,大大简化了整站爬取的代码。
2. 核心组件详解
a. 链接提取器 (LinkExtractor)
LinkExtractor
的角色是“链接探测器”,它的任务是从一个网页(Response
)中找出所有我们感兴趣的链接。
常用参数:
allow
: 接收一个正则表达式或正则表达式列表。只有匹配这个正则的 URL 才会被提取。allow=r'.*\/category\/.*\.html'
(提取包含/category/
的.html
链接)
deny
: 与allow
相反,用于排除某些 URL。优先级高于allow
。restrict_xpaths
: 接收一个 XPath 表达式或列表,只在由该 XPath 选择的标签区域内提取链接。非常常用!restrict_xpaths='//div[@class="pagination"]'
(只从分页 div 中提取链接)
restrict_css
: 与restrict_xpaths
类似,但使用 CSS 选择器。tags
: 指定从哪些标签中提取链接(默认是['a', 'area']
)。attrs
: 指定从标签的哪个属性中提取链接(默认是['href']
)。
b. 规则 (Rule)
Rule
对象告诉爬虫如何处理由 LinkExtractor
提取到的链接。
常用参数:
link_extractor
: 一个定义好的LinkExtractor
实例。callback
: 指定用于解析由该规则提取到的链接返回的 Response 的回调函数方法名(字符串)。注意:不要写括号()
。follow
: 一个布尔值。决定了从这些新页面中提取到的链接是否继续遵循当前这条规则。callback
为None
时,follow
默认为True
。有
callback
时,follow
默认为False
。
process_links
: 一个可调用的函数(或函数名),用于过滤或处理LinkExtractor
提取到的链接列表,之后才会创建 Request 对象。process_request
: 一个可调用的函数,用于处理该规则生成的每个Request
对象(例如,给 Request 添加特定的 headers 或 meta)。
3. CrawlSpider 的工作流程
从
start_urls
开始爬取。下载
start_urls
的页面后,默认由parse_start_url
方法进行解析(你可以重写这个方法)。同时,所有的
Rule
都会被应用到这些初始页面上。LinkExtractor
会从中提取出符合条件的链接。对于每个提取到的链接,Scrapy 会创建一个
Request
对象。根据
Rule
中的定义:如果有
callback
,这个Request
的回调函数就是指定的方法。根据
follow
的值决定是否对这次新请求返回的页面再次应用相同的规则(即递归跟进)。
这个过程持续进行,直到没有新的链接被发现或达到深度限制等其他设置。
4. 如何创建一个 CrawlSpider
使用命令创建模板:
scrapy genspider -t crawl my_crawler example.com # 这会生成一个基于 CrawlSpider 的模板文件 my_crawler.py
一个典型的 CrawlSpider
代码结构如下:
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
class MyCrawlerSpider(CrawlSpider):name = 'my_crawler' # 爬虫名allowed_domains = ['example.com'] # 允许的域名start_urls = ['http://www.example.com'] # 起始URL
# 定义规则 (Rules)rules = (# Rule 1: 提取匹配‘/item/’的链接,并用parse_item方法解析,不继续跟进这些页面里的链接Rule(LinkExtractor(allow=r'/item/'), callback='parse_item', follow=False),
# Rule 2: 提取分页链接(例如下一页),这些页面本身不需要解析(callback=None),但需要继续跟进(follow=True)以应用其他规则Rule(LinkExtractor(restrict_xpaths='//a[@class="nextPage"]'), follow=True),)
# 解析商品详情页的回调函数def parse_item(self, response):item = {}item['title'] = response.xpath('//h1/text()').get()item['url'] = response.url# ... 提取其他数据return item
# 你可以选择重写parse_start_url方法,用于解析初始页面# def parse_start_url(self, response):# return self.parse_item(response) # 例如,如果起始页本身也是详情页
5. 适用场景与注意事项
适用场景:
有清晰结构的内容网站(如新闻站、博客、文档、电商网站)。
需要爬取大量遵循特定模式的页面(如所有分页、所有文章详情页、所有产品分类页)。
进行整站爬取或大规模数据采集。
注意事项:
小心循环链接:某些网站的分页或过滤条件可能会产生无限循环的 URL(如
?page=1
,?page=1&sort=asc
,?page=1&sort=desc
),需要使用allow
、deny
或process_links
精心设计规则来避免。规则顺序:
Rule
在rules
元组中的顺序很重要,规则是按顺序应用的。避免重复爬取:Scrapy 默认会自动过滤已经访问过的 URL(
DUPEFILTER_CLASS
),但你仍然需要确保规则不会生成大量不必要的重复请求。灵活性与控制力:虽然
CrawlSpider
很强大,但对于一些结构特别复杂或反爬严密的网站,有时手动编写请求逻辑的基础 Spider 可能更有控制力。
总结
CrawlSpider
是 Scrapy 为规则化、自动化的全站爬取提供的利器。它通过 LinkExtractor
(定义抓什么链接)和 Rule
(定义怎么处理链接)的分离与组合,极大地提升了开发效率,让开发者从繁琐的“手动发起请求”中解放出来,更专注于核心的数据解析逻辑。