CrawlSpider
CrawlSpider
爬取全站数据
CrawlSpider其实是Spider的一个子类,除了继承到Spider的特性和功能外,还派生除了其自己独有的更加强大的特性和功能。其中最显著的功能就是”LinkExtractors链接提取器“。Spider是所有爬虫的基类,其设计原则只是为了爬取start_url列表中网页,而从爬取到的网页中提取出的url进行继续的爬取工作使用CrawlSpider更合适。
使用
- 创建scrapy工程:scrapy startproject projectName
- 创建爬虫文件:scrapy genspider -t crawl spiderName www.xxx.com
- 此指令对比以前的指令多了 "-t crawl",表示创建的爬虫文件是基于CrawlSpider这个类的,而不再是Spider这个基类。
- 观察生成的爬虫文件
# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor # 导入CrawlSpider相关模块
from scrapy.spiders import CrawlSpider, Rule
class ChoutidemoSpider(CrawlSpider): # 继承 CrawlSpider 类
name = 'choutiDemo'
#allowed_domains = ['www.chouti.com']
start_urls = ['http://www.chouti.com/']
rules = ( # 提取规则
Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
)
def parse_item(self, response):
pass
CrawlSpider类和Spider类的最大不同是CrawlSpider多了一个rules属性,其作用是定义”提取动作“。在rules中可以包含一个或多个Rule对象,在Rule对象中包含了LinkExtractor对象。
链接提取器 LinkExtractor
scrapy.linkextractors.LinkExtractor(
allow = (), # 符合正则表达式参数的数据会被提取
deny = (), # 符合正则表达式参数的数据禁止提取
allow_domains = (), # 包含的域名中可以提取数据
deny_domains = (), # 包含的域名中禁止提取数据
deny_extensions = (),
restrict_xpath = (), # 使用xpath提取数据,和allow共同起作用
tags = (), # 根据标签名称提取数据
attrs = (), # 根据标签属性提取数据
unique = True, # 剔除重复链接请求
)
规则解析器 Rule
rules = [
Rule(
link_extractor, # LinkExtractor对象
callback=None, # 请求到响应数据时的回调函数,不要使用 parse 作为回调函数
cb_kwargs=None, # 回调函数设置的参数,是否继续爬取,true 继续爬取,false 到此停止
follow=None, # 一个布尔值,指定是否应该从使用此规则提取的每个响应中跟踪链接。如果callback是follow默认值True,则默认为False
process_links=None, # 过滤 linkextractor 列表,每次获取列表时都会调用
process_request=None # 过滤request,每次提取request都会调用,该函数必须返回一个request或者None
)
]
流程
- 爬虫文件首先根据起始url,获取该url的网页内容
- 链接提取器会根据指定提取规则将步骤1中网页内容中的链接进行提取
- 规则解析器会根据指定解析规则将链接提取器中提取到的链接中的网页内容根据指定的规则进行解析
- 将解析数据封装到item中,然后提交给管道进行持久化存储
tips
- 重写
parse_start_url
方法可以作为start_url
的回调函数,实现对start_url
的解析
示例
爬取糗事百科糗图板块的所有页码数据
爬虫
# -*- coding: utf-8 -*-
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from qiubaiProjecct.items import QiubaiprojecctItem
from scrapy.http.response.html import HtmlResponse
class QiubaiSpider(CrawlSpider):
name = 'qiubai'
# allowed_domains = ['www.xxx.com']
start_urls = ['https://www.qiushibaike.com/pic/']
rules = (
Rule(LinkExtractor(allow=r'/pic/page/\d+\?s=\d+'), callback='parse_item', follow=True),
)
def parse_item(self, response: HtmlResponse):
print(response.url)
div_list = response.xpath('//div[@id="content-left"]/div')
for div in div_list:
author = div.xpath('./div[@class="author clearfix"]/a[@title]/@title').extract_first()
content = div.xpath('./a/div/span/text()').extract_first()
item = QiubaiprojecctItem()
item['author'] = author
item['content'] = content
yield item
item
# -*- coding: utf-8 -*-
import scrapy
class QiubaiprojecctItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
author = scrapy.Field()
content = scrapy.Field()
pipeline
# -*- coding: utf-8 -*-
class QiubaiprojecctPipeline(object):
def process_item(self, item, spider):
self.fp.write(f'作者:{item["author"]}\t,内容:{item["content"]}\n')
return item
def __init__(self):
self.fp = None
def open_spider(self, spider):
self.fp = open('qiubai.pic.txt', 'w', encoding='utf8')
def close_spider(self, spider):
self.fp.close()
settings
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
ROBOTSTXT_OBEY = False
ITEM_PIPELINES = {
'qiubaiProjecct.pipelines.QiubaiprojecctPipeline': 300,
}