scrapy框架的持久化存储
一 . 基于终端指令的持久化存储
保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作。
执行输出指定格式进行存储: 将爬取到的数据写入不同格式的文件中进行存储
scrapy crawl 爬虫名称 -o xxx.json
scrapy crawl 爬虫名称 - o xxx.xml
scrapy crawl 爬虫名称 - o xxx.csv
二 . 基于管道的持久化存储
scrapy框架已经为我们专门集成了高效 , 便捷的持久化操作功能,我们直接用即可.
在使用scrapy的持久化操作功能之前,我们要知道这两个文件是什么 ?
item.py : 数据结构模板文件, 定义数据属性
pipelines.py: 管道文件. 接收数据(items) 进行持久化操作 持久化流程: 1. 爬虫文件爬到数据后, 需要将数据封装到 items 对象中
2. 使用yield 关键字将items 对象提交给 pipelines 管道进行持久化操作.
3. 在管道文件中的 process_item 方法中接收爬虫文件提交过来的item 对象, 然后编写持久化存储的代码将item对象中存储的数据进行持久化存储
4.settings.py配置文件中开启管道
三 . 实例
1 . 进行本地的持久化存储
⑴ . 爬虫文件 first_hh.py
# -*- coding: utf-8 -*-
import scrapy
from frist_boll.items import FristBollItem class FirstHhSpider(scrapy.Spider):
# 爬虫文件的名称
name = 'first_hh'
# 允许访问的域名 , 但是有时候图片的地址与访问的网站不是同一域名,
# 为了可以正常访问,就注释了就好
# allowed_domains = ['www.xxx.com']
# 起始的url列表,可以放多个url
start_urls = ['https://www.qiushibaike.com/text/'] def parse(self, response):
div_list = response.xpath("//div[@id='content-left']/div")
# all_data = [] for div in div_list:
# 如果xpath返回的列表中只有一个类别元素-就用extract_first
# 列表中有多个列表元素-用extract()
author = div.xpath('./div[1]/a[2]/h2/text()').extract_first()
content = div.xpath('./a[1]/div/span//text()').extract() # 储存的时候要是字符串,不能是列表
content = "".join(content) # 实例化item对象
item = FristBollItem()
# 将解析到的数据全部封装到item中,传给管道文件pipelines.py
item['author'] = author
item['content'] = content
# 将item提交给管道文件(pipelines.py)
yield item
⑵ . items.py 文件
# -*- coding: utf-8 -*- # Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html class FristBollPipeline(object):
f1 = None #定义一个文件描述符属性 # 打开文件,因为函数process_item 要进行循环,所有只要打开一次文件就可以,
# 下面都是重写父类方法,所有spider参数必须有
def open_spider(self, spider):
print("start")
self.f1 = open('./趣事百科.csv', 'w', encoding='utf-8') #因为该方法会被执行调用多次,所以文件的开启和关闭操作写在了另外两个只会各自执行一次的方法中。
def process_item(self, item, spider):
#将爬虫程序提交的item进行持久化存储
self.f1.write(item['author'] + '\n' + item['content'])
print()
return item # 结束爬虫 , 关闭文件
def close_spider(self, spider):
print("end")
self.f1.close()
⑷ . 配置文件 : settings.py
#开启管道
ITEM_PIPELINES = {
'secondblood.pipelines.SecondbloodPipeline': 300, #300表示为优先级,值越小优先级越高
}
2 . 基于mysql的管道存储
爬取boss直聘的爬虫职位
先将 mysql打开,并创建一个文件夹和创建个文件,而且你要存储的字段也要创建好,scrapy框架只负责添加数据到mysql,不负责创建.
创建项目 : scrapy startproject boss
进入目录 : cd boss
创建应用 : scrapy genspider boss_hh www.xxx.com
⑴ . 爬虫文件 : boss_hh.py
# -*- coding: utf-8 -*-
import scrapy
from boss.items import BossItem class BossHhSpider(scrapy.Spider):
name = 'boss_hh'
# allowed_domains = ['www.xxx.com']
start_urls = ['https://www.zhipin.com/job_detail/?query=%E7%88%AC%E8%99%AB&scity=101010100&industry=&position=']
# 因为有分页的效果,而且第一页与后面几页的url不一样,所有要进行判断 page=%d 进行页码
url = 'https://www.zhipin.com/c101010100/?query=python爬虫&page=%d&ka=page-2'
# 默认第一页,起始页面
page = 1 def parse(self, response):
li_list = response.xpath('//div[@class="job-list"]/ul/li')
for li in li_list:
job_name = li.xpath('.//div[@class="info-primary"]/h3/a/div/text()').extract_first()
salary = li.xpath('.//div[@class="info-primary"]/h3/a/span/text()').extract_first()
company = li.xpath('.//div[@class="company-text"]/h3/a/text()').extract_first()
# 实例化
item = BossItem()
# 解析到的数据加到item对象中
item['job_name'] = job_name
item['salary'] = salary
item['company'] = company
# 提交到管道进行保存
yield item
if self.page <= 3:
print("执行 if 判断 ")
# 从第二页开始,封装集成了一个新的页码的url
self.page += 1
# 占位
new_url = format(self.url % self.page) # 手动请求的发送,callback 表示指定的解析方式 , 回调
#递归爬取数据:callback参数的值为回调函数(将url请求后,得到的相应数据继续进行parse解析),递归调用parse函数 yield scrapy.Request(url=new_url,callback=self.parse)
⑵ . items文件 :
# -*- coding: utf-8 -*- # Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html import scrapy class BossItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field() job_name = scrapy.Field()
salary = scrapy.Field()
company = scrapy.Field()
⑶ . 管道文件 : pipelines.py
# -*- coding: utf-8 -*- # Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html import pymysql
from redis import Redis class mysqlPipeline(object):
conn = None
cursor = None # 打开mysql
def open_spider(self, spider):
self.conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='', db='scrapy', charset='utf8') def process_item(self, item, spider):
self.cursor = self.conn.cursor()
try:
# 将数据写入mysql
self.cursor.execute('insert into boss(job_name,salary,company) values("%s","%s","%s")' % (item['job_name'], item['salary'], item['company'])) self.conn.commit()
except Exception as e:
self.conn.rollback()
return item # 注意
# 关闭mysql
def close_spider(self, spider):
self.conn.close()
self.cursor.close()
⑷ . settings文件 :
ITEM_PIPELINES = {
# 'boss.pipelines.BossPipeline': 300,
'boss.pipelines.mysqlPipeline': 301,
}
# 前一个属于子代文件,如果只想执行mysql,就可以将前面的注释
注意 : 在管道文件 : pipelines.py 中 , 函数 mysqlPipeline,最后返回了一个 return item . 这个是给下面的函数进行的,因为可以在一个管道文件中进行本地硬盘存储和mysql存储,可以通过 settings里面的开启管道的优先级设置那个先进行存储,return item 就会从先执行的传给后执行的. 一定要返回,否则后面的不会执行
# -*- coding: utf-8 -*- # Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html import pymysql
from redis import Redis class BossPipeline(object):
f1 = None def open_spider(self, spider):
print("start ----------->")
self.f1 = open('boss.txt', 'w', encoding='utf-8') def close_spider(self, spider):
print("end ------------->")
self.f1.close() def process_item(self, item, spider):
self.f1.write(item['job_name'] + ":" + item['salary'] + ":" + item['company'] + '\n')
return item # 返回给mysql进行 class mysqlPipeline(object):
conn = None
cursor = None def open_spider(self, spider):
self.conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='', db='scrapy', charset='utf8') def process_item(self, item, spider):
self.cursor = self.conn.cursor()
try:
self.cursor.execute('insert into boss(job_name,salary,company) values("%s","%s","%s")' % (item['job_name'], item['salary'], item['company']))
self.conn.commit()
except Exception as e:
self.conn.rollback()
return item def close_spider(self, spider):
self.conn.close()
self.cursor.close()
管道文件 : 本地和mysql都存储
3 . 基于redis的管道存储
只需要将 管道文件 修改就可以了 !!!!!
from redis import Redis class redisPileLine(object):
conn = None def open_spider(self, spider):
self.conn = Redis(host='127.0.0.1', port=6379)
print(self.conn) def process_item(self, item, spider):
# print(item)
dic = {
'name': item['job_name'],
'salary': item['salary'],
'company': item['company']
}
self.conn.lpush('boss', dic)
settings文件 :
ITEM_PIPELINES = {
'qiubaiPro.pipelines.QiubaiproPipelineByRedis': 300,
}
四 . 总结
如果最终需要将爬取到的数据值一份存储到磁盘文件,一份存储到数据库中,则应该如何操作scrapy?
答 : 管道文件中的代码
#该类为管道类,该类中的process_item方法是用来实现持久化存储操作的。
class DoublekillPipeline(object): def process_item(self, item, spider):
#持久化操作代码 (方式1:写入磁盘文件)
return item #如果想实现另一种形式的持久化操作,则可以再定制一个管道类:
class DoublekillPipeline_db(object): def process_item(self, item, spider):
#持久化操作代码 (方式1:写入数据库)
return item
settings.py文件的开启管道的代码 :
#下列结构为字典,字典中的键值表示的是即将被启用执行的管道文件和其执行的优先级。
ITEM_PIPELINES = {
'doublekill.pipelines.DoublekillPipeline': 300,
'doublekill.pipelines.DoublekillPipeline_db': 200,
} #上述代码中,字典中的两组键值分别表示会执行管道文件中对应的两个管道类中的process_item方法,实现两种不同形式的持久化操作。
scrapy框架的持久化存储的更多相关文章
- (六--二)scrapy框架之持久化操作
scrapy框架之持久化操作 基于终端指令的持久化存储 基于管道的持久化存储 1 基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过 ...
- scrapy 爬虫框架之持久化存储
scrapy 持久化存储 一.主要过程: 以爬取校花网为例 : http://www.xiaohuar.com/hua/ 1. spider 回调函数 返回item 时 要用y ...
- scrapy框架之持久化操作
1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作. 执行输出指定格式进行存储: ...
- 爬虫开发8.scrapy框架之持久化操作
今日概要 基于终端指令的持久化存储 基于管道的持久化存储 今日详情 1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的 ...
- 小爬爬5:scrapy介绍3持久化存储
一.两种持久化存储的方式 1.基于终端指令的吃持久化存储: 特点:终端指令的持久化存储,只可以将parse方法的返回值存储到磁盘文件 因此我们需要将上一篇文章中的author和content作为返回值 ...
- Scrapy 框架,持久化文件相关
持久化相关 相关文件 items.py 数据结构模板文件.定义数据属性. pipelines.py 管道文件.接收数据(items),进行持久化操作. 持久化流程 1.爬虫文件爬取到数据后,需要将数据 ...
- 11.scrapy框架持久化存储
今日概要 基于终端指令的持久化存储 基于管道的持久化存储 今日详情 1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的 ...
- scrapy框架持久化存储
基于终端指令的持久化存储 基于管道的持久化存储 1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文 ...
- 11,scrapy框架持久化存储
今日总结 基于终端指令的持久化存储 基于管道的持久化存储 今日详情 1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的 ...
随机推荐
- HDU1757
解题思路:分析需要不少时间,比较懒,直接把别人的分析贴在这里, 然后贴上自己写的代码: K相当之大.所以逐一递推的算法无法胜任.这时我们就不得不运用矩阵加速.首先来讲一下矩阵乘法: 若一矩阵的列数与另 ...
- 关于Mybatis将查询结果中添加常量列并返回
引言 在使用mybatis的时候,查询一个集合返回给前台页面,在有的时候,我们会添加一个常量字段到对象或者集合中,来标识这个对象属于的类型等等情况,当前台进行再次请求的时候携带此变量进行请求. 但是: ...
- 解决 mklink 使用中的各种坑(硬链接,软链接/符号链接,目录链接)
通过 mklink 命令可以创建文件或文件夹的链接,而这种链接跟快捷方式是不一样的.然而我们还可能会遇到其使用过程中的一些坑,本文将整理这些坑并提供解决方法. 0x00 背景介绍:mklink m ...
- VS 2013 简体中文 专业版 下载地址。
官方原始链接:http://download.microsoft.com/download/7/A/C/7AC27F37-FDFE-4991-B18A-962E26E31BD1/VS2013_RTM_ ...
- phpstrom主题
http://phpstorm-themes.com/ 安装方法 JAR文件 导航->file->Import Settings->然后选择你刚才下载的JAR文件->点击确认- ...
- 系列文章--ASP.NET之AJAX入门教程
ASP.NET AJAX入门系列将会写关于ASP.NET AJAX一些控件的使用方法以及基础知识,其中部分文章为原创,也有一些文章是直接翻译自官方文档,本部分内容会不断更新. 目录 ASP.NET A ...
- L2TP/IPSec一键安装脚本
本脚本适用环境:系统支持:CentOS6+,Debian7+,Ubuntu12+内存要求:≥128M更新日期:2017 年 05 月 28 日 关于本脚本:名词解释如下L2TP(Layer 2 Tun ...
- VirtulBox安装虚拟机(鼠标点击时)0x00000000指令引用的0x00000000内存该内存不能为written错误解决方案
这个错误并不是所有人都会用到,我用的是WIN7系统,公司的电脑.查找了很多原因后,发现的确是由于系统主题被破解过的原因. 手工恢复风险太高.通过下面的工具就可以直接恢复.UniversalThemeP ...
- wordpress插件汉化包,和使用教程
点击下载汉化包 解压后上传到该插件的 languages 目录即可
- 教你30分钟学会XAML
1.狂妄的WPF 相对传统的Windows图形编程,需要做很多复杂的工作,引用许多不同的API.例如:WinForm(带控件表单).GDI+(2D图形).DirectX API(3D图形)以及流媒体和 ...