redis分布式部署
- 概念:可以将一组程序执行在多台机器上(分布式机群),使其进行数据的分布爬取。
1.scrapy框架是否可以自己实现分布式?
其一:因为多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器无法分配start_urls列表中的url。(多台机器无法共享同一个调度器)
其二:多台机器爬取到的数据无法通过同一个管道对数据进行统一的数据持久出存储。(多台机器无法共享同一个管道)
2.基于scrapy-redis组件的分布式爬虫
- scrapy-redis组件中为我们封装好了可以被多台机器共享的调度器和管道,我们可以直接使用并实现分布式数据爬取。
- 实现方式:
1.基于该组件的RedisSpider类
2.基于该组件的RedisCrawlSpider类
3.分布式实现流程:上述两种不同方式的分布式实现流程是统一的
- 3.1 下载scrapy-redis组件:pip install scrapy-redis
- 3.2 redis配置文件的配置:
- 注释该行:bind 127.0.0.1,表示可以让其他ip访问redis - 将yes该为no:protected-mode no,表示可以让其他ip操作redis
3.3 修改爬虫文件中的相关代码:
- 将爬虫类的父类修改成基于RedisSpider或者RedisCrawlSpider。
注意:如果原始爬虫文件是基于Spider的,则应该将父类修改成RedisSpider,如果原始爬虫文件是基于CrawlSpider的,则应该将其父类修改成RedisCrawlSpider。
- 注释或者删除start_urls列表,切加入redis_key属性,属性值为scrpy-redis组件中调度器队列的名称
3.4 在setting中进行相关配置,开启使用scrapy-redis组件中封装好的管道
ITEM_PIPELINES = {
‘scrapy_redis.pipelines.RedisPipeline‘:400,
}
3.5 在setting文件中进行相关配置,开启使用scrapy-redis组件中封装好的调度器
# 使用scrapy-redis组件的去重队列
# 增加一个去重容器类的配置,作用是用Redis的set集合来存储请求的指纹数据,从而实现请求去重的持久化
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis组件自己的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 配置调度器是否要持久化,也就是当爬虫结束了,要不要清空Redis中请求队列和去重指纹的set。True:表示要持久化存储,不清空数据;False清空数据
SCHEDULER_PERSIST = True
3.6 在setting文件中进行爬虫程序链接redis的配置:
3.7 开启redis服务器:redis-server 配置文件
携带配置文件启动redis服务【windows终端切换到redis文件目录】
redis-server ./redis.windows.conf
3.8 开启redis客户端:【windows终端中输入】
redis-cli
3.9 运行爬虫文件:scrapy runspider SpiderFile
pycharm终端进入spider文件目录,输入【scrapy runspider xxx.py】
3.10 向调度器队列中扔入一个起始url(在redis客户端中操作):lpush redis_key属性值 起始url
windows终端输入:lpush ts www.xxx.com
3.11 redis客户端【redis-cli】中显示数据【items:xxx】
实例:阳光热线
# 1.spider文件 import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from scrapyRedisPro.items import ScrapyredisproItem from scrapy_redis.spiders import RedisCrawlSpider class ScrapyredisSpider(RedisCrawlSpider): name = ‘scrapyredis‘ redis_key = ‘ts‘ # 可以被共享的调度器中的队列名称 rules = ( Rule(LinkExtractor(allow=r‘tupe=4&page=\d+‘), callback=‘parse_item‘, follow=True), ) def parse_item(self, response): tr_list = response.xpath(‘//*[@id="morelist"]/div/table[2]//tr/td/table//tr‘) for tr in tr_list: title = tr.xpath(‘./td[2]/a[2]/text()‘).extract_first() net_friend = tr.xpath(‘./td[4]/text()‘).extract_first() item = SunlinecrawlItem() item[‘title‘] = title item[‘net_friend‘] = net_friend yield item # 提交的item必须保证提交到可以被共享的管道中 ---------------------------------------------------------------------------------------- # 2.setting文件 BOT_NAME = ‘scrapyRedisPro‘ SPIDER_MODULES = [‘scrapyRedisPro.spiders‘] NEWSPIDER_MODULE = ‘scrapyRedisPro.spiders‘ USER_AGENT = ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36‘ ROBOTSTXT_OBEY = False LOG_LEVEL = ‘ERROR‘ ITEM_PIPELINES = { ‘scrapy_redis.pipelines.RedisPipeline‘:400, } # 使用scrapy-redis组件的去重队列 # 增加一个去重容器类的配置,作用是用Redis的set集合来存储请求的指纹数据,从而实现请求去重的持久化 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 使用scrapy-redis组件自己的调度器 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 是否允许暂停 # 配置调度器是否要持久化,也就是当爬虫结束了,要不要清空Redis中请求队列和去重指纹的set。True:表示要持久化存储,不清空数据;False清空数据 SCHEDULER_PERSIST = True # 指定ip和port REDIS_HOSR = ‘127.0.0.1‘ #【redis服务器ip地址】【真实ip】 REDIS_PORT = 6379 # 当前请求数量【开启32个线程】 CONCURRENT_REQUESTS = 32 ---------------------------------------------------------------------------------------- # 3.items文件 import scrapy class ScrapyredisproItem(scrapy.Item): title = scrapy.Field() net_friend = scrapy.Field()
对应redis终端指令 开启redis服务器:redis-server 配置文件 D:\redis>redis-server.exe ./redis.windows.conf 开启redis客户端 D:\redis>redis-cli 查看redis数据库当前数据 127.0.0.1:6379> keys * (empty list or set) 向调度器队列中扔入一个起始url(在redis客户端中操作) 127.0.0.1:6379> lpush ts http://wz.sun0769.com/index.php/question/questionType?type=4&page=