分布式爬虫,可以让很多台电脑都使用同一个的爬虫程序,将爬虫分发得到多台电脑上,这样可以提高爬虫的速度,也就是分布式爬虫。
分布式爬虫需要专门的模块scrapy-redis,原生的scrapy框架无法实现分布式爬取,原因在于:(1)scrapy框架中五大核心组件中的调度器只归属于该项目,无法实现被分布式集群共享;(2)scrapy框架中五大核心组件中的调度器管道只接受该项目的数据对象,无法实现被分布式集群共享。
基于scrapy-redis组件的分布式爬虫
scrapy-redis组件中已经封装好了可以被多台机器共享的调度器和管道,可以直接使用并实现分布式数据爬取。要想实现分布式,必须要有共享的调度器队列和共享管道爬(爬取的数据必须存储在redis中,因为是基于scrapy-redis模块,内置封装的方法)
实现方式有两种: (1)基于该组件的RedisSpider类;(2)基于该组件的RedisCrawlSpider类。
分布式爬取数据案例
东莞阳光网(http://wz.sun0769.com/index.php/question/report?page=)
1.安装下载scrapy-redis模块
pip install scrapy-redis
2.创建爬虫项目(基于CrawlSpider来实现)
scrapy startproject fbsPro
cd fbsPro
scrapy genspider -t crawl fbsTest www.xxx.com
3.修改爬虫文件
1 import scrapy 2 from scrapy.linkextractors import LinkExtractor 3 from scrapy.spiders import CrawlSpider, Rule 4 from fbsPro.items import FbsproItem 5 from scrapy_redis.spiders import RedisCrawlSpider 6 7 8 #分布式实现不需要依赖scrapy框架提供的起始url调度器和管道 9 #(1)导入scrapy-redis模块封装好的类,将爬虫类的父类指定成RedisCrawlSpider 10 class FbstestSpider(RedisCrawlSpider): 11 name = 'fbsTest' 12 # allowed_domains = ['www.xxx.com'] 13 # start_urls = ['http://www.xxx.com/'] 14 15 # 分布式爬虫的起始url是放在共享调度器队列中的 16 #(2)分布式实现要指定共享调度器队列 17 redis_key = 'fbsQueue' # 可以被共享的调度器队列的名称 18 19 #本案例采用CrawlSpider实现自动全站爬取 20 # Rule是规则解析器; 21 # LinkExtractor是连接提取器,提取符合allow规则的完整的url; 22 # callback指定当前规则解析器的回调解析函数; 23 # follow指定是否将链接提取器继续作用到链接提取器提取出的链接网页; 24 # follow不指定默认False; 25 rules = ( 26 Rule(LinkExtractor(allow=r'page=d+'), callback='parse_item', follow=True), 27 ) 28 29 def parse_item(self, response): 30 item = FbsproItem() 31 tr_list = response.xpath('//*[@id="morelist"]/div/table[2]/tbody/tr/td/table/tbody/tr') 32 for tr in tr_list: 33 item['identifier'] = tr.xpath('./td[1]/text()').extract_first() # 解析编号 34 item['title'] = tr.xpath('/td[2]/a[2]/text()').extract_first() # 解析标题 35 yield item
4.items.py字段属性定义
1 import scrapy 2 3 4 class FbsproItem(scrapy.Item): 5 identifier=scrapy.Field() 6 title=scrapy.Field() 7 pass
5.settings.py配置文件
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" ROBOTSTXT_OBEY = False LOG_LEVEL="ERROR" #(1) 指定管道(自动持久化存储) ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline': 400 } #(2)指定调度器 # 增加了一个去重容器类的配置, 作用使用Redis的set集合来存储请求的指纹数据, 从而实现请求去重的持久化 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 使用scrapy-redis组件自己的调度器 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 配置调度器是否要持久化, 也就是当爬虫结束了, 要不要清空Redis中请求队列和去重指纹的set。如果是True, 就表示要持久化存储, 就不清空数据, 否则清空数据 SCHEDULER_PERSIST = True #(3)指定数据库 # REDIS_HOST = 'redis服务的ip地址'(注意不能是本机回环地址,此redis需要共用) REDIS_HOST = '192.168.0.103' REDIS_PORT = 6379
6.配置redis数据库
修改redis数据库配置文件:redis.windows.conf(windows)或者redis.conf(linux)
56行注释:#bind 127.0.0.1
关闭保护模式:protected-mode no
7.指定配置文件启动redis数据库服务
redis-server ./redis.windows.conf
8.启动爬虫项目(可以在多台机器上运行实现分布式)
进入到爬虫文件对应的目录中:scrapy runspider fbsTest.py
9.启动redis客户端,向共享调度器队列放进其实url
redis-cli
lpush fbsQueue http://wz.sun0769.com/index.php/question/report?page= (向在爬虫文件中指定的)