序言
在 Scrapy 中保存 json 文件有以下 3 种方式:
- 直接创建并写入 json 文件,将数据写入其中
- 使用 Scrapy.exporters 中自带的 JsonItemExporter进行导出操作
- 使用 Scrapy.exporters 中自带的 JsonLinesItemExporter进行导出操作
但,Scrapy 框架提供的这两个 json 导出模块,均 存在各自的问题 :
-
JsonItemExporter
必须先将爬虫爬取下来的 所有数据存放在内存 中,待爬虫完成后,再一次性写入文件。
这种方式,可以输出标准的 json 格式文件,但是如果数据量巨大,会 大量占用内存 。
-
JsonLinesItemExporter
这种方式,每次拿到数据都直接写入文件,占用内存少,但是输出的结果 并不是标准的 Json 格式文件 ,无法通过 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": "房产小程序:任何关于楼盘价格问题、户型问题、周边设施问题都可以小程序上直接沟通。房产小程序可以很好的帮助哪些懒人解决看房问题,楼盘价格及周边设施都可以详细的展示,用户也可以直接在小程序上面预约,然后在实地看房。"} ]
二、使用 JsonItemExporter 写入 Json 文件
-
在 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": "房产小程序:任何关于楼盘价格问题、户型问题、周边设施问题都可以小程序上直接沟通。房产小程序可以很好的帮助哪些懒人解决看房问题,楼盘价格及周边设施都可以详细的展示,用户也可以直接在小程序上面预约,然后在实地看房。"}]
二、使用 JsonLinesItemExporter 写入 json 文件
-
在 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 | 低 | 否 | 较低 |