赵走x博客
首页
书籍
软件
工具
古诗词
搜索
登录
精通Scrapy爬虫:25、Scrapy模拟登录
精通Scrapy爬虫:24、登录实质
精通Scrapy爬虫:23、项目实战:下载360图片
精通Scrapy爬虫:22、项目实战:爬取matplotlib例子源码文件
精通Scrapy爬虫:21、下载文件和图片:FilesPipeline和ImagesPipeline
精通Scrapy爬虫:20、项目练习
精通Scrapy爬虫:16、使用LinkExtractor提取链接
精通Scrapy爬虫:19、Exporter添加导出数据格式
精通Scrapy爬虫:18、使用Exporter导出数据
精通Scrapy爬虫:17、LinkExtractor描述提取规则
精通Scrapy爬虫:15、将数据存入MongoDB
精通Scrapy爬虫:14、过滤重复数据
精通Scrapy爬虫:13、Item Pipeline
精通Scrapy爬虫:12、Field元数据
精通Scrapy爬虫:11、Item和Field
精通Scrapy爬虫:10、CSS选择器
精通Scrapy爬虫:9、XPath
精通Scrapy爬虫:8、Response内置Selector
精通Scrapy爬虫:7、Selector对象
精通Scrapy爬虫:6、Spider开发流程
精通Scrapy爬虫:5、Request和Response对象
精通Scrapy爬虫:4、Scrapy框架结构及工作原理
精通Scrapy爬虫:3、编写第一个Scrapy爬虫
精通Scrapy爬虫:2、Scrapy简介及安装
精通Scrapy爬虫:1、网络爬虫是什么
精通Scrapy爬虫:19、Exporter添加导出数据格式
资源编号:75949
精通Scrapy
爬虫
热度:30
在某些需求下,我们想要添加新的导出数据格式,此时需要实现新的Exporter类。下面先参考Scrapy内部的Exporter类是如何实现的,然后自行实现一个Exporter。
在某些需求下,我们想要添加新的导出数据格式,此时需要实现新的Exporter类。下面先参考Scrapy内部的Exporter类是如何实现的,然后自行实现一个Exporter。 # 1、源码参考 Scrapy内部的Exporter类在scrapy.exporters模块中实现,以下是其中的代码片段: class BaseItemExporter(object): def __init__(self, **kwargs): self._configure(kwargs) def _configure(self, options, dont_fail=False): self.encoding = options.pop('encoding', None) self.fields_to_export = options.pop('fields_to_export', None) self.export_empty_fields = options.pop('export_empty_fields', False) if not dont_fail and options: raise TypeError("Unexpected options: %s" % ', '.join(options.keys())) def export_item(self, item): raise NotImplementedError def serialize_field(self, field, name, value): serializer = field.get('serializer', lambda x: x) return serializer(value) def start_exporting(self): pass def finish_exporting(self): pass def _get_serialized_fields(self, item, default_value=None, include_empty=None): """Return the fields to export as an iterable of tuples (name, serialized_value) """ if include_empty is None: include_empty = self.export_empty_fields if self.fields_to_export is None: if include_empty and not isinstance(item, dict): field_iter = six.iterkeys(item.fields) else: field_iter = six.iterkeys(item) else: if include_empty: field_iter = self.fields_to_export else: field_iter = (x for x in self.fields_to_export if x in item) for field_name in field_iter: if field_name in item: field = {} if isinstance(item, dict) else item.fields[field_name] value = self.serialize_field(field, field_name, item[field_name]) else: value = default_value yield field_name, value # json class JsonItemExporter(BaseItemExporter): 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) self.first_item = True def start_exporting(self): self.file.write(b"[\n") def finish_exporting(self): self.file.write(b"\n]") def export_item(self, item): if self.first_item: self.first_item = False else: self.file.write(b',\n') itemdict = dict(self._get_serialized_fields(item)) data = self.encoder.encode(itemdict) self.file.write(to_bytes(data, self.encoding)) # json lines class JsonLinesItemExporter(BaseItemExporter): ... # xml class XmlItemExporter(BaseItemExporter): ... # csv class CsvItemExporter(BaseItemExporter): ... ... 其中的每一个Exporter都是BaseItemExporter的一个子类,BaseItemExporter定义了一些抽象接口待子类实现: ● export_item(self, item) 负责导出爬取到的每一项数据,参数item为一项爬取到的数据,每个子类必须实现该方法。 ● start_exporting(self) 在导出开始时被调用,可在该方法中执行某些初始化工作。 ● finish_exporting(self) 在导出完成时被调用,可在该方法中执行某些清理工作。 以JsonItemExporter为例,其实现非常简单: ● 为了使最终导出结果是一个json中的列表,在start_exporting和finish_exporting方法中分别向文件写入b"[\n, b"\n]"。 ● 在export_item方法中,调用self.encoder.encode方法将一项数据转换成json串(具体细节不再赘述),然后写入文件。 # 2、实现Exporter 接下来,我们参照JsonItemExporter的源码,在第1章example项目中实现一个能将数据以Excel格式导出的Exporter。 在项目中创建一个my_exporters.py(与settings.py同级目录),在其中实现ExcelItemExporter,代码如下: from scrapy.exporters import BaseItemExporter import xlwt class ExcelItemExporter(BaseItemExporter): def __init__(self, file, **kwargs): self._configure(kwargs) self.file = file self.wbook = xlwt.Workbook() self.wsheet = self.wbook.add_sheet('scrapy') self.row = 0 def finish_exporting(self): self.wbook.save(self.file) def export_item(self, item): fields = self._get_serialized_fields(item) for col, v in enumerate(x for _, x in fields): self.wsheet.write(self.row, col, v) self.row += 1 解释上述代码如下: ● 这里使用第三方库xlwt将数据写入Excel文件。 ● 在构造器方法中创建Workbook对象和Worksheet对象,并初始化用来记录写入行坐标的self.row。 ● 在export_item方法中调用基类的_get_serialized_fields方法,获得item所有字段的迭代器,然后调用self.wsheet.write方法将各字段写入Excel表格。 ● finish_exporting方法在所有数据都被写入Excel表格后被调用,在该方法中调用self.wbook.save方法将Excel表格写入Excel文件。 完成ExcelItemExporter后,在配置文件settings.py中添加如下代码: FEED_EXPORTERS = {'excel': 'example.my_exporters.ExcelItemExporter'} 现在,可以使用ExcelItemExporter导出数据了,以-t excel为参数重新运行爬虫: $ scrapy crawl books -t excel -o books.xls 图7-1所示为爬取完成后在Excel文件中观察到的结果。 ![bs64](https://img.handsomemark.com/2019/10/19/bccc4cfa-f1c5-11e9-988c-acde48001122.png) 图7-1 如上所示,我们成功地使用ExcelItemExporter将爬取到的数据存入了Excel文件中。 # 本章小结 本章学习了在Scrapy中如何使用Exporter将爬取到的数据导出到文件,首先介绍使用命令行参数以及配置文件指定如何导出数据的方法,然后参考Scrapy内部Exporter的源码实现了一个能将数据导出到Excel文件的Exporter。