首页 > 数据库 >Day 25 25.2 Scrapy框架之分布式爬虫(scrapy_redis)

Day 25 25.2 Scrapy框架之分布式爬虫(scrapy_redis)

时间:2023-04-20 09:44:34浏览次数:31  
标签:25 25.2 Redis redis 爬虫 scrapy request Scrapy

分布式爬虫(scrapy_redis)

  • 分布式爬虫是指将一个大型的爬虫任务分解成多个子任务,由多个爬虫进程或者多台机器同时执行的一种爬虫方式。
    • 在分布式爬虫中,每个爬虫进程或者机器都具有独立的爬取能力,可以独立地爬取指定的网页或者网站,然后将爬取到的数据进行汇总和处理。
  • 分布式爬虫相对于单机爬虫的优势在于:
  1. 高效性:分布式爬虫可以同时爬取多个网页或者网站,从而大大提高爬取速度和效率。
  2. 可扩展性:分布式爬虫可以根据需要动态地添加或者删除爬虫进程或者机器,从而适应不同的爬虫任务需求。
  3. 高稳定性:分布式爬虫可以通过任务分解和数据备份等机制保证任务的连续性和稳定性。
  4. 高可靠性:分布式爬虫可以通过多个 IP 地址和 User-Agent 等方式来防止 IP 被封锁、反爬等问题。1

(1) scrapy-redis架构

Scheduler

  • Scrapy改造了python本来的collection.deque(双向队列)形成了自己的Scrapy queue,
    • 但是Scrapy多个spider不能共享待爬取队列Scrapy queue, 即Scrapy本身不支持爬虫分布式,
    • scrapy-redis 的解决是把这个Scrapy queue换成redis数据库(也是指redis队列)
    • 从同一个redis-server存放要爬取的request,便能让多个spider去同一个数据库里读取。
  • Scrapy中跟“待爬队列”直接相关的就是调度器Scheduler,它负责对新的request进行入列操作(加入Scrapy queue),取出下一个要爬取的request(从Scrapy queue中取出)等操作。
    • 它把待爬队列按照优先级建立了一个字典结构,比如:
{
        优先级0 : 队列0
        优先级1 : 队列1
        优先级2 : 队列2
    }
  • 然后根据request中的优先级,来决定该入哪个队列,出列时则按优先级较小的优先出列。
    • 为了管理这个比较高级的队列字典,Scheduler需要提供一系列的方法。
    • 但是原来的Scheduler已经无法使用,所以使用Scrapy-redis的scheduler组件。

Duplication Filter

  • Scrapy中用集合实现这个request去重功能,Scrapy中把已经发送的request指纹放入到一个集合中,把下一个request的指纹拿到集合中比对,如果该指纹存在于集合中,说明这个request发送过了,如果没有则继续操作。

  • 在scrapy-redis中去重是由Duplication Filter组件来实现的,它通过redis的set 不重复的特性,巧妙的实现了Duplication Filter去重。

    • scrapy-redis调度器从引擎接受request,将request的指纹存⼊redis的set检查是否重复,并将不重复的request push写⼊redis的 request queue。
  • 引擎请求request(Spider发出的)时,调度器从redis的request queue队列⾥里根据优先级pop 出⼀个request 返回给引擎,引擎将此request发给spider处理。

Item Pipeline

  • 引擎将(Spider返回的)爬取到的Item给Item Pipeline
    • scrapy-redis 的Item Pipeline将爬取到的 Item 存⼊redis的 items queue。
  • 修改过Item Pipeline可以很方便的根据 key 从 items queue 提取item
    • 从⽽实现items processes集群。

Base Spider

  • 不再使用scrapy原有的Spider类,重写的RedisSpider继承了Spider和RedisMixin这两个类,
    • RedisMixin是用来从redis读取url的类。
      • 当我们生成一个Spider继承RedisSpider时,调用setup_redis函数,这个函数会去连接redis数据库,然后会设置signals(信号):
        • 一个是当spider空闲时候的signal,会调用spider_idle函数,这个函数调用schedule_next_request函数,保证spider是一直活着的状态,并且抛出DontCloseSpider异常。
        • 一个是当抓到一个item时的signal,会调用item_scraped函数,这个函数会调用schedule_next_request函数,获取下一个request。

(2)Scrapy-Redis分布式策略

  • 假设有四台电脑:Windows 10、Mac OS X、Ubuntu 16.04、CentOS 7.2,
    • 任意一台电脑都可以作为 Master端 或 Slaver端,比如:
  • Master端(核心服务器) :使用 Windows 10,搭建一个Redis数据库,不负责爬取,只负责url指纹判重、Request的分配,以及数据的存储。
    • Slaver端(爬虫程序执行端) :使用 Mac OS X 、Ubuntu 16.04、CentOS 7.2,负责执行爬虫程序,运行过程中提交新的Request给Master。
  • 首先Slaver端从Master端拿任务(Request、url)进行数据抓取,Slaver抓取数据的同时,产生新任务的Request便提交给 Master 处理;
    • Master端只有一个Redis数据库,负责将未处理的Request去重和任务分配,
    • 将处理后的Request加入待爬队列,并且存储爬取的数据。
  • Scrapy-Redis默认使用的就是这种策略,我们实现起来很简单,
    • 因为任务调度等工作Scrapy-Redis都已经帮我们做好了,
    • 我们只需要继承RedisSpider、指定redis_key就行了。
  • 缺点是,Scrapy-Redis调度的任务是Request对象,里面信息量比较大(不仅包含url,还有callback函数、headers等信息),
    • 可能导致的结果就是会降低爬虫速度、而且会占用Redis大量的存储空间,
    • 所以如果要保证效率,那么就需要一定硬件水平。
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from fbs2.items import DaImgItem

from scrapy_redis.spiders import RedisCrawlSpider


class DaimgSpider(RedisCrawlSpider): # 注意这里的继承类
    name = "daimg"

    # start_urls = ['http://www.daimg.com/pic/%E7%BE%8E%E5%A5%B3%E5%9B%BE%E7%89%87-0-0-0-0-0_1.html']
    redis_key = 'daImgQueue'

    link = LinkExtractor(allow=r'pic/%E7%BE%8E%E5%A5%B3%E5%9B%BE%E7%89%87')
    rules = (
        Rule(link, callback="parse_item", follow=False, ),
    )

    def parse_item(self, response):
        li_list = response.xpath('/html/body/div[5]/ul/li')
        for li in li_list:
            title = li.xpath('./a/img/@title').extract_first()
            src = li.xpath('./a/img/@src').extract_first()
            item = DaImgItem()
            item['img_name'] = title
            item['img_url'] = src
            print("item:::", item)
            yield item

注意:如果不是全站的深度爬虫,仅需要继承RedisSpider,来自from scrapy_redis.spiders import RedisSpider

  • settings.py
# 增加了一个去重容器类的配置, 作用使用Redis的set集合来存储请求的指纹数据, 从而实现请求去重的持久化
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis组件自己的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 配置调度器是否要持久化, 也就是当爬虫结束了, 要不要清空Redis中请求队列和去重指纹的set。如果是True, 就表示要持久化存储, 就不清空数据, 否则清空数据
SCHEDULER_PERSIST = True

ITEM_PIPELINES = {
    'scrapy_redis.pipelines.RedisPipeline': 400
}


REDIS_HOST = '127.0.0.1'
REDIS_PORT = 6379
# REDIS_ENCODING = ‘utf-8’
# REDIS_PARAMS = {"password":"123456"}
  • 在 Scrapy-Redis 分布式爬虫中
    • Redis 起到了以下作用:
  1. 任务调度和分配:Scrapy-Redis 使用 Redis 数据库实现了多台机器之间的任务调度和分配,通过 Redis 中的队列来存储待爬取的 URL、请求和爬取状态等信息,从而实现多个爬虫进程或者机器之间的任务分配和调度。
  2. URL 管理:Scrapy-Redis 使用 Redis 数据库来存储待爬取的 URL 队列和已经爬取过的 URL 集合,从而避免了爬虫任务的重复执行和冲突问题。
  3. 数据存储:Scrapy-Redis 可以将爬取到的数据存储到 Redis 数据库中,从而实现分布式数据存储。这样可以避免单机存储造成的数据量过大和存储速度慢的问题。
  4. 状态共享:Scrapy-Redis 使用 Redis 数据库作为状态存储,从而实现多台机器之间的状态共享。当一个爬虫进程爬取了一个 URL 后,它可以将爬虫状态保存到 Redis 数据库中,其他进程就可以直接从 Redis 数据库中获取该状态。
  • 开启多个slaver端:
scrapy crawl daming
  • 启动Master端:
# redis-cli
# flushall
# lpush daImgQueue http://www.daimg.com/pic/%E7%BE%8E%E5%A5%B3%E5%9B%BE%E7%89%87-0-0-0-0-0_1.html

- 编码流程:
        1.创建工程
        2.cd proName
        3.创建crawlspider的爬虫文件
        4.修改一下爬虫类:
            - 导包:from scrapy_redis.spiders import RedisCrawlSpider
            - 修改当前爬虫类的父类:RedisCrawlSpider
            - allowed_domains和start_urls删除
            - 添加一个新属性:redis_key = 'xxxx'可以被共享的调度器队列的名称
        5.修改配置settings.py
            - 指定管道
                ITEM_PIPELINES = {
                        'scrapy_redis.pipelines.RedisPipeline': 400
                    }
            - 指定调度器
                # 增加了一个去重容器类的配置, 作用使用Redis的set集合来存储请求的指纹数据, 从而实现请求去重的持久化
                DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
                # 使用scrapy-redis组件自己的调度器
                SCHEDULER = "scrapy_redis.scheduler.Scheduler"
                # 配置调度器是否要持久化, 也就是当爬虫结束了, 要不要清空Redis中请求队列和去重指纹的set。
                # 如果是True, 就表示要持久化存储, 就不清空数据, 否则清空数据
                SCHEDULER_PERSIST = True
            - 指定redis数据库
                REDIS_HOST = 'redis服务的ip地址'
                REDIS_PORT = 6379
         6.配置redis数据库(redis.windows.conf)
            - 关闭默认绑定
                - 56Line:#bind 127.0.0.1
            - 关闭保护模式
                - 75line:protected-mode no
         7.启动redis服务(携带配置文件)和客户端
            - redis-server.exe redis.windows.conf
            - redis-cli
         8.执行工程
            - scrapy runspider spider.py
         9.将起始的url仍入到可以被共享的调度器的队列(sun)中
            - 在redis-cli中操作:lpush sun www.xxx.com
         10.redis:
            - xxx:items:存储的就是爬取到的数据

标签:25,25.2,Redis,redis,爬虫,scrapy,request,Scrapy
From: https://www.cnblogs.com/dream-ze/p/17335672.html

相关文章

  • scrapy命令
    scrapy常用命令:1.scrapystartprojectproject_name:创建一个新的Scrapy项目。2.scrapygenspiderspider_namedomain:创建一个新的Scrapy爬虫。3.scrapycrawlspider_name:运行指定的Scrapy爬虫。4.scrapylist:列出当前Scrapy项目中所有可用的爬虫。5.scrapysh......
  • 低功耗蓝牙MESH芯片PHY6222/PHY6252 适用于无线耳麦
    旅游带团专用无线耳麦讲解器 无线讲解器已经成为讲解场所的主要设备。该装置分为发射器和接收器。讲师会用发射器说话,听者会戴上接收器听讲话。 产品功能及适用场合:1. 可实现讲解员用正常音量讲解,配接听耳机的客人无论距离讲解员远近(200米内)可听清讲解员的讲解。讲解比较......
  • Day 24 24.1 Scrapy框架之下载中间件
    Scrapy框架之下载中间件classMyDownMiddleware(object):defprocess_request(self,request,spider):"""请求需要被下载时,经过所有下载器中间件的process_request调用:paramrequest::paramspider::return:......
  • pytest + yaml 框架 -25.参数化数据支持读取外部文件txt/csv/json/yaml
    前言v1.2.2版本开始,参数化数据支持读取外部文件,文件格式可以支持:txt/csv/json/yaml参数化的实现用例参数化的实现,我设计了2种实现方式参数化方式1:config:name:post示例fixtures:username,passwordparameters:-[test1,'123456']-[t......
  • Hackers' Crackdown UVA11825
    你需要将n个集合分成尽量多组,使得每一组里面所有集合的并集等于全集  32122022014111013120   f[S]=max(f[S],f[S-j]+1)且j是一个包含所有点的集合#include<iostream>#include<algorithm>#include<cstring>usingname......
  • Codeforces Round 625 (Div. 1, based on Technocup 2020 Final Round) A. Journey Pl
    https://codeforces.com/contest/1320/problem/AA.JourneyPlanning题目大意:给定一组数,问我们ai-aj==i-j的时候就可以把ai的值加起来,问我们可以凑到的最大总值是多少?input6107191015output26input1400000output400000input7892611122914out......
  • python爬虫scrapy框架的使用
    总结scrapystartprojectnamescrapygenspiderbaiduhttp://www.baidu.comscrapycrawlbaiduscrapy项目创建scrapystartprojectscrapy_baidu_091创建爬虫文件在spider中创建爬虫文件#scrapygenspider名称域名(不写http)scrapygenspiderbaiduhttp://www.b......
  • selenium登录cnblogs、抽屉半自动点赞、xpath的使用、打码平台使用、scrapy介绍
    昨日回顾#1beautifulsoup4使用-xml解析库,用它来解析爬回来的html内容,从中找出我们需要的内容#2遍历文档树-.的使用soup.html.body.p.a-获取属性对象.attrs.get('href')-获取文本对象.textstringstrings-子节点,父节点,兄......
  • scrapy架构介绍、scrapy解析数据、settings相关配置、持久化方案
    上节回顾#1selenium -登录cnblogs,拿到cookie,再打开cnblogs,写入cookie,它就是登录状态-半自动点赞---》selenium生成的cookie,给requests用 -selenium操作浏览器,速度慢-requests速度快-动作链-自动登录12306#2打码平台 -帮我们破......
  • 爬取的数据存mysql中、加代理,cookie,header,加入selenium、布隆过滤器、scrapy-redis实
    上节回顾#1scrapy架构 -爬虫:写的一个个类-引擎: -调度器:排队,去重-下载器-pipline-下载中间件-爬虫中间件#2命令 -scrapystartproject项目名-scrapygensipder爬虫名网址-scrapycrawl爬虫名字-run.py#......