CrawlSpider
其实是Spider
的一个子类,除了继承到Spider
的特性和功能外,还派生除了其自己独有的更加强大的特性和功能。其中最显著的功能就是”LinkExtractors
链接提取器“。是所有爬虫的基类,其设计原则只是为了爬取start_url
列表中网页,而从爬取到的网页中提取出的url
进行继续的爬取工作使用CrawlSpider
更合适。
前我们爬取起始页面以外的其他列表页时,使用了递归爬取的方式,即使用 `Request`模块递归回调`parse`方法 ,不太熟悉可参考[递归的访问](https://www.diandian100.cn/64071ba.html#%E9%80%92%E5%BD%92%E7%9A%84%E8%AE%BF%E9%97%AE)。今天我们通过使用`CrawlSpider`来进行目标爬取,感受下写原生递归爬取有何不同及优势。
创建爬虫工程 1 scrapy startproject mySpider
创建爬虫 1 2 3 4 # 进入爬虫工程 cd mySpider # 创建爬虫 scrapy genspider -t crawl chouti www.chouti.com
爬虫代码 CrawlSpider
类和Spider
类的最大不同是CrawlSpider
多了一个rules
属性,其作用是定义”提取动作“。在rules
中可以包含一个或多个Rule
对象,在Rule对象中包含了LinkExtractor
对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import scrapyfrom scrapy.linkextractors import LinkExtractorfrom scrapy.spiders import CrawlSpider, Ruleclass ChoutidemoSpider (CrawlSpider ): name = 'choutiDemo' start_urls = ['http://www.chouti.com/' ] rules = ( Rule(LinkExtractor(allow=r'Items/' ), callback='parse_item' , follow=True ), ) def parse_item (self, response ): i = {} return i
链接提取器,用来提取response
中符合规则的链接。
1 2 3 4 5 6 7 LinkExtractor( allow=r'Items/' , deny=xxx, restrict_xpaths=xxx, restrict_css=xxx, deny_domains=xxx, )
Rule
规则解析器。根据链接提取器中提取到的链接,根据指定规则提取解析器链接网页中的内容。
1 Rule(LinkExtractor(allow=r'Items/' ), callback='parse_item' , follow=True )
参数1:指定链接提取器;参数2:指定规则解析器解析数据的规则(回调函数);参数3:是否将链接提取器继续作用到链接提取器提取出的链接网页中。当callback
为None
,参数3的默认值为true
。
rules
指定不同规则解析器。一个Rule对象表示一种提取规则。
流程 a)爬虫文件首先根据起始url
,获取该url
的网页内容
b)链接提取器会根据指定提取规则将步骤a中网页内容中的链接进行提取
c)规则解析器会根据指定解析规则将链接提取器中提取到的链接中的网页内容根据指定的规则进行解析
d)将解析数据封装到item
中,然后提交给管道进行持久化存储
实战 爬取糗图所有列表页面 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import scrapyfrom scrapy.linkextractors import LinkExtractorfrom scrapy.spiders import CrawlSpider, Ruleclass CrawldemoSpider (CrawlSpider ): name = 'qiubai' start_urls = ['https://www.qiushibaike.com/pic/' ] link = LinkExtractor(allow=r'/pic/page/\d+\?' ) link1 = LinkExtractor(allow=r'/pic/$' ) rules = ( Rule(link, callback='parse_item' , follow=True ), Rule(link1, callback='parse_item' , follow=True ), ) def parse_item (self, response ): print (response)
爬取糗图作者内容 爬虫文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import scrapyfrom scrapy.linkextractors import LinkExtractorfrom scrapy.spiders import CrawlSpider, Rulefrom qiubaiBycrawl.items import QiubaibycrawlItemimport reclass QiubaitestSpider (CrawlSpider ): name = 'qiubaiTest' start_urls = ['http://www.qiushibaike.com/' ] page_link = LinkExtractor(allow=r'/8hr/page/\d+/' ) rules = ( Rule(page_link, callback='parse_item' , follow=True ), ) def parse_item (self, response ): div_list = response.xpath('//div[@id="content-left"]/div' ) for div in div_list: item = QiubaibycrawlItem() item['author' ] = div.xpath('./div/a[2]/h2/text()' ).extract_first().strip('\n' ) item['content' ] = div.xpath('.//div[@class="content"]/span/text()' ).extract_first().strip('\n' ) yield item
item
文件1 2 3 4 5 import scrapyclass QiubaibycrawlItem (scrapy.Item): author = scrapy.Field() content = scrapy.Field()
管道文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class QiubaibycrawlPipeline (object ): def __init__ (self ): self.fp = None def open_spider (self,spider ): print ('开始爬虫' ) self.fp = open ('./data.txt' ,'w' ) def process_item (self, item, spider ): self.fp.write(item['author' ]+':' +item['content' ]+'\n' ) return item def close_spider (self,spider ): print ('结束爬虫' ) self.fp.close()