redis分布式部署
scrapy框架是否可以自己实现分布式?
不可以原因有两点
其一:因为多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器无法分配start_urls列表中的url。(多台机器无法共享同一个调度器)
其二:多台机器爬取到的数据无法通过同一个管道对数据进行统一的数据持久出存储。(多台机器无法共享同一个管道)
基于scrapy-redis组件的分布式爬虫
scrapy-redis组件中为我们封装好了可以被多台机器共享的调度器和管道,我们可以直接使用并实现分布式数据爬取
实现方式:
1.基于该组件的RedisSpider类 ==》基于该组件的RedisCrawlSpider类
分布式实现流程:
一.修改爬虫文件 1.导入scrapy-redis模块:from scrapy_redis.spiders import RedisSpider 2.将当前爬虫类的父类修改成RedisSpider 3.将allowed_domains和start_urls进行删除 4.添加一个新的属性redis_key = 'xxx',该属性值表示的就是可以被共享的调度器队列的名称 二.进行配置文件的配置 1.保证爬虫文件发起的请求都会被提交到可以被共享的调度器的队列中 SCHEDULER = "scrapy_redis.scheduler.Scheduler"
2.确保所有爬虫共享相同的去重指纹
DUPEFILTER = "scrapy_redis.dupefilter.RFPDuperFilter"
3.保证爬虫文件提交的item会被存储到可以被共享的管道中 ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline': 400 }
4. 在redis中保持scrapy-redis用到的队列,不会清理redis中的队列,从而实现暂停和恢复功能
SCHEDULER_PERSTST = True
5.配置最终数据存储的redis数据库 REDIS_HOST = 'redis服务的ip地址' REDIS_PORT = 6379 REDIS_ENCODING = ‘utf-8’ REDIS_PARAMS = {‘password’:’123456’} 6.redis数据库的配置文件进行配置:关闭保护模式和 改bind 0.0.0.0 7.开启redis服务和客户端 8.执行爬虫文件:scrapy runspider xxx.py 9.向调度器队列中仍入一个起始的url:
代码如下
1.创建项目和应用
scrapy start project redisDemo
cd redisDemo
scrapy genspider testDemo
# -*- coding: utf-8 -*- import scrapy from scrapy_redis.spiders import RedisSpider from redisDemo.items import RedisdemoItem ''' 一.修改爬虫文件 1.导入scrapy-redis模块:from scrapy_redis.spiders import RedisSpider 2.将当前爬虫类的父类修改成RedisSpider 3.将allowed_domains和start_urls进行删除 4.添加一个新的属性redis_key = 'xxx',该属性值表示的就是可以被共享的调度器队列的名称 二.进行配置文件的配置 1.保证爬虫文件发起的请求都会被提交到可以被共享的调度器的队列中 SCHEDULER = "scrapy_redis.scheduler.Scheduler" 2.保证爬虫文件提交的item会被存储到可以被共享的管道中 ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline': 400 } 3.配置最终数据存储的redis数据库 REDIS_HOST = 'redis服务的ip地址' REDIS_PORT = 6379 REDIS_ENCODING = ‘utf-8’ REDIS_PARAMS = {‘password’:’123456’} 4.redis数据库的配置文件进行配置:关闭保护模式和 改bind 0.0.0.0 5.开启redis服务和客户端 6.执行爬虫文件:scrapy runspider xxx.py 7.向调度器队列中仍入一个起始的url: ''' class TestdemoSpider(RedisSpider): name = 'testDemo' # allowed_domains = ['www.x.com'] # 不注释可能会出问题 # start_urls = ['http://www.x.com/'] # 起始url需手动输入 redis_key = 'cmdb' # 表示的就是可以被共享的调度器队列的名称 url = 'http://db.pharmcube.com/database/cfda/detail/cfda_cn_instrument/%d' # 所有的url page = 1 # 生成所有url的公共变量 def parse(self, response): item = RedisdemoItem() # 实例化item item['num'] = response.xpath('/html/body/div/table/tbody/tr[1]/td[2]/text()').extract_first() item['company_name'] = response.xpath('//html/body/div/table/tbody/tr[2]/td[2]/text()').extract_first() item['company_address'] = response.xpath('/html/body/div/table/tbody/tr[3]/td[2]/text()').extract_first() yield item urls = [] if self.page < 130000: self.page += 1 new_url = format(self.url % self.page) yield scrapy.Request(url=new_url, callback=self.parse)