分布式的概念和作用
- 分布式:将一个业务分拆多个子任务,将任务分配运行在不同地方的电脑上
- 作用:提高安全性和效率
- 使用场景:scrapy框架已经可以提供异步数据获取,如果网站的数据非常庞大, 我们就需要使用分布式来更快的爬取数据
分布式爬虫
- 默认情况下,我们使用scrapy框架进行爬虫时使用的是单机爬虫,就是说它只能在一台电脑上运行,因为爬虫调度器当中的队列queue去重和set集合都只能在本机上创建的,其他电脑无法访问另外一台电脑上的内存和内容。
- 分布式爬虫实现了多台电脑使用一个共同的爬虫程序,它可以同时将爬虫任务部署到多台电脑上运行,这样可以提高爬虫速度,实现分布式爬虫。
特点和结构
scrapy_redis是一个基于Redis的Scrapy组件,用于scrapy项目的分布式部署和开发。
特点: 分布式爬取。可以启动多个spider对象,互相之间共享有一个redis的request队列。最适合多个域名的广泛内容的提取。分布式数据处理是爬取到的item数据被推送到redis中,这意味着可以启动尽可能多的item来处理程序。
安装和使用
安装
一般通过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"
复制三个一样的,就可以对其进行分布式爬取