scrapy 序列化写入器
Scrapy支持多种序列化格式(serialization format)及存储方式(storage backends)。
如果你是想单纯的将数据输出或存入文件,那直接可以用Scrapy提供的现成类。
Item Exporters
为了使用 Item Exporter,你必须对 Item Exporter 及其参数 (args) 实例化。每个 Item Exporter 需要不同的参数 。在实例化了 exporter 之后,你必须:
- 调用方法
start_exporting()
以标识过程的开始。 - 对要导出的每个item调用
export_item()
方法。 - 最后调用
finish_exporting()
表示过程的结束
例如:
from scrapy.exporters import JsonItemExporter
class TestPipeline(object):
def open_spider(self, spider):
self.fp = open("data.json", 'wb') # 打开文件 ,要以wb的形式打开
self.exporter = JsonItemExporter(self.fp, ensure_ascii=False, encoding='utf-8') # 实例化写入器
self.exporter.start_exporting() # 开启写入器
def process_item(self, item, spider):
self.exporter.export_item(item) # 写入一条数据
return item
def close_spider(self, spider):
self.exporter.finish_exporting() # 关闭写入器
self.fp.close() # 关闭文件
序列化方式(Serialization formats)
导入方式:from scrapy.exporters import XXXX
-
JSON(常用)
-
JsonItemExporter
-
-
JSON lines(常用)
-
JsonLinesItemExporter
-
-
CSV
-
CsvItemExporter
-
-
XML
-
XmlItemExporter
-
关于JsonItemExporter和JsonLinesItemExporter
源码如下:
class JsonLinesItemExporter(BaseItemExporter):
#指定了输出文件,以及BaseItemExporter所需要的属性。
#ScrapyJSONEncoder提供了将字典类型的数据转换为Json格式数据的方法
def __init__(self, file, **kwargs):
self._configure(kwargs, dont_fail=True)
self.file = file
kwargs.setdefault('ensure_ascii', not self.encoding)
self.encoder = ScrapyJSONEncoder(**kwargs)
#将转化为字典类型的item写入指定的文件中,每条数据就是一个字典
def export_item(self, item):
itemdict = dict(self._get_serialized_fields(item))
data = self.encoder.encode(itemdict) + '\n'
self.file.write(to_bytes(data, self.encoding))
class JsonItemExporter(BaseItemExporter):
#创建Json格式的Exporter
#与JsonLinesItemExporter不同的是该类会把所有的item封装成数组写入文件,
#整个json文件就是一个列表。
def __init__(self, file, **kwargs):
self._configure(kwargs, dont_fail=True)
self.file = file
# there is a small difference between the behaviour or JsonItemExporter.indent
# and ScrapyJSONEncoder.indent. ScrapyJSONEncoder.indent=None is needed to prevent
# the addition of newlines everywhere
json_indent = self.indent if self.indent is not None and self.indent > 0 else None
kwargs.setdefault('indent', json_indent)
kwargs.setdefault('ensure_ascii', not self.encoding)
self.encoder = ScrapyJSONEncoder(**kwargs)
self.first_item = True
def _beautify_newline(self):
if self.indent is not None:
self.file.write(b'\n')
def start_exporting(self):
self.file.write(b"[")
self._beautify_newline()
def finish_exporting(self):
self._beautify_newline()
self.file.write(b"]")
def export_item(self, item):
if self.first_item:
self.first_item = False
else:
self.file.write(b',') # 添加逗号
self._beautify_newline() # 添加\n换行
itemdict = dict(self._get_serialized_fields(item))
data = self.encoder.encode(itemdict)
self.file.write(to_bytes(data, self.encoding))
大致概括下:
(要用二进制的方式来写)
首先我们从名字里大致可以看出来了,两者区别 Lines 也就是行的意思.
JsonLinesItemExporter每一条数据就是一个字典,一个字典一行,没有逗号隔开,这个文件不是一个特别规范的json文件
JsonItemExporter在打开写入器和关闭写入器的时候分别写入看[
和]
并且每一条数据都有逗号和换行分隔,整个文件是一个字典列表