为 XML 输出序列化一个 Scrapy 项目
Serialize a Scrapy Item for XML output
我是 scrapy 的新手,我正在寻找一种方法来序列化我的 Scrapy 项目,以便能够将属性添加到我的 XML 输出中,让它看起来像这样:
<field name='example'> i have some data scraped here </field>
例如,我正在尝试找到一种添加 "name" 属性的方法。我知道可以通过覆盖 XmlItemExporter class 中的 export_item() 方法来实现,但到目前为止我运气不好。到目前为止,我的 XmlExportPipeline 看起来像这样:
from scrapy.exporters import XmlItemExporter
class XmlExportPipeline(object):
def open_spider(self, spider):
self.file = open('%s_products.xml' % spider.name, 'w+b')
self.exporter = XmlItemExporter(self.file, item_element='field', root_element='items')
self.exporter.start_exporting()
def close_spider(self, spider):
self.exporter.finish_exporting()
self.file.close()
def process_item(self, item, spider):
self.exporter.export_item(item)
return item
此外,到目前为止,我的所有数据都是我项目的不同字段,但理想情况下,我会将其中一些字段作为其他字段的属性。
您只需更改 XMLItemExporter
并创建自定义的。在您的项目中创建 exporters.py
并添加以下代码
import six
from scrapy.exporters import XmlItemExporter
from scrapy.utils.python import is_listlike
class MyXmlExportPipeline(XmlItemExporter):
def _export_xml_field(self, name, serialized_value, depth):
self._beautify_indent(depth=depth)
self.xg.startElement("field", {"name": name})
if hasattr(serialized_value, 'items'):
self._beautify_newline()
for subname, value in serialized_value.items():
self._export_xml_field(subname, value, depth=depth+1)
self._beautify_indent(depth=depth)
elif is_listlike(serialized_value):
self._beautify_newline()
for value in serialized_value:
self._export_xml_field('value', value, depth=depth+1)
self._beautify_indent(depth=depth)
elif isinstance(serialized_value, six.text_type):
self._xg_characters(serialized_value)
else:
self._xg_characters(str(serialized_value))
self.xg.endElement("field")
self._beautify_newline()
我所做的仅有的两项更改是更改
self.xg.startElement(name, {})
....
self.xg.endElement(name)
从原始导出到
self.xg.startElement("field", {"name" :name})
....
self.xg.endElement("field")
然后更新您的 settings.py
并添加
FEED_EXPORTERS = {
'xml': 'so.exporters.MyXmlExportPipeline'
}
然后我创建了一个简单的抓取工具来测试输出
class XMLExport(Spider):
name = "xml"
start_urls = ["http://www.tarunlalwani.com"]
def parse(self, response):
yield {"first_name": "tarun", "last_name": "lalwani"}
pass
并使用 scrapy crawl xml -o test.xml
进行测试,输出 XML 文件为
<?xml version="1.0" encoding="utf-8"?>
<items>
<item><field name="first_name">tarun</field><field name="last_name">lalwani</field></item>
</items>
我是 scrapy 的新手,我正在寻找一种方法来序列化我的 Scrapy 项目,以便能够将属性添加到我的 XML 输出中,让它看起来像这样:
<field name='example'> i have some data scraped here </field>
例如,我正在尝试找到一种添加 "name" 属性的方法。我知道可以通过覆盖 XmlItemExporter class 中的 export_item() 方法来实现,但到目前为止我运气不好。到目前为止,我的 XmlExportPipeline 看起来像这样:
from scrapy.exporters import XmlItemExporter
class XmlExportPipeline(object):
def open_spider(self, spider):
self.file = open('%s_products.xml' % spider.name, 'w+b')
self.exporter = XmlItemExporter(self.file, item_element='field', root_element='items')
self.exporter.start_exporting()
def close_spider(self, spider):
self.exporter.finish_exporting()
self.file.close()
def process_item(self, item, spider):
self.exporter.export_item(item)
return item
此外,到目前为止,我的所有数据都是我项目的不同字段,但理想情况下,我会将其中一些字段作为其他字段的属性。
您只需更改 XMLItemExporter
并创建自定义的。在您的项目中创建 exporters.py
并添加以下代码
import six
from scrapy.exporters import XmlItemExporter
from scrapy.utils.python import is_listlike
class MyXmlExportPipeline(XmlItemExporter):
def _export_xml_field(self, name, serialized_value, depth):
self._beautify_indent(depth=depth)
self.xg.startElement("field", {"name": name})
if hasattr(serialized_value, 'items'):
self._beautify_newline()
for subname, value in serialized_value.items():
self._export_xml_field(subname, value, depth=depth+1)
self._beautify_indent(depth=depth)
elif is_listlike(serialized_value):
self._beautify_newline()
for value in serialized_value:
self._export_xml_field('value', value, depth=depth+1)
self._beautify_indent(depth=depth)
elif isinstance(serialized_value, six.text_type):
self._xg_characters(serialized_value)
else:
self._xg_characters(str(serialized_value))
self.xg.endElement("field")
self._beautify_newline()
我所做的仅有的两项更改是更改
self.xg.startElement(name, {})
....
self.xg.endElement(name)
从原始导出到
self.xg.startElement("field", {"name" :name})
....
self.xg.endElement("field")
然后更新您的 settings.py
并添加
FEED_EXPORTERS = {
'xml': 'so.exporters.MyXmlExportPipeline'
}
然后我创建了一个简单的抓取工具来测试输出
class XMLExport(Spider):
name = "xml"
start_urls = ["http://www.tarunlalwani.com"]
def parse(self, response):
yield {"first_name": "tarun", "last_name": "lalwani"}
pass
并使用 scrapy crawl xml -o test.xml
进行测试,输出 XML 文件为
<?xml version="1.0" encoding="utf-8"?>
<items>
<item><field name="first_name">tarun</field><field name="last_name">lalwani</field></item>
</items>