Scrapy-Redis代码实战

Scrapy 是一个通用的爬虫框架,但是不支持分布式,Scrapy-redis是为了更方便地实现Scrapy分布式爬取,而提供了一些以redis为基础的组件(仅有组件)。

scrapy-redis在scrapy的架构上增加了redis,基于redis的特性拓展了如下四种组件:

  • Scheduler
  • Duplication Filter
  • Item Pipeline
  • Base Spider

scrapy-redis架构

Scheduler

Scrapy原本的queue是不支持多个spider共享一个队列的,scrapy-redis通过将queue改为redis实现队列共享。

Duplication Filter

Scrapy中通过Python中的集合实现request指纹去重,在scrapy-redis中去重是由Duplication Filter组件来实现的,它通过redis的set不重复的特性,巧妙的实现了DuplicationFilter去重。

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

安装Scrapy-Redis

python3.6 -m pip install scrapy-redis

项目练习

首先修改配置文件

BOT_NAME = 'cnblogs'
SPIDER_MODULES = ['cnblogs.spiders']
NEWSPIDER_MODULE = 'cnblogs.spiders'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False # Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32 # See also autothrottle settings and docs
#DOWNLOAD_DELAY = 3
DOWNLOAD_DELAY = 2 # 等待2s
MY_USER_AGENT = ["Mozilla/5.0+(Windows+NT+6.2;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/45.0.2454.101+Safari/537.36",
"Mozilla/5.0+(Windows+NT+5.1)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/28.0.1500.95+Safari/537.36+SE+2.X+MetaSr+1.0",
"Mozilla/5.0+(Windows+NT+6.1;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/50.0.2657.3+Safari/537.36"]
# Enable or disable downloader middlewares
# See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html
DOWNLOADER_MIDDLEWARES = {
'cnblogs.middlewares.UserAgentMiddleware': 543,
}
LOG_LEVEL = "ERROR" ITEM_PIPELINES = {
'cnblogs.pipelines.MongoPipeline': 300,
}
#将结果保存到Mongo数据库
MONGO_HOST = "127.0.0.1" # 主机IP
MONGO_PORT = 27017 # 端口号
MONGO_DB = "spider_data" # 库名
MONGO_COLL = "cnblogs_title" # collection名 #需要将调度器的类和去重的类替换为 Scrapy-Redis 提供的类
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
REDIS_HOST = '127.0.0.1'
REDIS_PORT = 7001 #Redis集群中其中一个节点的端口 #配置持久化
#Scrapy-Redis 默认会在爬取全部完成后清空爬取队列和去重指纹集合。
#SCHEDULER_PERSIST = True #设置重爬
#SCHEDULER_FLUSH_ON_START = True

代码要改的地方有两处:

第一处是继承的RedisSpider

第二处就是start_urls改为了redis_key。

# -*- coding: utf-8 -*-
import scrapy
import datetime
from scrapy_redis.spiders import RedisSpider
class CnblogSpider(RedisSpider):
name = 'cnblog'
redis_key = "myspider:start_urls"
#start_urls = [f'https://www.cnblogs.com/c-x-a/default.html?page={i}' for i in range(1,2)] def parse(self, response):
main_info_list_node = response.xpath('//div[@class="forFlow"]')
content_list_node = main_info_list_node.xpath(".//a[@class='postTitle2']/text()").extract()
for item in content_list_node:
url = response.url
title=item
crawl_date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
item = {}
item['url'] = url
item['title'] = title.strip() if title else title
item['crawl_date'] = crawl_date
yield item

因为Scrapy-Redis是以Redis为队列进行消息共享的,所以我们的任务需要提前插入到数据库,它的key就叫我们指定的"myspider:start_urls"。

在之前创建好的redis集群中插入任务,首先使用集群的模式连接数据库

redis-cli -c -p 7000 #我的redis集群的一个Master节点端口

执行下面的语句插入任务

lpush myspider:start_urls https://www.cnblogs.com/c-x-a/default.html?page=1
lpush myspider:start_urls https://www.cnblogs.com/c-x-a/default.html?page=2

然后查看

lrange myspider:start_urls 0 10

看到我们的任务,好了任务插入成功了。

接下来就是运行代码了,运行完代码之后,去查看三处。

第一处,查看redis的任务发现任务已经没有了

(empty list or set)

第二处,查看mongo数据库,发现我们成功保存了结果。

第三处,你会发现的你爬虫程序并没有结束,这个其实是正常的,因为我们使用了scrapy-redis之后,爬虫程序会一直取redis中的任务,如果没有任务了就等待,如果在redis插入了新的任务他就会继续进行爬虫程序,之后又进入等待任务的状态。

关注公众号:Python学习开发,后台回复:redis即可获取源码。

参考资料

https://segmentfault.com/a/1190000014333162?utm_source=channel-hottest

scrapy-redis分布式爬虫实战的更多相关文章

  1. scrapy进行分布式爬虫

    今天,参照崔庆才老师的爬虫实战课程,实践了一下分布式爬虫,并没有之前想象的那么神秘,其实非常的简单,相信你看过这篇文章后,不出一小时,便可以动手完成一个分布式爬虫! 1.分布式爬虫原理 首先我们来看一 ...

  2. Scrapy 框架 分布式 爬虫

    分布式 爬虫 scrapy-redis 实现 原生scrapy 无法实现 分布式 调度器和管道无法被分布式机群共享 环境安装 - pip install scrapy_redis 导包:from sc ...

  3. scrapy简单分布式爬虫

    经过一段时间的折腾,终于整明白scrapy分布式是怎么个搞法了,特记录一点心得. 虽然scrapy能做的事情很多,但是要做到大规模的分布式应用则捉襟见肘.有能人改变了scrapy的队列调度,将起始的网 ...

  4. 16 Scrapy之分布式爬虫

    redis分布式部署 1.scrapy框架是否可以自己实现分布式? - 不可以.原因有二. 其一:因为多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器无法分配start_urls ...

  5. scrapy补充-分布式爬虫

    spiders 介绍:在项目中是创建爬虫程序的py文件 #1.Spiders是由一系列类(定义了一个网址或一组网址将被爬取)组成,具体包括如何执行爬取任务并且如何从页面中提取结构化的数据. #2.换句 ...

  6. 【Python3爬虫】爬取美女图新姿势--Redis分布式爬虫初体验

    一.写在前面 之前写的爬虫都是单机爬虫,还没有尝试过分布式爬虫,这次就是一个分布式爬虫的初体验.所谓分布式爬虫,就是要用多台电脑同时爬取数据,相比于单机爬虫,分布式爬虫的爬取速度更快,也能更好地应对I ...

  7. 【Python3爬虫】学习分布式爬虫第一步--Redis分布式爬虫初体验

    一.写在前面 之前写的爬虫都是单机爬虫,还没有尝试过分布式爬虫,这次就是一个分布式爬虫的初体验.所谓分布式爬虫,就是要用多台电脑同时爬取数据,相比于单机爬虫,分布式爬虫的爬取速度更快,也能更好地应对I ...

  8. 从Redis分布式缓存实战入手到底层原理分析、面面俱到覆盖大厂面试考点

    概述 官方说明 Redis官网 https://redis.io/ 最新版本6.2.6 Redis中文官网 http://www.redis.cn/ 不过中文官网的同步更新维护相对要滞后不少时间,但对 ...

  9. Redis分布式锁实战

    什么是分布式锁 在单机部署的情况下,要想保证特定业务在顺序执行,通过JDK提供的synchronized关键字.Semaphore.ReentrantLock,或者我们也可以基于AQS定制化锁.单机部 ...

  10. 爬虫--scrapy+redis分布式爬取58同城北京全站租房数据

    作业需求: 1.基于Spider或者CrawlSpider进行租房信息的爬取 2.本机搭建分布式环境对租房信息进行爬取 3.搭建多台机器的分布式环境,多台机器同时进行租房数据爬取 建议:用Pychar ...

随机推荐

  1. C#反射与特性(二):探究反射

    目录 1,反射的使用概述 2,获取 Type 在上一章中,我们探究了 C# 引入程序集的各种方法,这一章节笔者将探究 C# 中使用反射的各种操作和代码实践. 1,反射的使用概述 1.1 什么是反射 & ...

  2. 「UVA1328」Period 解题报告

    English题面 题意: 给你一个长度为n的字符串,依次取字符串前i个(前缀),如果前缀由k(k>0)个相同真子串构成,那么输出i和k 直到n为0结束,每组数据后要有一行空白 思路: KMP+ ...

  3. ThreadLocal解析:父线程的本地变量不能传递到子线程详解

    众所周知,ThreadLocal类是java提供线程本地变量的工具类.但父线程的本地变量却不能被子线程使用,代码如下: public static void main(String[] args) { ...

  4. 2016女生专场 ABCDEF题解 其他待补...

    GHIJ待补... A.HUD5702:Solving Order Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/3276 ...

  5. BitSet 的使用

    BitSet 的简单介绍 BitSet,即位图,是位操作的对象,值只有 0 或 1(即 false 或 true). Java 的 BitSet 内部维护着一个 long 数组,默认初始化时数组的长度 ...

  6. hexo博客零基础搭建系列(一)

    文章目录 其他搭建 1.简介 2.安装Node和Git 3.安装Hexo 4.Hexo的目录结构 5.我的版本 其他搭建 不好意思,下面的链接都是CSDN的链接,如果要在博客园看,请点我的分类查看.因 ...

  7. 【linux学习笔记】

    网上看一个两小时突击linux的教程,就想补充一下linux的知识.想着一天抽出俩小时立马就能学完呢,结果乱七八糟的事情拖了四五天,实际完成某项任务的时间超出预期完成任务的两部不止.好了," ...

  8. 让vue-router渲染为指定的标签

    <router-link :to="{name:'cart'}" tag="li"> cart </router-link> 在rout ...

  9. C#调用7z实现文件的压缩与解压

    1.关于7z 首先在这里先介绍一下7z压缩软件,7z是一种主流的 压缩格式,它拥有极高的压缩比.在计算机科学中,7z是一种可以使用多种压缩算法进行数据压缩的档案格式.主要有以下特点: 来源且模块化的组 ...

  10. “土法炮制”之 OOM框架

    一.什么是OOM框架? OOM 的全拼是 Object-Object-Map,意思是对象与对象之间的映射,OOM框架要解决的问题就是对象与对象之间数据的自动映射. 举一个具体的例子:用过MVC模式开发 ...