Scrapy管道设置和数据保存
1.1 介绍部分:
文字提到常用的Web框架有Django和Flask,接下来将学习一个全球范围内流行的爬虫框架Scrapy。
1.2 内容部分:
Scrapy的概念、作用和工作流程
Scrapy的入门使用
Scrapy构造并发送请求
Scrapy模拟登陆
Scrapy管道的使用
Scrapy中间件的使用
Scrapy_redis概念作用和流程
Scrapy_redis原理分析并实现断点续爬以及分布式爬虫
Scrapy_splash组件的使用
Scrapy的日志信息与配置
Scrapyd部署Scrapy项目
1.2.1 原始爬虫工作流程
原始框架转换成矩形展示
1.2.2 scrapy框架模型
其流程可以描述如下:
爬虫中起始的url构造成request对象–>爬虫中间件–>引擎–>调度器
调度器把request–>引擎–>下载中间件–>下载器
下载器发送请求,获取response响应–>下载中间件–>引擎–>爬虫中间件–>爬虫
爬虫提取url地址,组装成request对象–>爬虫中间件–>引擎–>调度器,重复步骤2
用人话描述 spiders模块会解析最初始的url,发送给engine引擎调度器,然后由调度器发送给Downloader下载器,下载器将响应返回给调度器,调度器把响应派发给Spiders,想用传递给Spider会被内部的parse解析
自定义的下载器代码
import scrapy
class ItcastSpider(scrapy.Spider):
name = "itcast"
allowed_domains = ["itcast.cn"]
start_urls = ["https://itcast.cn"]
def parse(self, response):
#定义对于网站的相关操作
pass
1.2.3 scrapy3个内置对象
request请求对象:由url、method、post_data、header等构成
response响应对象:由url、body、status、headers等构成
item数据对象:本质是个字典
1.2.4 scrapy每个模块的作用
1.2.5 安装scrapy
pip install scrapy
1.2.6 开发流程
创建项目:
scrapy startproject mySpider
生成一个爬虫:
scrapy genspider itcast itcast.cn
提取数据:
根据网站结构在spider中实现数据采集相关内容
保存数据:
使用pipeline进行数据后续处理和保存
1.2.7 创建项目
创建scrapy项目的命令:
scrapy startproject <项目名字>
示例:
scrapy startproject myspider
生成的目录和文件结果如下:
1.2.8 scrapy中各文件作用
- spider文件夹一般爬虫都放置在该文件夹中。
- items.py负责处理被spider提取出来的item,定义数据。
- pipelines.py通道文件, 当我们的items被返回的时候,会自动调用我们的pipelines类中process_item()(需要加到settings.py里面)
- middlewares.pyscrapy框架的扩展插件
- setting.pyscrapy爬虫的配置文件。
1.2.9 创建爬虫
通过命令创建出爬虫文件,爬虫文件为主要的代码作业文件,通常一个网站的爬取动作都会在爬虫文件中进行编写。
命令:
在项目路径下执行:
scrapy genspider <爬虫名字> <允许爬取的域名>
爬虫名字:作为爬虫运行时的参数
允许爬取的域名:为对于爬虫设置的爬取范围,设置之后用于过滤要爬取的url,如果爬取的url与允许的域不通则被过滤掉。
示例:
cd myspider
scrapy genspider itcast itcast.cn
1.2.10 启动爬虫
import scrapy
class ItcastSpider(scrapy.Spider):
name = "itcast"
# 2.检查域名
allowed_domains = ['itcast.cn']
# 1.修改起始url
start_urls = ['http://www.itcast.cn/channel/teacher.shtml#ajavaee']
# 3. 在parse方法中实现爬取逻辑
def parse(self, response):
# 定义对于网站的相关操作
# with open('itcast.html', 'wb') as f:
# f.write(response.body)
# 获取所有教师节点
node_list = response.xpath('//div[@class="li_txt"]')
print("获取所有教师节点长度:",len(node_list))
data_list = []
# 遍历教师节点列表
for node in node_list:
temp = {}
#xpath 方法返回的是选择器对象列表,extract()会获取不是空列表的第一个值
temp['name'] = node.xpath('./h3/text()').extract()
temp['title'] = node.xpath('./h4/text()').extract()
temp['desc'] = node.xpath('./p/text()').extract()
print(temp)
yield temp
# data_list.append(temp)
# return data_list
运行scrapy
命令:在项目目录下执行scrapy crawl
示例:scrapy crawl itcast
scrapy crawl itcast --nolog 可以关闭日志,降低干扰
关于Scrapy爬虫的要点,包括:
- Scrapy.Spider爬虫必须有名为parse的解析函数:该函数是处理和提取数据的关键。
- 可以自定义其他解析函数:如果网站结构复杂,可以通过自定义解析函数处理特定的页面或数据。
- 解析函数中提取的URL地址如果要发送请求,必须属于allowed_domains范围内:这是一种安全措施,确保爬虫只访问指定的域名范围。
- start_urls中的URL地址不受这个限制:初始URL可以不在allowed_domains范围内,但后续解析的URL必须符合规定。
- 启动爬虫时注意启动的位置:应该在项目路径下启动,以确保正确加载项目配置和资源。
- parse()函数中使用yield返回数据:yield可以返回BaseItem, Request, dict或None。
1.2.11 定位元素以及提取数据、属性值的方法
解析并获取Scrapy爬虫中的数据:利用XPath规则对字符串进行定位和提取
response.xpath
方法的返回结果是一个类列表的类型 其中包含的是selector
对象,操作和列表一样,但是有一些额外的方法- 额外方法
extract()
:返回一个包含字符串的列表 - 额外方法
extract_first()
:返回列表中的第一个字符串,列表为空时返回None
1.2.12 response响应对象的常用属性
- response.url: 当前响应的 URL 地址
- response.request.url: 当前响应对应的请求的 URL 地址
- response.headers: 响应头
- response.request.headers: 当前响应的请求头
- response.body: 响应体,也就是 HTML 代码,类型为 byte
- response.status: 响应状态码
1.2.13 保存数据
利用管道pipeline来处理(保存)数据
1.2.14 在pipelines.py文件中定义对数据的操作
- 定义一个管道类
- 重写管道类的process_item方法
- process_item方法处理完item之后必须返回给引擎
import json
class ItcastPipeline():
# 爬虫文件中把数据传输的方法每次yield一个item, 就会运行一次
# 该方法为固定存储函数
def process_item(self, item, spider):
print(item)
return item
1.2.15 在 settings.py
配置启用管道
ITEM_PIPELINES = {
'myspider.pipelines.ItcastPipeline': 400
}
这个配置用于在 Scrapy 项目的 settings.py
文件中启用数据管道。通过将管道类 ItcastPipeline
添加到 ITEM_PIPELINES
字典中,并设置一个优先级(例如 400
),Scrapy 将会在处理每个 item
时调用该管道。
配置项中键为使用的管道类,管道类使用.进行分割,第一个为项目目录,第二个为文件,第三个为定义的管道类。
配置项中值为管道的使用顺序,设置的数值越小越优先执行,该值一般设置为1000以内。
1.2.16 pipelines.py更新数据操作,保存数据
# 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
import json
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
class MyspiderPipeline:
def __init__(self):
self.file = open('itcast.json', 'w',encoding='utf-8')
def process_item(self, item, spider):
# print("itcast:", item)
# 默认使用完管道之后将需要的数据返回给引擎
# 将字典数据序列化
json_data = json.dumps(item,ensure_ascii=False)+',\n'
# 将数据写入文件
self.file.write(json_data)
return item
def __del__(self):
self.file.close()