Author | Blog | |
---|---|---|
冬酒暖阳 | mailto:[email protected] | 博客:www.lifepoem.cn |
在 Scrapy 中保存 json 文件有以下 3 种方式:
但,Scrapy 框架提供的这两个 json 导出模块,均 存在各自的问题 :
JsonItemExporter
必须先将爬虫爬取下来的 所有数据存放在内存 中,待爬虫完成后,再一次性写入文件。
这种方式,可以输出标准的 json 格式文件,但是如果数据量巨大,会 大量占用内存 。
JsonLinesItemExporter
这种方式,每次拿到数据都直接写入文件,占用内存少,但是输出的结果 并不是标准的 Json 格式文件 ,无法通过 Json 将文件内容解析出来。
于是,下面首先介绍,第一种方式,直接创建并将数据写入 json 文件,
在 Scrapy 框架的 pipeline 写入如下内容
import os
import codecs
import json
class SpiderPipeline(object):
# 构造方法(初始化对象时执行的方法)
def __init__(self):
# 必须使用 w+ 模式打开文件,以便后续进行 读写操作(w+模式,意味既可读,亦可写)
# 注意:此处打开文件使用的不是 python 的 open 方法,而是 codecs 中的 open 方法
self.json_file = codecs.open('data.json', 'w+', encoding='UTF-8')
# 爬虫开始时执行的方法
def open_spider(self, spider):
# 在爬虫开始时,首先写入一个 '[' 符号,构造一个 json 数组
# 为使得 Json 文件具有更高的易读性,我们辅助输出了 '\n'(换行符)
self.json_file.write('[\n')
# 爬虫 pipeline 接收到 Scrapy 引擎发来的 item 数据时,执行的方法
def process_item(self, item, spider):
# 将 item 转换为 字典类型,并编码为 json 字符串,写入文件
# 为使得 Json 文件具有更高的易读性,我们辅助输出了 '\t'(制表符) 与 '\n'(换行符)
item_json = json.dumps(dict(item), ensure_ascii=False)
self.json_file.write('\t' + item_json + ',\n')
return item
# 爬虫结束时执行的方法
def close_spider(self, spider):
# 在结束后,需要对 process_item 最后一次执行输出的 “逗号” 去除
# 当前文件指针处于文件尾,我们需要首先使用 SEEK 方法,定位文件尾前的两个字符(一个','(逗号), 一个'\n'(换行符))的位置
self.json_file.seek(-2, os.SEEK_END)
# 使用 truncate() 方法,将后面的数据清空
self.json_file.truncate()
# 重新输出'\n',并输入']',与 open_spider(self, spider) 时输出的 '[',构成一个完整的数组格式
self.json_file.write('\n]')
# 关闭文件
self.json_file.close()
输出示例
[
{"title": "用户拒绝授权小程序使用通讯地址API的问题和解决方法", "author_nickName": "KOSS", "content": "小程序中正确使用通讯地址这个开发接口的流程:思路:"},
{"title": "房产小程序开发", "author_nickName": "Right Here Waiting", "content": "房产小程序:任何关于楼盘价格问题、户型问题、周边设施问题都可以小程序上直接沟通。房产小程序可以很好的帮助哪些懒人解决看房问题,楼盘价格及周边设施都可以详细的展示,用户也可以直接在小程序上面预约,然后在实地看房。"}
]
在 Scrapy 框架的 pipeline 写入如下内容
# 导入 JsonItemExporter
from scrapy.exporters import JsonItemExporter
class SpiderPipeline(object):
# 构造方法(初始化对象时执行的方法)
def __init__(self):
# 使用 'wb' (二进制写模式)模式打开文件
self.json_file = open('data.json', 'wb')
# 构建 JsonItemExporter 对象,设定不使用 ASCII 编码,并指定编码格式为 'UTF-8'
self.json_exporter = JsonItemExporter(self.json_file, ensure_ascii=False, encoding='UTF-8')
# 声明 exporting 过程 开始,这一句也可以放在 open_spider() 方法中执行。
self.json_exporter.start_exporting()
# 爬虫 pipeline 接收到 Scrapy 引擎发来的 item 数据时,执行的方法
def process_item(self, item, spider):
# 将 item 存储到内存中
self.json_exporter.export_item(item)
return item
def close_spider(self, spider):
# 声明 exporting 过程 结束,结束后,JsonItemExporter 会将收集存放在内存中的所有数据统一写入文件中
self.json_exporter.finish_exporting()
# 关闭文件
self.json_file.close()
输出示例
[{"title": "用户拒绝授权小程序使用通讯地址API的问题和解决方法", "author_nickName": "KOSS", "content": "小程序中正确使用通讯地址这个开发接口的流程:思路:"},{"title": "房产小程序开发", "author_nickName": "Right Here Waiting", "content": "房产小程序:任何关于楼盘价格问题、户型问题、周边设施问题都可以小程序上直接沟通。房产小程序可以很好的帮助哪些懒人解决看房问题,楼盘价格及周边设施都可以详细的展示,用户也可以直接在小程序上面预约,然后在实地看房。"}]
在 Scrapy 框架的 pipeline 写入如下内容
# 导入 JsonLinesItemExporter
from scrapy.exporters import JsonLinesItemExporter
class SpiderPipeline(object):
# 构造方法(初始化对象时执行的方法)
def __init__(self):
# 使用 'wb' (二进制写模式)模式打开文件
self.json_file = open('data.json', 'wb')
# 构建 JsonLinesItemExporter 对象,设定不使用 ASCII 编码,并指定编码格式为 'UTF-8'
self.json_exporter = JsonLinesItemExporter(self.json_file, ensure_ascii=False, encoding='UTF-8')
# 声明 exporting 过程 开始,这一句也可以放在 open_spider() 方法中执行。
self.json_exporter.start_exporting()
# 爬虫 pipeline 接收到 Scrapy 引擎发来的 item 数据时,执行的方法
def process_item(self, item, spider):
# 将 item 直接写入文件中
self.json_exporter.export_item(item)
return item
def close_spider(self, spider):
# 声明 exporting 过程 结束,结束后,JsonItemExporter 会将收集存放在内存中的所有数据统一写入文件中
self.json_exporter.finish_exporting()
# 关闭文件
self.json_file.close()
输出示例
{"title": "用户拒绝授权小程序使用通讯地址API的问题和解决方法", "author_nickName": "KOSS", "content": "小程序中正确使用通讯地址这个开发接口的流程:思路:"}
{"title": "房产小程序开发", "author_nickName": "Right Here Waiting", "content": "房产小程序:任何关于楼盘价格问题、户型问题、周边设施问题都可以小程序上直接沟通。房产小程序可以很好的帮助哪些懒人解决看房问题,楼盘价格及周边设施都可以详细的展示,用户也可以直接在小程序上面预约,然后在实地看房。"}
序号 | 方式 | 内存占用情况 | 是否为标准 json 格式 | 易读性 |
---|---|---|---|---|
1 | 直接创建并写入文件 | 低 | 是 | 高 |
2 | JsonItemExporter | 高 | 是 | 低 |
3 | JsonLinesItemExporter | 低 | 否 | 较低 |