目录

1. scrapy-redis是什么?

2. scrapy-redis工作原理

3.分布式架构

4. scrapy-redis的源码分析

5. 部署scrapy-redis

6. scrapy-redis的基本使用

6.1 redis数据库基本表项

6.2 在scrapy项目的基础进行更改

7. redis数据转存入mysql数据库


课程推荐:day07_01.scrapy-redis官方案例演示_recv_哔哩哔哩_bilibili

1. scrapy-redis是什么?

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

2. scrapy-redis工作原理

与scrapy框架不同的是,scrapy-redis框架中request链接不再交付于调度器(Scheduler)中url队列,而是保存在redis数据库中,再由过滤器进行过滤,符合要求的请求链接再交付于调度器(Scheduler),此外redis数据还可以存储到本地数据库(item processes)。其余流程与scrapy流程基本相同。

(1) 引擎(Scrapy Engine)向爬虫(Spiders)请求第一个要爬取的URL。

(2) 引擎从爬虫中获取到第一个要爬取的URL,封装成请求(Request)并交给调度器(Scheduler)。

(3) 调度器访问Redis数据库对请求进行判重,如果不重复,就把这个请求添加到Redis中。

(4) 当调度条件满足时,调度器会从Redis中取出Request,交给引擎,引擎将这个Request通过下载中间件转发给下载器。

(5) 一旦页面下载完毕,下载器(Downloader)生成一个该页面的响应(Response),并将其通过下载中间件发送给引擎。

(6) 引擎从下载器中接收到响应,并通过爬虫中间件(Spider Middlewares)发送给爬虫处理。

(7) Spider处理Response,并返回爬取到的Item及新的Request给引擎。

(8) 引擎将爬取到的Item通过Item Pipeline给Redis数据库,将Request给调度器。从(2) 开始重复,直到调度器中没有更多的Request为止。

3.分布式架构

这种框架,主从式框架主要由一台url提供主机(master)向资源爬取主机(slave)提供url,由资源爬取主机依照url爬取相应的资源。这也是scrapy-redis的分布式模式。

4. scrapy-redis的源码分析

(1) 源码地址

GitHub - rmax/scrapy-redis: Redis-based components for Scrapy.

(2) 源码案例详解

example-project为源码给予的案例,我们使用scrapy-redis以此为例。我们仅需分析example-project下的文件即可。与scrapy相同,scrapy-redis主要文件也是由items文件、pipelines文件、setting文件和爬虫文件组成。

items文件: 与scrapy一样,为爬虫文件的数据结构

from scrapy.item import Item, Field
from scrapy.loader import ItemLoader
from scrapy.loader.processors import MapCompose, TakeFirst, Join# 与scrapy一样,为爬虫文件的数据结构
class ExampleItem(Item):name = Field()description = Field()link = Field()crawled = Field()spider = Field()url = Field()# 与scrapy中的ItemLoader作用一致
class ExampleLoader(ItemLoader):default_item_class = ExampleItemdefault_input_processor = MapCompose(lambda s: s.strip())default_output_processor = TakeFirst()description_out = Join()

pipelines文件: 没有特殊需要,pipelines文件不再需要写任何的语句,return会自动将item数据传入数据库。

from datetime import datetimeclass ExamplePipeline(object):def process_item(self, item, spider):# 时间戳item["crawled"] = datetime.utcnow()# 爬虫名,分布式爬虫有多个爬虫,规定爬虫名易于区分item["spider"] = spider.namereturn item

setting文件: scrapy_redis所必须的设置

SPIDER_MODULES = ['example.spiders']
NEWSPIDER_MODULE = 'example.spiders'USER_AGENT = 'scrapy-redis (+https://github.com/rolando/scrapy-redis)'# 去重类,使用scrapy_redis中的去重类
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 调度器,使用scrapy_redis中的调度器组件
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 是否允许暂停,redis中请求记录不丢失
SCHEDULER_PERSIST = True# 默认的scrapy-redis请求集合
# SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"# 队列形式,请求url会先进先出
# SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"# 栈形式,请求url会先进后出
# SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"# 'scrapy_redis.pipelines.RedisPipeline' 支持存储到redis数据库中,必须开启
ITEM_PIPELINES = {'example.pipelines.ExamplePipeline': 300,# redis管道,必须设置,不然数据无法传入数据库'scrapy_redis.pipelines.RedisPipeline': 400,
}# 日志等级
LOG_LEVEL = 'DEBUG'# 下载延迟
DOWNLOAD_DELAY = 1# redis配置
# 指定数据库ip
REDIS_HOST = "127.0.0.1"
# 指定数据库端口号
REDIS_PORT = 6379

爬虫文件(三个不同类型的样例):

domz.py:  非分布式,有链接提取器

# domz.pyfrom scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule# 非分布式,有链接提取器
# 使用的是CrawlSpider链接提取器
class DmozSpider(CrawlSpider):"""Follow categories and extract links."""name = 'dmoz'allowed_domains = ['dmoz-odp.org']start_urls = ['http://www.dmoz-odp.org/']# 链接提取器的提取规则rules = [Rule(LinkExtractor(restrict_css=('.top-cat', '.sub-cat', '.cat-item')), callback='parse_directory', follow=True),]def parse_directory(self, response):for div in response.css('.title-and-desc'):yield {'name': div.css('.site-title::text').extract_first(),'description': div.css('.site-descr::text').extract_first().strip(),'link': div.css('a::attr(href)').extract_first(),}

mycrawler_redis.py:  分布式,有链接提取器

# mycrawler_redis.pyfrom scrapy.spiders import Rule
from scrapy.linkextractors import LinkExtractorfrom scrapy_redis.spiders import RedisCrawlSpiderclass MyCrawler(RedisCrawlSpider):name = 'mycrawler_redis'# 分布式爬虫开启指令,第一个要爬前的url,与数据库中格式需一致redis_key = 'mycrawler:start_urls'# 提取链接规则rules = (# follow all linksRule(LinkExtractor(), callback='parse_page', follow=True),)# 动态域名,与allowed_domains作用一致,规定可爬url域,可设置多个可爬域# __init__方法必须按规定写,使用时只需修改super()里的类名参数即可def __init__(self, *args, **kwargs):domain = kwargs.pop('domain', '')self.allowed_domains = filter(None, domain.split(','))# 修改这里的类名为当前类名super(MyCrawler, self).__init__(*args, **kwargs)def parse_page(self, response):return {'name': response.css('title::text').extract_first(),'url': response.url,}

myspider_redis.py:  分布式,无链接提取器

from scrapy_redis.spiders import RedisSpider# 没有链接提取器
class MySpider(RedisSpider):"""Spider that reads urls from redis queue (myspider:start_urls)."""name = 'myspider_redis'# 分布式爬虫开启指令,第一个要爬前的url,与数据库中格式需一致redis_key = 'myspider:start_urls'def __init__(self, *args, **kwargs):# Dynamically define the allowed domains list.# 弹出域名domain = kwargs.pop('domain', '')# 准许访问的域名self.allowed_domains = filter(None, domain.split(','))super(MySpider, self).__init__(*args, **kwargs)def parse(self, response):return {'name': response.css('title::text').extract_first(),'url': response.url,}

5. 部署scrapy-redis

(1) slave端(2台linux系统)

软件配置:python 3 + pip + scrapy + scrapy-redis

安装linux系统:https://shuijinglan.blog.csdn.net/article/details/105604065

配置yum网络源:https://pokes.blog.csdn.net/article/details/124627065

安装python 3(版本要9.9):Linux系统安装Python3环境(超详细) - 知乎

安装scrapy-redis:

pip install scrapy-redis -i https://pypi.douban.com/simple

(2)master端(windows系统)
软件配置: redis + scrapy + scrapy-redis

redis下载:

https://github.com/tporadowski/redis/releases/download/v5.0.14.1/Redis-x64-5.0.14.1.zip

redis.windows.conf配置:

1. 在redis.windows.conf文件中,禁用bind 127.0.0.1

2. 在redis.windows.conf文件中,将daemonize no改为yes

启动redis:先运行redis-server再运行redis-cli

永久启动方法:

Redis下载和安装(Windows系统)

6. scrapy-redis的基本使用

6.1 redis数据库基本表项

爬虫名:dupelines        # 已过滤的链接,已爬过的链接不再爬取

爬虫名:items               # 爬取的数据,对应items数据项

爬虫名:requests          # 请求链接,要爬的url

爬虫名:start_urls         # 分布式爬虫开启指令,第一个要爬的url,与数据库中格式需一致

6.2 在scrapy项目的基础进行更改

(1) 在settings中添加配置信息

# scrapy-redis
USER_AGENT = 'scrapy-redis (+https://github.com/rolando/scrapy-redis)'# 过滤配置
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 调度引擎
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 是否允许暂停
SCHEDULER_PERSIST = True# SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
# SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"
# SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"
ITEM_PIPELINES = {'DistrubutedSpider.pipelines.DistrubutedSpiderPipeline': 300,# redis管道,item数据直接入库,必须添加'scrapy_redis.pipelines.RedisPipeline': 400,
}

(2)更改爬虫文件

第一种:带有链接提取器

# 读书网案例
from scrapy.spiders import Rule
from scrapy.linkextractors import LinkExtractor
from scrapy_redis.spiders import RedisCrawlSpider# 带有链接提取器
class slaveSpider(RedisCrawlSpider):name = 'slave'# 起始连接,放在数据库中第一批要爬取得链接,Requests从这批链接的页面中获取redis_key = 'slave:start_urls'# 提取链接规则rules = (Rule(LinkExtractor(allow=r'/book/1188_\d+\.html'), callback='parse_item', follow=False),)# 类似allow_domain,准许多个域名域# 动态域,__init__方法必须按规定写,使用时只需修改super()里的类名参数即可def __init__(self, *args, **kwargs):# Dynamically define the allowed domains list.domain = kwargs.pop('domain', '')self.allowed_domains = filter(None, domain.split(','))# 修改这里的类名为当前类名super(Master02Spider, self).__init__(*args, **kwargs)def parse_item(self,response):# xpathimg_list = response.xpath('//ul/li/div[@class="book-info"]/div/a')for i in img_list:src = i.xpath('./img/@data-original').extract_first()name = i.xpath('./img/@alt').extract_first()# itemyield {'src': src, 'name': name}

(3)运行程序

在2台linux虚拟机中分别部署爬虫文件,运行,并在redis输入start_urls  。

分布式爬虫文件启动命令:

scrapy runspider 爬虫文件名.py

例:scrapy runspider slave.py

进入Redis数据库输入:

lpush 爬虫文件名:start_urls   要爬的第一条链接

例:lpush slave:start_urls https://www.dushu.com/book/1188_01.html

7. redis数据转存入mysql数据库

(1)安装MySQLdb (python版本为3.7)

pip install mysqlclient==1.3.14

(2)redis数据转存入mysql数据库

# !/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
import MySQLdb
import jsondef process_item():while(True):# 1.创建redis数据库链接redis_con = redis.Redis(host="127.0.0.1",port=6379,db=0)# 2.创建mysql数据库链接mysql_con = MySQLdb.connect(host="127.0.0.1",port=3306,user="root",password="123456",db="spider01", charset="utf8")# 3.将数据从redis数据库中pop出来source,data = redis_con.blpop("demo02:items")# 4.json转换字符串item = json.loads(data)## mysql# 5.创建mysql的游标对象,执行sql语句cursor = mysql_con.cursor()# 6.sql语句sql = 'insert into book(name,src) values ("{}","{}")'.format(item['name'],item['src'])# 7.执行sql,%等同于格式化语句.format()cursor.execute(sql)# 8.提交mysql_con.commit()# 9.结束cursor.close()if __name__ == '__main__':process_item()

scrapy-redis分布式爬虫学习记录相关推荐

  1. 第063讲: 论一只爬虫的自我修养11:Scrapy框架之初窥门径 | 学习记录(小甲鱼零基础入门学习Python)

    上一节课我们好不容易装好了 Scrapy,今天我们就来学习如何用好它,有些同学可能会有些疑惑,既然我们懂得了Python编写爬虫的技巧,那要这个所谓的爬虫框架又有什么用呢?其实啊,你懂得Python写 ...

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

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

  3. Scrapy 框架 分布式 爬虫

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

  4. Python-玩转数据-scrapy简单分布式爬虫

    一.说明 虽然scrapy能做的事情很多,但是要做到大规模的分布式应用则捉襟见肘.有能人改变了scrapy的队列调度,将起始的网址从start_urls里分离出来,改为从redis读取,多个客户端可以 ...

  5. 解析python网络爬虫pdf 黑马程序员_正版 解析Python网络爬虫 核心技术 Scrapy框架 分布式爬虫 黑马程序员 Python应用编程丛书 中国铁道出版社...

    商品参数 书名:Python应用编程丛书:解析Python网络爬虫:核心技术.Scrapy框架.分布式爬虫 定价:52.00元 作者:[中国]黑马程序员 出版社:中国铁道出版社 出版日期:2018-0 ...

  6. 基于jupyter notebook的简单爬虫学习记录

    目录 前言 一.基础理解 二.前期准备 三.爬虫实操[入门] 3.1.引入库 3.2.请求网页 3.3.解析网页 3.3.1.网页解读 3.3.2.熟悉部分BeautifulSoup语法规则 3.4. ...

  7. 【Python3.6爬虫学习记录】(十五)Scrapy爬虫框架的应用及马赛克拼图生成

    目录 目录 前言 1.Scrapy框架应用 1.1.Scrapy准备 1.2.创建项目及配置 1.3.网页分析及代码实现 1.3.1 items.py 中定义存储的数据 1.3.2 spiders文件 ...

  8. Scrapy + Redis 分布式爬取58同城北京全站二手房数据

    Hello,我是 Alex 007,为啥是007呢?因为叫 Alex 的人太多了,再加上每天007的生活,Alex 007就诞生了. 经过一个星期的学习,爬虫这个章节算是告一段落了,记录一下作业. 文 ...

  9. 基于scrapy的分布式爬虫抓取新浪微博个人信息和微博内容存入MySQL

    为了学习机器学习深度学习和文本挖掘方面的知识,需要获取一定的数据,新浪微博的大量数据可以作为此次研究历程的对象 一.环境准备 python 2.7 scrapy框架的部署(可以查看上一篇博客的简要操作 ...

最新文章

  1. Unity创建2D动作RPG游戏 Create Action 2D RPG Game in Unity
  2. win7冒险岛java,win7玩冒险岛不兼容怎么办?解决win7玩冒险岛不兼容的方法
  3. http请求curl
  4. 让对话框不显示边框_微信消息“无边框”模式搭配这款壁纸,简直绝了
  5. android自动化框架简要剖析(一):运行原理+基本框架
  6. NOIP201202寻宝
  7. string int 相互转换
  8. 软工作业 评价输入法
  9. 遵循PSR-4的自动加载
  10. 计算机视觉的技术与应用
  11. 2021.12.18-参加青少年人工智能编程水平(YCL)测试5级C++(良好通过)
  12. 怎么设置计算机桌面一键关机,图文详解如何设置电脑定时开关机
  13. 浅析嵌入式开发中的RAM和ROM
  14. JMeter5.0的脚本录制
  15. php 获取agent,PHP解析HTTP_USER_AGENT 获取客户端浏览器以及版本号 | 八戒哥技术博客...
  16. 12、PIC系列-I2C通讯模块
  17. 【离散数学】二元关系
  18. 用C语言写一个计算器
  19. H264码流RTP封装方式详解
  20. 深入浅出Pandas:利用Python进行数据处理与分析 (李庆辉) 读书笔记

热门文章

  1. 讲解高防服务器抵御CC攻击的相关配置
  2. B站疯传|200个Java程序员必备词汇
  3. 数字ic设计——AMBA总线(1)AMBA总线介绍
  4. 项目管理专业人员能力评价(CSPM)含金量高吗?都考什么?
  5. python新手如何写代码_Python新人指南[2]
  6. KBP310-ASEMI插件整流桥3A 1000V
  7. 运维工程师的职责和必备技能
  8. 149 混合推荐系统案例(功能分析)
  9. SciTE如何修改背景色
  10. Android 7.0中的多窗口-分屏-实现解析