python之简单Scrapy分布式爬虫的实现

分布式爬虫:爬虫共用同一个爬虫程序,即把同一个爬虫程序同时部署到多台电脑上运行,这样可以提高爬虫速度。

在默认情况下,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打开服务器(注意:服务器不能关)

python之简单Scrapy分布式爬虫的实现

 master和slave一起运行爬虫程序

重新打开一个终端

python之简单Scrapy分布式爬虫的实现

运行之后,master和slave会一起停留,等待命令

python之简单Scrapy分布式爬虫的实现

 这里再打开一个终端(红色部分为master的ip地址)

python之简单Scrapy分布式爬虫的实现

master和slave运行爬虫程序的终端将会继续执行

python之简单Scrapy分布式爬虫的实现

 这样就实现了分布式爬虫