分布式爬虫:爬虫共用同一个爬虫程序,即把同一个爬虫程序同时部署到多台电脑上运行,这样可以提高爬虫速度。
在默认情况下,scrapy爬虫是单机爬虫,只能在一台电脑上运行,因为爬虫调度器当中的队列queue去重和set集合都是在本机上创建的,其他的电脑无法访问另外一台电脑上的内存的内容;想要让多台机器共用一个queue队列和set集合,可以让scrapy结合scrapy_redis来完成。
要实现分布式爬虫,首先要配置服务器主从:
配置主从的目的:
1、达到一个备份的功能,一旦master出现崩溃,而数据库中还有数据的话
可以将其中的一个slave重新设置为主服务器,从而恢复Redis的正常运行
2、一个Redis服务器负责读写,性能较低,通过主从来减轻一个Redis的压力
下面通过爬伯乐在线来介绍具体怎么实现:
第一步:
在爬虫文件中引入RedisCrawSpider和Rule
from scrapy_redis.spiders import RedisCrawlSpider
from scrapy.spiders import Rule
#让类继承RedisCrawSpider
class BlogSpider(RedisCrawlSpider):
name = 'blog'
#允许爬虫的范围
allowed_domains = ['blog.jobbole.com']
#用于查找所有符合给定模式的key
redis_key = 'blogspider:start_urls'
第二步:
完成需求,我的需求:获取所有文章的标题 图片地址 时间 详情页地址 收藏 点赞 评论
引入scrapy
import scrapy
获取数据:
def parse(self, response):
div_list = response.xpath('//div[@class="post floated-thumb"]')
for div in div_list:
img = div.xpath('.//div[@class="post-thumb"]/a/img/@src').extract_first('')
title_url = div.xpath('.//div[@class="post-meta"]/p/a/@href').extract_first('')
yield scrapy.Request(url=title_url,meta={'img':img},callback=self.get_detail_with_url)
def get_detail_with_url(self,response):
img = response.meta['img']
detail_url = response.url
title = response.xpath('//div[@class="entry-header"]/h1/text()').extract_first('')
dian_zan = response.xpath('//div[@class="post-adds"]/span/h10/text()').extract_first('')
book_mark = response.xpath('//div[@class="post-adds"]/span[@class=" btn-bluet-bigger href-style bookmark-btn register-user-only "]/text()').extract_first('')
book_mark = book_mark.split(' ')[1]
book_num = 0
if len(book_mark) != 0:
book_num = int(book_mark)
comment = response.xpath('//div[@class="post-adds"]/a/span/text()').extract_first('')
comment = comment.split(' ')[1]
comment_num = 0
if len(comment) != 0:
comment_num = int(comment)
time = response.xpath('//div[@class="entry-meta"]/p/text()').extract_first('')
第三步:
将值传入items.py(存放数据模型)中
在items.py中写入要获得的数据
import scrapy
class JobboleItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
img = scrapy.Field()
title = scrapy.Field()
time = scrapy.Field()
detail_url = scrapy.Field()
dian_zan = scrapy.Field()
book_mark = scrapy.Field()
comment = scrapy.Field()
在爬虫文件中引入items.py中的类名
from ..items import JobboleItem
在第二步代码的最后实例化item,并传值
item = JobboleItem()
item['img'] = [img]
item['title'] = title
item['time'] = time
item['detail_url'] = detail_url
item['dian_zan'] = dian_zan
item['book_mark'] = book_num
item['comment'] = comment_num
yield item
第四步:
设置settings.py
# 使用scrapy_redis的去重类 不使用scrapy默认的去重类
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy_redis的调度器 不使用scrapy默认的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 控制爬虫是否允许暂停
SCHEDULER_PERSIST = True
ITEM_PIPELINES = {
'jobbole.pipelines.JobbolePipeline': 300,
# 'jobbole.pipelines.jobboleDownImage':1,
'scrapy_redis.pipelines.RedisPipeline': 400,
}
# 域名为字符串 如果不写 默认为本机 数据库的ip
# 注意:若为master这里的域名应该写本机的域名,我这里写127.0.0.1来代替
若为slave这里写master的域名
REDIS_HOST = '127.0.0.1'
# 端口为数字
REDIS_PORT = 6379
第五步:
master打开服务器(注意:服务器不能关)
master和slave一起运行爬虫程序
重新打开一个终端
运行之后,master和slave会一起停留,等待命令
这里再打开一个终端(红色部分为master的ip地址)
master和slave运行爬虫程序的终端将会继续执行
这样就实现了分布式爬虫