Scrapy_redis分布式

154 阅读6分钟

分布式的概念和作用

  • 分布式:将一个业务分拆多个子任务,将任务分配运行在不同地方的电脑上
  • 作用:提高安全性和效率
  • 使用场景:scrapy框架已经可以提供异步数据获取,如果网站的数据非常庞大, 我们就需要使用分布式来更快的爬取数据

分布式爬虫

  • 默认情况下,我们使用scrapy框架进行爬虫时使用的是单机爬虫,就是说它只能在一台电脑上运行,因为爬虫调度器当中的队列queue去重和set集合都只能在本机上创建的,其他电脑无法访问另外一台电脑上的内存和内容。
  • 分布式爬虫实现了多台电脑使用一个共同的爬虫程序,它可以同时将爬虫任务部署到多台电脑上运行,这样可以提高爬虫速度,实现分布式爬虫。

特点和结构

scrapy_redis是一个基于Redis的Scrapy组件,用于scrapy项目的分布式部署和开发。

特点: 分布式爬取。可以启动多个spider对象,互相之间共享有一个redis的request队列。最适合多个域名的广泛内容的提取。分布式数据处理是爬取到的item数据被推送到redis中,这意味着可以启动尽可能多的item来处理程序。

image.png

安装和使用

安装

一般通过pip安装Scrapy_redis,Scrapy_redis是基于scrapy使用的:

pip install Scrapy_redis

使用

Scrapy-redis的使用比较简单,几乎可以不改变原本的scrapy项目的代码,只用做少量的设置

spider文件

爬虫文件需要修改的就算基础的类,使用Scrapy_redis中的RedisSpider,启动爬虫也不再使用start_urls,而是使用redis_key获取其实连接

# 使用RedisSpider类,具有和redis数据库交互的爬虫类
from scrapy_redis.spiders import RedisSpider  #或者from scrapy_redis import spiders


class ChinazSpider(RedisSpider): #或者class Bdspider(spiders.RedisSpider):
    # 初始队列统一从redis中读取,不再需要start_urls 
    # start_urls =[f'https://movie.douban.com/j/chart/top_list'] 
    redis_key = 'db:start_urls' 
    # 冒号前面默认为爬虫名称 
    # redis的key,用于从redis数据库中获取起始的url

settings文件

通过设置项覆盖原本的配置,其中主要覆盖的调度器,过滤器和管道

# 使用scrapy_redis的调度器,在redis里进行请求分配 必须 
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

# 确保所有spider通过redis共享相同的重复过滤。 必须 
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

# 可选 不清除redis数据库中去重集合,和任务数据队列 
SCHEDULER_PERSIST = True

# REDIS连接参数 主机和端口 必须 
REDIS_HOST = '127.0.0.1' # 写自己电脑的ip地址
REDIS_PORT = 6379 # 默认不变

#公共管道 
#如果你希望数据后期统一处理,则可以增加’scrapy_redis.pipelines.RedisPipeline’: 300 
#ITEM_PIPELINES = { 
    #'scrapy_redis.pipelines.RedisPipeline':300, 
#开启该管道,会把数据都存入redis数据库中 
#}
#需要对数据进行存储到redis中,就可以打开这个通道

启动分布式

# 格式 lpush key:value url
# 启动示例
lpush bd:start_urls '{"url": "https://example.com"}'
python.exe -m pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple

小结

1、scrapy_redis的含义和能够实现的功能

scrapy是框架
scrapy_redis是scrapy的组件
scrapy_redis能够实现断点续爬和分布式爬虫

2、scrapy_redis流程和实现原理

在scrapy框架流程的基础上,把存储request对象放到了redis的有序集合中,利用该有序集合实现请求队列
并对request对象生成指纹对象,也存储到同一redis的集合中,利用request指纹避免发送重复的请求

3、request对象进入队列的条件

request的指纹不在集合中
request的dont_filter为True,即不过滤

4、request指纹的实现

请求方法
排序后的请求地址
排序并处理过的请求体或空字符串
用hashlib.sha1()对以上内容进行加密

5、scarpy_redis实现增量式爬虫、布式爬虫

    1.  对setting进行如下设置

        a.  DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
        b.  SCHEDULER = "scrapy_redis.scheduler.Scheduler"
        c.  SCHEDULER_PERSIST = True

    2.  爬虫文件中的爬虫类继承RedisSpider类

    3.  爬虫类中redis_key替代了start_urls

    4.  启动方式不同

        a.  通过`scrapy crawl spider`启动爬虫后,向redis_key放入一个或多个起始url(lpush或rpush都可以),才能够让scrapy_redis爬虫运行

    5.  除了以上差异点以外,scrapy_redis爬虫和scrapy爬虫的使用方法都是一样的

练习:百度

bd.py

import scrapy
import re  #正则表达式
from scrapy_redis.spiders import RedisSpider

class BdSpider(RedisSpider):
    name = "bd"
    allowed_domains = ["www.baidu.com"]
    # start_urls = ["https://www.baidu.com"]
    # lpush bd:start_urls '{"url":"https://www.baidu.com"}'
    redis_key = 'bd:start_urls'

    def parse(self, response,*_):
        print(response.text)
        card_title=re.findall('"card_title": "(.*?)","',response.text)
        print(card_title)
        yield {'card_title':card_title}

        pass

settings.py

# Scrapy settings for baidu project
#
# For simplicity, this file contains only settings considered important or
# commonly used. You can find more settings consulting the documentation:
#
#     https://docs.scrapy.org/en/latest/topics/settings.html
#     https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#     https://docs.scrapy.org/en/latest/topics/spider-middleware.html

BOT_NAME = "baidu"

SPIDER_MODULES = ["baidu.spiders"]
NEWSPIDER_MODULE = "baidu.spiders"


# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"

# Obey robots.txt rules
ROBOTSTXT_OBEY = False

# 使用scrapy_redis的调度器,在redis里进行请求分配 必须
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

# 确保所有spider通过redis共享相同的重复过滤。 必须
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

# 可选 不清除redis数据库中去重集合,和任务数据队列
SCHEDULER_PERSIST = True

# REDIS连接参数 主机和端口 必须
REDIS_HOST = '127.0.0.1' # 写自己电脑的ip地址
REDIS_PORT = 6379 # 默认不变

#公共管道
#如果你希望数据后期统一处理,则可以增加’scrapy_redis.pipelines.RedisPipeline’: 300
ITEM_PIPELINES = {
    'scrapy_redis.pipelines.RedisPipeline':300,
#开启该管道,会把数据都存入redis数据库中
}


# Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32

# Configure a delay for requests for the same website (default: 0)
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
#DOWNLOAD_DELAY = 3
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16

# Disable cookies (enabled by default)
#COOKIES_ENABLED = False

# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False

# Override the default request headers:
#DEFAULT_REQUEST_HEADERS = {
#    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
#    "Accept-Language": "en",
#}

# Enable or disable spider middlewares
# See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES = {
#    "baidu.middlewares.BaiduSpiderMiddleware": 543,
#}

# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
#    "baidu.middlewares.BaiduDownloaderMiddleware": 543,
#}

# Enable or disable extensions
# See https://docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS = {
#    "scrapy.extensions.telnet.TelnetConsole": None,
#}

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
#ITEM_PIPELINES = {
#    "baidu.pipelines.BaiduPipeline": 300,
#}

# Enable and configure the AutoThrottle extension (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED = True
# The initial download delay
#AUTOTHROTTLE_START_DELAY = 5
# The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY = 60
# The average number of requests Scrapy should be sending in parallel to
# each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
# Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG = False

# Enable and configure HTTP caching (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = "httpcache"
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = "scrapy.extensions.httpcache.FilesystemCacheStorage"

# Set settings whose default value is deprecated to a future-proof value
REQUEST_FINGERPRINTER_IMPLEMENTATION = "2.7"
TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
FEED_EXPORT_ENCODING = "utf-8"

image.png

复制三个一样的,就可以对其进行分布式爬取