【Python从入门到进阶】49、当当网Scrapy项目实战(二)

接上篇《48、当当网Scrapy项目实战(一)》
上一篇我们正式开启了一个Scrapy爬虫项目的实战,对当当网进行剖析和抓取。本篇我们继续编写该当当网的项目,讲解刚刚编写的Spider与item之间的关系,以及如何使用item,以及使用pipelines管道进行数据下载的操作。

一、使用item封装数据

在上一篇我们通过编写的爬虫文件,获取到当当网“一般管理类”书籍的第一页的明细列表信息。但是我们仅仅是将爬取到的目标信息print打印到控制台了,没有保存下来,这里我们就需要item先进行数据的封装。在“dang.py”爬虫文件里,我们获取到了目标数据,这些数据是我们之前通过item定义过这些数据的数据结构,但是没有使用过:

import scrapyclass ScrapyDangdang01Item(scrapy.Item):# 书籍图片src = scrapy.Field()# 书籍名称title = scrapy.Field()# 书籍作者search_book_author = scrapy.Field()# 书籍价格price = scrapy.Field()# 书籍简介detail = scrapy.Field()

那么,我们如何使用item定义好的数据结构呢?我们在爬虫文件中,首先通过from引用上面的class的名称:

from scrapy_dangdang_01.items import ScrapyDangdang01Item

注:可能编译器会报错,这是编译器版本的问题,不影响后面的执行,可以忽略。
导入完毕之后,我们创建一个book对象,这个对象就是把上面那些零散的信息全部都组装起来的集合体,然后在构造函数中,将所有抓取到的属性,挨个赋值到item文件中的各个属性中去:

book = ScrapyDangdang01Item(src=src, title=title, search_book_author=search_book_author, price=price, detail=detail)

然后这个book对象,就要交给pipelines进行下载。

二、设置yield返回目标对象

这里我们需要使用到Python中的yield指令,它的作用如下:

        yield是Python中的一个关键字,主要用于定义生成器(generator)。生成器是一种特殊的迭代器,可以逐个地生成并返回一系列的值,而不是一次性地生成所有的值。这可以节省大量的内存,尤其是在处理大量数据时。

        yield的工作原理类似于return,但它不仅仅返回一个值,还可以保存生成器的状态,使得函数在下次调用时可以从上次离开的地方继续执行。
下面是一个简单的生成器函数的例子:

def simple_generator():  n = 1  while n <= 5:  yield n  n += 1  for i in simple_generator():  print(i)

        在这个例子中,simple_generator 是一个生成器函数,它使用 yield 来生成一系列的数字。当我们对这个生成器进行迭代(例如,在 for 循环中)时,它会逐个生成数字 1 到 5,并打印出来。

所以我们这里使用yield是用来将上面for循环中的每一个book交给pipelines处理,循环一个处理一个。编写代码如下:

# 将数据封装到item对象中
book = ScrapyDangdang01Item(src=src, title=title, search_book_author=search_book_author, price=price, detail=detail)# 获取一个book对象,就将该对象交给pipelines
yield book

此时for循环每执行一次,爬虫函数就会返回一个封装好的book对象。完整的爬虫文件代码如下(scrapy_dangdang_01/scrapy_dangdang_01/spiders/dang.py):

import scrapyfrom scrapy_dangdang_01.items import ScrapyDangdang01Itemclass DangSpider(scrapy.Spider):name = "dang"allowed_domains = ["category.dangdang.com"]start_urls = ["http://category.dangdang.com/cp01.22.01.00.00.00.html"]def parse(self, response):# 获取所有的图书列表对象li_list = response.xpath('//ul[@id="component_59"]/li')# 遍历li列表,获取每一个li元素的几个值for li in li_list:# 书籍图片src = li.xpath('.//img/@data-original').extract_first()# 第一张图片没有@data-original属性,所以会获取到控制,此时需要获取src属性值if src:src = srcelse:src = li.xpath('.//img/@src').extract_first()# 书籍名称title = li.xpath('.//img/@alt').extract_first()# 书籍作者search_book_author = li.xpath('./p[@class="search_book_author"]//span[1]//a[1]/@title').extract_first()# 书籍价格price = li.xpath('./p[@class="price"]//span[@class="search_now_price"]/text()').extract_first()# 书籍简介detail = li.xpath('./p[@class="detail"]/text()').extract_first()# print("======================")# print("【图片地址】", src)# print("【书籍标题】", title)# print("【书籍作者】", search_book_author)# print("【书籍价格】", price)# print("【书籍简介】", detail)# 将数据封装到item对象中book = ScrapyDangdang01Item(src=src, title=title, search_book_author=search_book_author, price=price, detail=detail)# 获取一个book对象,就将该对象交给pipelinesyield book

三、编写pipelines保存数据至本地

首先我们进入setting.py中,设置“ITEM_PIPELINES”参数,在其中添加我们设置的pipelines管道文件的路径地址:

# 管道可以有很多个,前面是管道名后面是管道优先级,优先级的范围是1到1000,值越小优先级越高
ITEM_PIPELINES = {"scrapy_dangdang_01.pipelines.ScrapyDangdang01Pipeline": 300,
}

此时我们进入pipelines.py中编写管道逻辑:

from itemadapter import ItemAdapter# 如果需要使用管道,要在setting.py中打开ITEM_PIPELINES参数
class ScrapyDangdang01Pipeline:# process_item函数中的item,就是爬虫文件yield的book对象def process_item(self, item, spider):# 这里写入文件需要用'a'追加模式,而不是'w'写入模式,因为写入模式会覆盖之前写的with open('book.json', 'a', encoding='utf-8') as fp:# write方法必须写一个字符串,而不能是其他的对象fp.write(str(item))return item

此时我们执行爬虫函数,可以看到执行成功:

然后我们打开生成的book.json文件,“Ctrl+Alt+l”排版之后,可以看到我们爬取的数据已经生成了:

上面就是管道+爬虫+item的综合使用模式。

四、进行必要的优化

在上面的pipelines管道函数中,我们每一次获取到爬虫for循环yield的book对象时,都需要打开一次文件进行写入,比较耗费读写资源,对文件的操作过于频繁。

优化方案:在爬虫执行开始的时候就打开文件,爬虫执行结束之后再关闭文件。此时我们就需要了解pipelines的生命周期函数。分别为以下几个方法:

(1)open_spider(self, spider): 当爬虫开始时,这个方法会被调用。你可以在这里进行一些初始化的操作,比如打开文件、建立数据库连接等。
(2)close_spider(self, spider): 当爬虫结束时,这个方法会被调用。你可以在这里进行清理操作,比如关闭文件、断开数据库连接等。
(3)process_item(self, item, spider): 这是pipelines中最核心的方法。每个被抓取并返回的项目都会经过这个方法。你可以在这里对数据进行清洗、验证、转换等操作。这个方法必须返回一个项目(可以是原项目,也可以是经过处理的新项目),或者抛出一个DropItem异常,表示该项目不应被进一步处理。

此时我们就可以使用open_spider定义爬虫开始时打开文件,close_spider定义爬虫结束时关闭文件,而在爬虫运行期间的process_item方法中,只进行写的操作,完整代码如下:

from itemadapter import ItemAdapter
import json# 如果需要使用管道,要在setting.py中打开ITEM_PIPELINES参数
class ScrapyDangdang01Pipeline:# 1、在爬虫文件开始执行前执行的方法def open_spider(self,spider):print('++++++++爬虫开始++++++++')# 这里写入文件需要用'a'追加模式,而不是'w'写入模式,因为写入模式会覆盖之前写的self.fp = open('book.json', 'a', encoding='utf-8') # 打开文件写入# 2、爬虫文件执行时,返回数据时执行的方法# process_item函数中的item,就是爬虫文件yield的book对象def process_item(self, item, spider):# write方法必须写一个字符串,而不能是其他的对象self.fp.write(str(item)) # 将爬取信息写入文件return item# 在爬虫文件开始执行后执行的方法def close_spider(self, spider):print('++++++++爬虫结束++++++++')self.fp.close() # 关闭文件写入

这样就能解决对文件操作频繁,耗费读写资源的问题了。

五、多管道的支持

pipelines支持设置多个管道,例如我们在原来的pipelines.py中再定义一个管道class类,用来下载每一个图书的图片:

# 下载爬取到的book对象中的图片文件
class ScrapyDangdangImagesPipeline:def process_item(self, item, spider):# 获取book的src属性,并按照地址下载图片,保存值books文件夹下url = 'http:' + item.get('src')filename = './books/' + item.get('title') + '.jpg'# 检查并创建目录if not os.path.exists('./books/'):os.makedirs('./books/')urllib.request.urlretrieve(url=url, filename=filename)return item

然后我们在setting.py中的ITEM_PIPELINES参数中追加这个管道:

# 管道可以有很多个,前面是管道名后面是管道优先级,优先级的范围是1到1000,值越小优先级越高
ITEM_PIPELINES = {"scrapy_dangdang_01.pipelines.ScrapyDangdang01Pipeline": 300,"scrapy_dangdang_01.pipelines.ScrapyDangdangImagesPipeline": 301
}

运行爬虫文件,可以看到相关的图片已经全部下载下来:

并且都是可以打开的图片:

至此管道+爬虫+item的综合使用模式讲解完毕。下一篇我们来讲解Scrapy的多页面下载如何实现。

参考:尚硅谷Python爬虫教程小白零基础速通
转载请注明出处:https://guangzai.blog.csdn.net/article/details/136283532

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

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

相关文章

【python】0、超详细介绍:json、http

文章目录 一、json二、http2.1 json 读取 request 序列化 三、基本类型3.1 decimal 四、图像4.1 颜色格式转换 一、json import json f open(data.json) # open json file data json.load(f) # 读出 json object for i in data[emp_details]: # 取出一级属性 emp_details, …

云尚办公-0.3.0

5. controller层 import pers.beiluo.yunshangoffice.model.system.SysRole; import pers.beiluo.yunshangoffice.service.SysRoleService;import java.util.List;//RestController&#xff1a;1.该类是控制器&#xff1b;2.方法返回值会被写进响应报文的报文体&#xff0c;而…

ChatRTX安装教程

介于本人一直想将现有的智慧城市的文档结合大模型RAG实现知识库问答助手&#xff0c;借着Chat With RTX的风潮正好将机器人和知识库合二为一&#xff0c;方便以后对众多文件进行查阅。 一、概要 Chat With RTX 是一个 Demo&#xff0c;用来将您自己的资料&#xff08;文档、笔…

第三节:kafka sarama 遇到Bug?

文章目录 前言一、先上结果二、刨根问底总结 前言 前面两节&#xff0c;我们已经简单应用了sarama的两个类型Client和ClusterAdmin&#xff0c;其中有一个案例是获取集群的ControllerId&#xff0c;但是在后面的测试过程过程中&#xff0c;发现一个问题&#xff0c;返回的Cont…

【PyQt5桌面应用开发】3.Qt Designer快速入门(控件详解)

一、Qt Designer简介 Qt Designer是PyQt程序UI界面的实现工具&#xff0c;可以帮助我们快速开发 PyQt 程序的速度。它生成的 UI 界面是一个后缀为 .ui 的文件&#xff0c;可以通过 pyiuc 转换为 .py 文件。 Qt Designer工具使用简单&#xff0c;可以通过拖拽和点击完成复杂界面…

仿12306校招项目业务二(列车检索)

目录 验证数据 加载城市数据 查询列车站点信息 查询列车余票信息 构建列车返回数据 12306 项目中列车数据检索接口路径 &#xfeff; TicketController的pageListTicketQuery&#xfeff;。 GetMapping("/api/ticket-service/ticket/query")public Result<T…

查看笔记本电池健康状态-windows11

在 Windows 11 中获取详细的电池报告 Windows 11 中内置的 Powerfg 命令行选项来生成电池报告。 在任务栏上选择“搜索”&#xff0c;键入“cmd”&#xff0c;长按&#xff08;或右键单击&#xff09;“命令提示符”&#xff0c;然后选择“以管理员身份运行” ->“是”。 …

Mac使用K6工具压测WebSocket

commend空格 打开终端&#xff0c;安装k6 brew install k6验证是否安装成功 k6 version设置日志级别为debug export K6_LOG_LEVELdebug执行脚本&#xff08;进入脚本所在文件夹下&#xff09; k6 run --vus 100 --duration 10m --out csvresult.csv script.js 脚本解释&…

自定义神经网络三之梯度和损失函数激活函数

文章目录 前言梯度概述梯度下降算法梯度下降的过程 optimize优化器 梯度问题梯度消失梯度爆炸 损失函数常用的损失函数损失函数使用原则 激活函数激活函数和损失函数的区别激活函数Relu-隐藏层激活函数Sigmoid和Tanh-隐藏层Sigmoid函数Tanh&#xff08;双曲正切&#xff09; &l…

【前端】nginx 反向代理,实现跨域问题

前面讲跨域的问题&#xff0c;这篇 C# webapi 文章里面已经说过了。在上述文章中是属于从服务器端去允许访问的策略去解决跨域问题。而这里是从客户端的角度利用反向代理的方法去解决跨域问题。 反向代理&#xff1a;其原理就是将请求都接收到一个中间件&#xff08;中间地址&a…

IO 作业 24/2/26

1>思维导图 1> 使用消息队列完成两个进程间相互通信 #include<myhead.h> //定义一个消息类型 struct msgbuf {long mtype; //消息类型char mtext[1024]; //消息正文 }; //定义一个宏&#xff0c;表示消息正文大小 #define MSGSIZE sizeof(struct msgbuf…

人工智能 — 点云模型

目录 一、点云模型1、三维图像2、点云1、概念2、内容 3、点云处理的三个层次1、低层次处理方法2、中层次处理方法3、高层次处理方法 二、Spin image 一、点云模型 1、三维图像 三维图像是一种特殊的信息表达形式&#xff0c;其特征是表达的空间中三个维度的数据。 和二维图像…

荣耀手机如何开启地震预警功能

1、打开荣耀手机&#xff0c;进入“设置”&#xff0c;在搜素栏输入“地震”。 2、进入“安全-应急预警通知”功能栏。 3、开启“地震预警”。 4、查看“预警演示教程”。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/e207e356bb634c11adf926c6a53e48cc.png…

Mysql学习之事务日志redolog深入剖析

Mysql 事务日志 redo log 事务有4种特性&#xff1a;原子性、一致性、隔离性和持久性。那么事务的四种特性到底是基于什么机制实现的呢&#xff1f; 事务的隔离性由锁机制实现。而事务的原子性、一致性和持久性由事务的redo日志和undo日志来保证。 REDO LOG 称为重做日志&…

OpenGL ES (OpenGL) Compute Shader 计算着色器是怎么用的?

OpenGL ES (OpenGL) Compute Shader 是怎么用的? Compute Shader 是 OpenGL ES(以及 OpenGL )中的一种 Shader 程序类型,用于在GPU上执行通用计算任务。与传统的顶点着色器和片段着色器不同,Compute Shader 被设计用于在 GPU 上执行各种通用计算任务,而不是仅仅处理图形…

挑战杯 基于情感分析的网络舆情热点分析系统

文章目录 0 前言1 课题背景2 数据处理3 文本情感分析3.1 情感分析-词库搭建3.2 文本情感分析实现3.3 建立情感倾向性分析模型 4 数据可视化工具4.1 django框架介绍4.2 ECharts 5 Django使用echarts进行可视化展示5.1 修改setting.py连接mysql数据库5.2 导入数据5.3 使用echarts…

供应链大数据:穿越经济迷雾的指南针

随着经济形势的变幻莫测&#xff0c;企业运营面临着前所未有的挑战。在这个充满不确定性的时代&#xff0c;供应链大数据如同一盏明亮的指南针&#xff0c;为企业提供精准的方向指引。下面&#xff0c;我们将深入探讨供应链大数据如何帮助企业洞察市场趋势、优化库存管理、降低…

2.deeplabv3+的主干网络(mobilenet网络)

deeplabv3的论文中用了resnet网络&#xff0c;在这里用轻量级网络mobilenet替换resnet&#xff0c;下面分别是两个网络的代码。 1.mobilenet网络 代码如下&#xff1a; import math import os import cv2 import numpy as np import torch import torch.nn as nn import tor…

基于YOLOv8深度学习+Pyqt5的电动车头盔佩戴检测系统

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;225头盔 获取完整源码源文件已标注的数据集&#xff08;1463张&#xff09;源码各文件说明配置跑通说明文档 若需要一对一远程操作在你电脑跑通&#xff0c;有偿89yuan 效果展示 基于YOLOv8深度学习PyQT5的电动车头盔佩戴检…

网络防御-内容安全

目录 内容安全IAE引擎DFI和DPI技术 --- 深度检测技术DPI --- 深度包检测技术DFI --- 深度流检测技术 入侵防御&#xff08;IPS&#xff09;入侵检测的方法异常检测误用检测 签名ID --- 签名的标识检测范围 内容安全 攻击可能只是一个点&#xff0c;防御需要全方面进行 IAE引擎 …