scrapy框架持久化存储
摘要:
基于终端指令的持久化存储
- 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作。
- 返回值可以是列表,但是需要列表里面套字典
执行输出指定格式进行存储:将爬取到的数据写入不同格式的文件中进行存储 scrapy crawl 爬虫名称 -o xxx.json scrapy crawl 爬虫名称 -o xxx.xml scrapy crawl 爬虫名称 -o xxx.csv
# -*- coding: utf-8 -*- import scrapy class FirstSpider(scrapy.Spider): #爬虫文件的名称,就是爬虫文件的一个唯一标识 name = 'first' #允许的域名,一般情况下会进行注释 # allowed_domains = ['www.yuyu.com'] #起始url列表,只要在这个列表中的URL都会被scrapy这个框架自动的发起请求发送 start_urls = ['https://www.qiushibaike.com/text/'] #parse方法会进行数据的解析 def parse(self, response): div_list = response.xpath('//div[@id="content-left"]/div') names=[] for div in div_list: #特性:xpath 返回的列表元素一定是Selector对象,使用extract()就可以获取Selector中data的数据 # author=div.xpath('./div[1]/a[2]/h2/text()')[0].extract() #第一种方式 author=div.xpath('./div[1]/a[2]/h2/text()').extract_first() #第二种方式 #在基于终端指令进行持久化存储的时候必须将解析到的数据封装到字典中 dic ={ "name":author } names.append(dic) return names
基于管道的持久化存储
scrapy框架中已经为我们专门集成好了高效、便捷的持久化操作功能,我们直接使用即可。要想使用scrapy的持久化操作功能,我们首先来认识如下两个文件:
items.py:数据结构模板文件。定义数据属性。
pipelines.py:管道文件。接收数据(items),进行持久化操作。
持久化流程:
1.数据解析 2.封装item类
3.实例化item类型的对象
4.将解析到的数据依次存储封装到item类型的对象中
5.使用yield关键字将items对象提交给pipelines管道进行持久化操作。 3.在管道文件中的process_item方法中接收爬虫文件提交过来的item对象,然后编写持久化存储的代码将item对象中存储的数据进行持久化存储 4.settings.py配置文件中开启管道
爬取文件:
# -*- coding: utf-8 -*- import scrapy from ..items import XiaohuawangItem class XiaohuaSpider(scrapy.Spider): name = 'xiaohua' # allowed_domains = ['www.xiaohua.com'] #第一页内容 start_urls = ['http://www.521609.com/daxuemeinv/'] # 生成一个通用的url模板 爬取前5页 url = 'http://www.521609.com/daxuemeinv/list8{}.html' page_num = 1 def parse(self, response): li_list = response.xpath('//div[@class="index_img list_center"]/ul/li') for li in li_list: img_url = "http://www.521609.com" + li.xpath("./a[1]/img/@src").extract_first() name = li.xpath("./a[2]/text()|./a[2]/b/text()").extract_first() # 实例化一个item类型的对象 item = XiaohuawangItem() item["name"] = name item["img_url"] = img_url # item提交给管道 yield item #爬取第2页-第5页 if self.page_num <= 5: self.page_num += 1 new_url = self.url.format(self.page_num) # 需要将爬取回来的响应对象交给self.parse进行解析 yield scrapy.Request(url=new_url,callback=self.parse)
items文件:
import scrapy class XiaohuawangItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() name = scrapy.Field() img_url = 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 XiaohuawangPipeline(object): f = None def open_spider(self, spider): print('开始爬虫!') self.f = open('./xiaohua.txt', 'w', encoding='utf-8') # 作用:实现持久化存储的操作 # 该方法的item参数就可以接收爬虫文件提交过来的item对象 # 该方法每接收一个item就会被调用一次(调用多次) def process_item(self, item, spider): name = item['name'] img_url = item['img_url'] self.f.write(name + ':' + img_url + '\n') # 返回值的作用:就是将item传递给下一个即将被执行的管道类 return item def close_spider(self, spider): print('结束爬虫!') self.f.close() 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='text77') print(self.conn) def process_item(self, item, spider): self.cursor = self.conn.cursor() try: self.cursor.execute('insert into xiaohua values ("%s","%s")' % (item['name'], item['img_url'])) self.conn.commit() except Exception as e: print(e) self.conn.rollback() return item def close_spider(self, spider): self.cursor.close() self.conn.close() class RedisPipeline(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): # dic = { # 'name':item['name'], # 'img_url':item['img_url'] # } ##注意有时候Redis中存储是字符串类型,有时候是字典类型 s = item['name']+":"+item['img_url'] self.conn.lpush('xiaohua',s) return item def close_spider(self, spider): pass
配置文件:settings.py
下列结构为字典,字典中的键值表示的是即将被启用执行的管道文件和其执行的优先级
######300表示为优先级,值越小优先级越高
ITEM_PIPELINES = { # 'xiaohuawang.pipelines.XiaohuawangPipeline': 300, # 'xiaohuawang.pipelines.MysqlPipeline': 301, 'xiaohuawang.pipelines.RedisPipeline': 302, }
存储结果: