一 介绍
原来scrapy的Scheduler维护的是本机的任务队列(存放Request对象及其回调函数等信息)+本机的去重队列(存放访问过的url地址)
所以实现分布式爬取的关键就是,找一台专门的主机上运行一个共享的队列比如Redis,
然后重写Scrapy的Scheduler,让新的Scheduler到共享队列存取Request,并且去除重复的Request请求,所以总结下来,实现分布式的关键就是三点:
#1、共享队列 #2、重写Scheduler,让其无论是去重还是任务都去访问共享队列 #3、为Scheduler定制去重规则(利用redis的集合类型)
以上三点便是scrapy-redis组件的核心功能
#安装: pip3 install scrapy-redis #源码: D:python3.6Libsite-packagesscrapy_redis
二、scrapy-redis组件
使用分布式爬虫步骤
1、安装
# pip3 install scrapy-redis
2、爬虫继承RedisSpider,(原来继承Spider)
import scrapy from cnblogs.items import CnblogsMysqlItem from scrapy_redis.spiders import RedisSpider class CnblogSpider(RedisSpider): name = 'cnblog' allowed_domains = ['www.cnblogs.com'] redis_key = 'myspider:start_urls' # start_urls = ['http://www.cnblogs.com/'] def parse(self, response): # 爬取cnblogs文章,把标题连接地址和文章内容保存到mysql,连续爬取n页 article_list = response.css('.post-item') for article in article_list: item = CnblogsMysqlItem() title = article.css('.post-item-title::text').extract_first() title_url = article.css('.post-item-title::attr(href)').extract_first() summary = article.css('.post-item-summary::text').extract_first() # 将解析到的数据封装至items对象中,注意:不支持item.title = title方式 item['title'] = title item['title_url'] = title_url item['summary'] = summary # 要继续爬取详情 # callback如果不写,默认回调到parse方法 # 如果写了,响应回来的对象就会调到自己写的解析方法中 # meta将参数传到回调函数 yield scrapy.Request(title_url, callback=self.parser_detail, meta={'item': item}) # 查找当前页是否存在下一页 pager = response.xpath('//div[@class="pager"]') next_page = pager.xpath('.//a[last()]/text()').extract_first() # print(next_page) if next_page is ">": next_page_url = pager.xpath('.//a[last()]/@href').extract_first() next_page_url_full = 'https://www.cnblogs.com%s' % next_page_url print(next_page_url_full) yield scrapy.Request(next_page_url_full, callback=self.parse) # yield scrapy.Request(next_page_url_full, callback=self.parse) def parser_detail(self, response): item = response.meta.get('item') # item哪里来 content = response.css('#cnblogs_post_body').extract_first() item['content'] = content print(item) yield item
3、不能写start_urls,需要写redis_key,具体见2
4、setting中配置:
# 使用scrapy-redis的去重 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 使用scrapy-redis的Scheduler # 分布式爬虫的配置 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 持久化的可以配置,也可以不配置 # 开启管道 ITEM_PIPELINES = { # 'cnblogs.pipelines.CnblogsFilePipeline': 300, 'cnblogs.pipelines.CnblogsMysqlPipeline': 305, 'scrapy_redis.pipelines.RedisPipeline': 299 } # 默认scrapy-redis链接redis是127.0.0.1:6379,如果想改见下面配置 REDIS_HOST = 'localhost' # 主机名 REDIS_PORT = 6379 # 端口 #REDIS_PASS = 'redisP@ssw0rd' # 密码 REDIS_URL = 'redis://user:pass@hostname:9001' # 连接URL(优先于上面三行配置) REDIS_PARAMS = {} # Redis连接参数 REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient' # 指定连接Redis的Python模块 REDIS_ENCODING = "utf-8" # redis编码类型
示例启动三个进程演示:
5、现在要让爬虫运行起来,需要去redis中以myspider:start_urls为key,插入一个起始地址
# lpush myspider:start_urls https://www.cnblogs.com/