scrapy-redis分布式爬虫学习记录

news2024/11/30 6:56:22

目录

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 = ExampleItem
    default_input_processor = MapCompose(lambda s: s.strip())
    default_output_processor = TakeFirst()
    description_out = Join()

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

from datetime import datetime


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

        return 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.py

from 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.py

from scrapy.spiders import Rule
from scrapy.linkextractors import LinkExtractor

from scrapy_redis.spiders import RedisCrawlSpider


class MyCrawler(RedisCrawlSpider):
    name = 'mycrawler_redis'
    # 分布式爬虫开启指令,第一个要爬前的url,与数据库中格式需一致
    redis_key = 'mycrawler:start_urls'

    # 提取链接规则
    rules = (
        # follow all links
        Rule(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):
        # xpath
        img_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()
            # item
            yield {'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 json

def 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()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/363642.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大学生成人插画培训机构盘点

成人插画培训机构哪个好,成人学插画如何选培训班?给大家梳理了国内较好的插画培训机构排名,各有优势和特色,供大家参考! 一:国内成人插画培训机构排名 1、轻微课(五颗星) 主打课程有…

Head First设计模式---3.装饰者模式

3.1装饰者模式 亦称: 装饰者模式、装饰器模式、Wrapper、Decorator 装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。 举个例子:天气很冷,我们一件一件穿衣服&#xff0c…

学习Flask之五、数据库

学习Flask之五、数据库 数据库有组织的存贮应用数据。根据需要应用发布查询追踪特定部分。网络应用最常用的数据库是基于关系模式的,也称为SQL数据库,引用结构化查询语句。但是近年来,面向文档和键值的数据库,非正式的统称为NoSQ…

乐友商城学习笔记(一)

SpringCloud 什么是SpringCloud 在SpringBoot基础上构建的微服务框架固定步骤 1.引入组件的启动器2.覆盖默认配置3.在引导类上添加相应的注解 eureka 注册中心,服务的注册与发现服务端 1.引入服务器启动器:eureka-server2.添加了配置 spring.applicati…

【Git】使用Git上传项目到远程仓库Gitee码云步骤详解

电脑里存放了很多项目,有的备份,有的没备份,如果不仔细分类管理的话,时间一长,到时看到那就会觉得非常杂乱,很难整理,这里有一个叫源代码托管,用过它的都知道,方便管理和…

如何下载阅读Spring源码-全过程详解

这篇文章记录了下载spring源码和在IDEA中打开运行的全过程,并且记录了过程中遇到的问题和解决方案,适合需要学习spring源码的同学阅读。 1.spring源码下载地址 通过Git下载spring-framework项目源码: git clone https://github.com/spring…

Document-Level event Extraction via human-like reading process 论文解读

Document-Level event Extraction via human-like reading process 论文:2202.03092v1.pdf (arxiv.org) 代码:无 期刊/会议:ICASSP 2022 摘要 文档级事件抽取(DEE)特别困难,因为它提出了两个挑战:论元分散和多事件。第一个挑战…

TPM 2.0实例探索2 —— LUKS磁盘加密(1)

本文大部分内容取自: LUKS磁盘格式_小写的毛毛的博客-CSDN博客_luks 如何破解LUKS加密 一、LUKS介绍 1. 什么是LUKS LUKS是“Linux Unified Key Setup”的简写,是 Linux 硬盘加密的标准。LUKS通过提供标准的磁盘格式,不仅可以促进发行版之…

短链或H5唤醒(跳转)APP应用

唤醒APP(两种方法) 一.短链唤醒(跳转)app ⭐ 短链跳转到APP,当如果用户手机不存在APP(某个应用)将会进入到官网页面。 app links实现 在android studio菜单栏Tools->App Links Ass点击,效果图如下 2.配置如下 点击ok,生成如下效果图 3.完成第二步后,会自动…

深度解读 | 数据资产管理面临诸多挑战,做好这5个措施是关键

日前,大数据技术标准推进委员会(中国通信标准化协会下(CCSA)的专业技术委员会,简称TC601)发布《数据资产管理实践白皮书》(6.0 版)(以下简称:报告&#xff09…

网友说socket通信讲的不彻底,原来这才是Socket

关于对 Socket 的认识,大致分为下面几个主题,Socket 是什么,Socket 是如何创建的,Socket 是如何连接并收发数据的,Socket 套接字的删除等。 Socket 是什么以及创建过程 一个数据包经由应用程序产生,进入到…

linux下安装mongoDB

一、下载mongoDB包 下载地址: https://www.mongodb.com/try/download/community 个人建议:如果是学习阶段,使用5以下版本更好些。 二、安装及配置 1、安装 # 1、解压 $ tar -zxvf mongodb-linux-x86_64-rhel70-4.4.19-rc1.tgz# 2、迁移目…

【二叉树】

1,利用类来构建结点,利用函数递归来构建树2,因为左子树的结点编号是父节点的2倍,右子树的结点编号是父节点的2倍1,所以可以用数组模拟建树的过程构建二叉树第一种构建方式class treenode():#二叉树节点def __init__(se…

【西安】Python-GEE遥感云大数据分析、管理与可视化技术及多领域案例实践应用

目录 第一章 理论基础 第二章 开发环境搭建 第三章 遥感大数据处理 基础 第四章 典型案例操作实践 第五章 输入输出及数据 资产高效管理 第六章 云端数据论文出版级可视化 ​随着航空、航天、近地空间等多个遥感平台的不断发展,近年来遥感技术突飞猛进。由此&…

使用代码生成器生成代码

一、新建数据源配置 因考虑到多数据源问题,代码生成器作为一个通用的模块,后续可能会为其他工程生成代码,所以,这里不直接读取系统工程配置的数据源,而是让用户自己维护。 新建数据源 参数说明 数据源名称&#xff1…

CIMCAI intellgent ship product applied by world top3 shipcompany

CIMCAI智慧船公司集装箱管理产品ceaspectusS™全球规模应用全球前三大船公司认可验箱标准应用落地全球港航人工智能AI独角兽 CIMCAI中集飞瞳CIMCAI Intellgent shipping product ceaspectusS ™which applied by the worlds top three shipping companiesGlobal port and shipp…

关于ch340驱动安装

这是一个悲伤的故事,搞了一上午,最后的解决办法是我找到了开发板的原装数据线,一换上去,板卡上电后,点击安装,就安装驱动成功了。。。。。把我走过的弯路记录在下面,链接里的办法是能解决阶段问…

【Go】使用Go语言打造定时提醒小工具,从基础到优化全方位探索

文章目录一、引言1.目的和背景2.选择GO语言的原因二、GO语言中的时间和定时器1.时间相关的包和函数2.定时器相关的包和函数三、使用GO语言实现功能四、代码改进1.time.AfterFunc()2.sync.WaitGroup3.接收参数五、总结一、引言 1.目的和背景 本文为征文活动“CSDN 征文活动&am…

(二十二)、实现评论功能(2)【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】

1,渲染评论列表 1.1,在detail页面中定义评论列表数组和getcomment方法: commentList: [],getcomment方法: //获取评论列表async getComment() {let commentTemp db.collection("quanzi_comment").where(article_id …

浏览器跨域问题

跨域问题什么是跨域问题如何解决跨域问题JSONPCORS方式解决跨域使用 Nginx 反向代理使用 WebSocket跨源请求是否能携带Cookie什么是跨域问题 跨域问题指的是不同站点之间,使用 ajax 无法相互调用的问题。跨域问题本质是浏览器的一种保护机制,它的初衷是为…