CrawlSpider继承自Spider, CrawlSpider主要用于有规则的url进行爬取。
先来说说它们的设计区别:
SpiderSpider 类的设计原则是只爬取 start_urls 中的url
,而 CrawlSpider 类定义了一些规则 rules 来提供跟进链接 link 的方便机制,从爬取的网页中获取link
并继续跟进的工作。
先来看看刚创建一个crawlSpider的爬虫 -t 指定模板为crawlSpider
scrapy genspider -t crawl cf circ.gov.cn
LinkExtractor 的源码:
from scrapy.linkextractors import LinkExtractor
allow :满足括号中”正则表达式”的值会被提取,如果为空,则全部匹配。
deny :与这个正则表达式(或正则表达式列表)不匹配的url一定不提取
allow_domain:会被提取的连接的domains
deny_domains :一定不会被提取链接的domains。
restrict_xpaths :使用xpath表达式,和allow共同作用过滤链接。
restrict_css :使用css选择器
在CrawlSpider源码中最先定义的是类Rule:Rule对象是一个爬取规则的类
link_extractor :是一个Link Extractor对象。其定义了如何从爬取到的页面提取链接。
callback :是一个callable或string(该Spider中同名的函数将会被调用)。从link_extractor中每获取到链接时将会调用该函数。该回调函数接收一个response作为其第一个参数,并返回一个包含Item以及Request对象(或者这两者的子类)的列表。
cb_kwargs :包含传递给回调函数的参数(keyword argument)的字典。
follow :是一个boolean值,指定了根据该规则从response提取的链接是否需要跟进。如果callback为None,follow默认设置True,否则默认False。
process_links :是一个callable或string(该Spider中同名的函数将会被调用)。从link_extrator中获取到链接列表时将会调用该函数。该方法主要是用来过滤。
process_request :是一个callable或string(该spider中同名的函数都将会被调用)。该规则提取到的每个request时都会调用该函数。该函数必须返回一个request或者None。用来过滤request
CrawlSpider类的源码:
rules :
是一个列表,存储的元素是Rule类的实例,其中每一个实例都定义了一种采集站点的行为。如果有多个rule都匹配同一个链接,那么位置下标最小的一个rule将会被使用。
__init__ :
它主要就是执行了_compile_rules方法
parse :
默认回调方法。源码进行了重写,所以我们自定义的函数,不可以使用这个名,这里直接调用方法 _parse_response ,并把 parse_start_url 方法作为处理response的方法。
parse_start_url :
它的主要作用就是处理parse返回的response,比如提取出需要的数据等,该方法也需要返回item、request或者他们的可迭代对象。它就是一个回调方法,和rule.callback用法一样。
_requests_to_follow :
它的作用就是从response中解析出目标url,并将其包装成request请求。该请求的回调方法是_response_downloaded,这里为request的meta值添加了rule参数,该参数的值是这个url对应rule在rules中的下标。
_response_downloaded :
该方法是方法 _requests_to_follow 的回调方法,作用就是调用 _parse_response 方法,处理下载器返回的 response ,设置 response 的处理方法为 rule.callback 方法。
_parse_response :
该方法将 resposne 交给参数callback代表的方法去处理,然后处理callback方法的requests_or_item。再根据rule.follow and spider._follow_links来判断是否继续采集,如果继续那么就将response交给_requests_to_follow方法,根据规则提取相关的链接。spider._follow_links的值是从settings的CRAWLSPIDER_FOLLOW_LINKS值获取到的。
_compile_rules :
作用就是将rule中的字符串表示的方法改成实际的方法,方便以后使用。
from_crawler :
用于创建,在scrapy源码中这种创建方式比较多
整个数据的流向如下图所示:
示例:
1.创建项目
scrapy startproject circ
2. 创建crawl爬虫
cd circ
scrapy genspider -t crawl cf circ.gov.cn
3.编写cf.py
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
import re class CfSpider(CrawlSpider):
name = 'cf'
allowed_domains = ['circ.gov.cn']
start_urls = ['http://www.circ.gov.cn/web/site0/tab5240/module14430/page1.htm'] #定义提取url地址规则
rules = (
#LinkExtractor 连接提取器,提取url地址
#callback 提取出来的url地址的response会交给callback处理
#follow 当前url地址的响应是够重新进过rules来提取url地址,
Rule(LinkExtractor(allow=r'/web/site0/tab5240/info\d+\.htm'), callback='parse_item'),
Rule(LinkExtractor(allow=r'/web/site0/tab5240/module14430/page\d+\.htm'),follow=True),
) #parse函数有特殊功能,不能定义
def parse_item(self, response):
item = {}
item["title"] = re.findall("<!--TitleStart-->(.*?)<!--TitleEnd-->",response.body.decode())[0]
item["publish_date"] = re.findall("发布时间:(20\d{2}-\d{2}-\d{2})",response.body.decode())[0]
print(item)