Scrapy爬虫异步框架之持久化存储(一篇文章齐全)

1、Scrapy框架初识(点击前往查阅)

2、Scrapy框架持久化存储(点击前往查阅)

3、Scrapy框架内置管道(点击前往查阅)

4、Scrapy框架中间件(点击前往查阅)

Scrapy 是一个开源的、基于Python的爬虫框架,它提供了强大而灵活的工具,用于快速、高效地提取信息。Scrapy包含了自动处理请求、处理Cookies、自动跟踪链接、下载中间件等功能

Scrapy框架的架构图(先学会再来看,就能看懂了!)

 

 一、持久化存储(文本)

1:基于终端指令的存储

基于终端指令:简单,但是局限性较大。

scrapy crawl myspider -o project_name.后缀名

命令讲解: (例:scrapy crawl baidu -o baidudata.json

  • myspider:执行的爬虫文件名
  • project_name.后缀名:想要保存的文件名和格式(具体格式参考下面)

终端指令的方法只可以将parse方法的返回值存储到指定后缀的文本文件中。且格式只能是如下展示的。

1.1:执行代码

import scrapy


class BaiduSpider(scrapy.Spider):
    # 爬虫文件的唯一标识(就是你创建的爬虫文件夹名字)
    name = "baidu"

    # 允许的域名,这个代表你只能访问这个网址的子域名,其他的都会禁止(这个我们会注释掉,不会打开)
    # allowed_domains = ["www.xxx.com"]

    # 起始的url列表,网址可以随便放,可以放多个,列表中的url都会被框架进行异步请求发送。
    start_urls = ["https://www.xiachufang.com/category/40076/"]

    # 数据解析:parse调用的次数取决于start_urls列表元素的个数
    def parse(self, response):  # response参数就表示响应对象
        # 创建一个空列表用于存储
        all_data = []

        # 利用xpath解析:(scrapy内置xpath,无需另外导入)
        li_list = response.xpath('//div[@class="pure-u-3-4 category-recipe-list"]//ul/li')

        for li in li_list:
            # 1、scrapy中的xpath会返回Selector对象,我们需要的数据在该对象data属性中(extract可以实现该功能,)
            # 2、extract_first()就是取第一个,因为文本两边有空格,所以.strip() 可以去除两侧的空格
            title = li.xpath('.//p[1]/a/text()').extract_first().strip()
            author = li.xpath('.//p[4]/a/text()').extract_first().strip()

            # 将每次获取到的标题和作者添加到字典中
            dic = {
                'title': title,
                'author': author
            }

            # 将字典添加到列表中
            all_data.append(dic)

        # 爬取到的数据被作为parse方法的返回值
        return all_data

1.1:执行结果分析

此代码在这个Scrapy框架初识(点击前往查阅)代码上就加了前4步(如下图)。

  • 第5步:执行代码
  • 第6步:最后生成的文件Scrapy框架初识(点击前往查阅)

 基于终端指令存储就是这样的,虽然简单,但是局限性很大。

2:基于管道的存储(存入本地文件)

基于管道的形式:相比较终端复杂,但是灵活性很大。

管道存储so easy 只需5步

2.1:在爬虫文件中进行数据解析操作。

解析代码如下⬇️

import scrapy


class BaiduSpider(scrapy.Spider):
    # 爬虫文件的唯一标识(就是你创建的爬虫文件夹名字)
    name = "baidu"

    # 允许的域名,这个代表你只能访问这个网址的子域名,其他的都会禁止(这个我们会注释掉,不会打开)
    # allowed_domains = ["www.xxx.com"]

    # 起始的url列表,网址可以随便放,可以放多个,列表中的url都会被框架进行异步请求发送。
    start_urls = ["https://www.xiachufang.com/category/40076/"]

    # 数据解析:parse调用的次数取决于start_urls列表元素的个数
    def parse(self, response):  # response参数就表示响应对象
        # 创建一个空列表用于存储
        all_data = []

        # 利用xpath解析:(scrapy内置xpath,无需另外导入)
        li_list = response.xpath('//div[@class="pure-u-3-4 category-recipe-list"]//ul/li')

        for li in li_list:
            # 1、scrapy中的xpath会返回Selector对象,我们需要的数据在该对象data属性中(extract可以实现该功能,)
            # 2、extract_first()就是取第一个,因为文本两边有空格,所以.strip() 可以去除两侧的空格
            title = li.xpath('.//p[1]/a/text()').extract_first().strip()
            author = li.xpath('.//p[4]/a/text()').extract_first().strip()

 

2.2:创建一个item类型的对象。

创建的item对象,需要封装自己需要的变量。例如:我需要title、author两个变量(框架中有封装好item类型文件)

2.2.1:将解析到的数据存储到该对象中。

如何将解析好的数据存储到item对象中呢?各位看官接着往下看~

2.3:将item对象提交给管道。

什么是管道呢?管道在框架中在哪呢?就在这~

 

如何将item对象提交给管道呢?只需要 yield 关键字就可以了! 

2.4:在管道中实现process_item的函数,实现对item对象的接收,对其进行指定的持久化存储。

代码讲解:(return是有多个管道把数据传递给下一个,后面会讲解)

  • open_spider函数:这个函数只会在process_item函数之前之前执行一次,所以这就操作的空间了,我们可以先定义一个全局变量,然后在这个函数中创建一个文件句柄。
  • process_item函数:self调用写入数据就行了。
  • close_spider函数:该函数会在process_item函数完全执行结束之后调用一次,这个里边就关闭文件就行了。

错误演示:❌❌❌

可能会有同学会想到用这个方法来储存,这就要想到一个问题了,process_item函数会被执行很多次(执行的次数取决于爬虫文件提交的次数)所以这个方法肯定是不行的。

2.5:在配置文件中开启管道功能。

注释去掉就是开启了,后面的300是优先级的,如果有多个管道会用到,数字越小优先级越高,下面会讲~(另外UA或者Cookie一些反爬根据网站需求决定是否开启

 

 2.6:执行结果

 执行指令:my_spider就是你的爬虫文件名字

scrapy crawl my_spider

执行代码:

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter


class CsdnPipeline:
    fp = None  # 全局变量。

    # 该函数只会被在process_item函数调用前被调用一次。
    def open_spider(self, item):
        # 创建文件
        self.fp = open('baidu.txt', 'w')

    # 该函数只会被在process_item函数完全执行结束后被调用一次。
    def close_spider(self, item):
        # 关闭文件
        self.fp.close()

    # 该函数是用来接收爬虫文件提交过来的item对象(此函数执行次数取决于爬虫文件提交的次数)
    def process_item(self, item, spider):  # item参数就表示接收到的item对象。
        # 将item中的数据取出来
        title = item['title']
        author = item['author']

        # 数据写入
        self.fp.write(title + ":" + author + '\n')

        return item

以我们设置的文件格式,文件名字储存好了。 

 

二、基于管道的存储(存入数据库)

首先肯定要先安装MySQL数据库的,没有安装可以参考最新版MySQL安装 & 配置 & 启动

还需要安装模块用于操作MySQL数据库

pip install pymsql

存到数据库步骤:(数据库要提前开启哦)

和存入本地文件唯一不同的地方就在第四步管道函数的编写,下面我们就把这方面重点分析一下~

1:settings中配置

前面还提到了 yield 的关键字,是提交给管道的,他优先提交给数字小的,也就是优先级高的。

 

2:管道原理剖析

还记得前面的 return吗?现在来填坑了!!!

如果 你需要一个管道就OK了下面不需要了,那OK不需要return也是可以的,但是,你下面还有管道,那必须要return的,不然你数据无法传递下去,并且还会报错。

 

3:代码编写

首先要学会Python操作MySQL方法,不会的可以参考这Python操作中MySQL数据方法

此代码指针对MySQL数据库的,完整的需要包含上面 class CsdnPipeline 中的代码 

import pymysql  # 导入操作数据库模块

class MysqlPipeline:
    # 1、创建一个链接对象
    conn = pymysql.connect(
        host='127.0.0.1',  # mysql服务器的ip地址
        port=3306,  # mysql默认端口号
        user='root',  # mysql用户名
        password='root1234',  # mysql密码
        db='spider',  # mysql指定的数据库
    )
    # 2、创建一个游标对象:用来执行sql语句
    cursor = conn.cursor()

    def process_item(self, item, spider):
        # 利用上面传入的item,我们先获取到数据
        title = item['title']
        author = item['author']

        # 将2个字段存储到mysql数据表中
        sql = 'insert into bili(title,author) values ("{}","{}")'.format(title, author)
        # 使用游标对象执行sql语句
        self.cursor.execute(sql)
        # 提交事物,最后才会将数据存入数据库中
        self.conn.commit()
        return item

    def close_spider(self, spider):
        # 关闭游标和链接对象
        self.cursor.close()
        self.conn.close()

 代码分析:

 其中主要就是数据库的链接,要提前创建好表和对应的字段,然后会简单的SQL语句。

 4:执行结果

三、基于管道的存储(存入Redis缓存中)

 首先肯定要先安装Redis的,没有安装可以参考手把手安装部署Redis

 还需要安装模块用于操作Redis,这个安装个低版本的,高的有些数据格式不支持,例如字典就不行的。

pip install redis==2.10.6

存到Redis步骤:(Redis要提前开启哦)

和上面一样的唯一不同的地方就在第四步管道函数的编写,下面我们就把这方面重点分析一下~

1:settings中配置 

 

2:代码编写

 此代码指针对Redis缓存的,完整的需要包含上面 class CsdnPipeline 和 class MysqlPipeline 中的代码。 

from redis import Redis  # 导入模块


class RedisPipeline:
    # 创建链接对象
    conn = Redis(host='127.0.0.1', port=6379)

    def process_item(self, item, spider):
        # 将item这个字典存储到redis中
        self.conn.lpush('bili', item)  # lpush(参数1,参数2):参数1新建列表的名称,参数2是向列表中存储的数据
        return item

 代码分析:

Redis的比较简单,主要就是连接,按照这个写就行了,没有啥理解的,固定语法。

 

 3:执行结果

 

自此Scrapy框架持久化存储的2种方法就这些了,另外还有就是图片和视频的持久存储,在内置管道中讲解。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jQuery_06 过滤器的使用

什么是过滤器? 过滤器就是用来筛选dom对象的,过滤器是和选择器一起使用的。在选择了dom对象后在进行过滤筛选。 jQuery对象中存储的dom对象顺序与页面标签声明有关系。 声明顺序就是dom中存放的顺序 1.基本过滤器 使用dom对象在数组中的位置来作为过滤条…

.NET6 开发一个检查某些状态持续多长时间的类

📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!📢本文作者:由webmote 原创📢作者格言:新的征程,我们面对的不仅仅是技术还有人心,人心不可测,海水不可量,唯有技术,才是深沉黑夜中的一座闪烁的灯塔 !序言 在代码的世界里,时常碰撞…

【Linux学习】基础IO

目录 八.系统文件IO 8.1 前言 8.2 C语言文件IO C语言常用的基本函数 C语言默认打开的的三个流 8.3 系统文件IO open接口 close接口 write接口 read接口 8.4 C语言文件IO与系统文件IO的关系 八.系统文件IO 8.1 前言 系统文件 I/O(输入/输出)是指在…

【电路笔记】-快速了电阻

电阻类型 文章目录 电阻类型1、概述2、电阻器的组成类型2.1 碳电阻器2.2 薄膜电阻器2.3 绕线电阻器 3、总结 电阻器是所有电子元件中最基本、最常用的元件,人们几乎认为电阻器是理所当然的,但它们在电路中起着至关重要的作用。 1、概述 有许多不同类型的…

17.找出1000之内的所有完数。

文章目录 前言一、题目描述 二、题目分析 三、解题 程序运行代码 前言 本系列为循环结构编程题,点滴成长,一起逆袭。 一、题目描述 一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如,⑥的因子为1、2、3,而…

2024年最新最全的Jmeter接口测试必会技能:jmeter_HTTP Cookie管理器

HTTP Cookie管理器 HTTP Cookie管理器可以像浏览器一样自动存储和发送cookie,以这种自 动收集的方式收集到的cookie不会在cookie manager中进行展示,但是运行后, 可以通过 查看结果树(监听器)可以查看到cookie信息 除…

【开源】基于JAVA的天然气工程业务管理系统

项目编号: S 021 ,文末获取源码。 \color{red}{项目编号:S021,文末获取源码。} 项目编号:S021,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、使用角色3.1 施工人员3.2 管理员 四…

hive杂谈

数据仓库是一个面向主题的、集成的、非易失的、随时间变化的,用来支持管理人员决策的数据集合,数据仓库中包含了粒度化的企业数据。 数据仓库的主要特征是:主题性、集成性、非易失性、时变性。 数据仓库的体系结构通常包含4个层次&#xff…

(数据结构)顺序表的定义

#include<stdio.h> //顺序表的实现——静态分配 #define MAX 10 //定义最大长度 typedef struct List {int data[MAX]; //用静态的数组存放数据int lenth; //顺序表现在的长度 }List; //顺序表的初始化 void ChuShiHua(List L) {L.lenth 0; //将顺序表的长度初始化…

NAS非接入层协议学习(二)

在无线通信网络中 NAS (Non-Access Stratum)做为非接入层是演进分组系统(或5G核心网)中的一组协议。NAS用于在用户设备(UE)和移动管理实体(MME/AMF)之间传送非无线电信令&#xff0c;以实现NR/LTE/E-UTRAN接入。 NAS在协议栈中是控制面的最高层。 NAS协议分组中可以将其分为两…

『Confetti 喜庆散花插件の使用』

以下用 VUE3 语法 举例使用&#xff1a; npm install js-confetti<script setup lang"ts"> import JSConfetti from js-confetticonst confetti new JSConfetti()function showConfetti() {confetti.addConfetti() } </script><template><h1 …

“BMP转PNG一键转换,批量处理图片,迈入高效图片管理新时代“

你是否曾经为了转换图片格式而烦恼&#xff1f;是否曾经因为一张一张地手动转换而感到无奈&#xff1f;现在&#xff0c;我们的全新工具将为你解决这些问题&#xff0c;开启高效图片管理新时代&#xff01; 首先&#xff0c;我们进入首助编辑高手主页面&#xff0c;会看到有多种…

人力资源管理后台 === 首页+部署

目录 1.首页-echarts图表的应用 2.首页-echarts图表的按需导入 3.路由模式-将路由改成history模式 4. 打包分析-分析 5.CDN加速 6.项目打包-安装nginx 7.mac/windows环境下nginx部署启动项目 8.nginx解决history的404问题 9.nginx配置代理解决生产环境跨域问题 1.首页-…

分享一个鬼~

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 先看效果&#xff1a; 上源码&#xff1a; import GUI from "https://cdn.jsdelivr.net/npm/lil-gui0.18.2/esm"const canv…

C/C++内存管理,malloc,realloc,calloc,new,delete详解!!!

1.初步了解内存中各个区间存储的数据特征 1.栈区&#xff1a;存储一些局部变量、函数参数、返回值等&#xff0c;跟函数栈振有关&#xff0c;出了作用域&#xff0c;生命周期结束。 2.堆区&#xff1a;用于动态开辟空间&#xff0c;如果不主动销毁空间&#xff0c;则程序运行结…

Centos Bind安装与排错

1.配置Centos系统静态IP vi/etc/sysconfig/network-scripts/ifcfg-ens33BOOTPROTOstaticIPADDR192.168.1.100NETMASK255.255.255.0GATEWAY192.168.1.1DNS18.8.8.8:wqsudo systemctl restart network.service 2.安装BIND&#xff08;需要服务器连接互联网&#xff0c;如果服务…

手把手教你实现一个循环队列(C语言)

这是一道leetcode关于队列的经典题&#xff1a; 622. 设计循环队列https://leetcode.cn/problems/design-circular-queue/ 思路&#xff1a; 大家注意这个题目要求&#xff0c;这个队列是定长的&#xff0c;如果满了则不能再添加数据。那么我们设计一个队头front和队尾rear&…

激光雷达SLAM(一)------初始激光雷达SLAM

专栏目的及认识激光雷达SLAM 一、专栏目的二、初始激光雷达SLAM1、激光雷达SLAM算法相关知识点2、SLAM常见问题[^2]3、激光雷达SLAM的需求点4、RTK在SLAM中的作用5、激光雷达视觉紧耦合图优化滤波紧耦合 一、专栏目的 大家好&#xff01;介绍一下博主自己&#xff0c;感知算法工…

职场份子钱随不随?这20个真相你需要知道!

职场份子钱随不随&#xff1f;这20个真相你需要知道&#xff01; 1.千万不要在老婆面前夸小姨子水灵。 2.盖世功劳&#xff0c;当不得一个矜字&#xff1b;弥天罪过&#xff0c;当不得一个悔字。 3.愚蠢的人永远只会根据答案判断难度。 4.改变自己的是神&#xff0c;企图改…

数据库基础教程之数据库的创建(一)

双击打开Navicat&#xff0c;点击&#xff1a;文件-》新建连接-》PostgreSQL 在下图新建连接中输入各参数&#xff0c;然后点击&#xff1a;连接测试&#xff0c;连接成功后再点击确定。 点击新建数据库 数据库设置如下&#xff1a;