我正在尝试基于JsonLinesItemExporter创建一个自定义的Scrapy Item Exporter,以便我可以稍微更改它产生的结构。
我已经在http://doc.scrapy.org/en/latest/topics/exporters.html上阅读了文档,但未说明如何创建自定义导出器,在何处存储或如何将其链接到管道。
。
我已经确定了如何对Feed导出程序进行自定义,但这不符合我的要求,因为我想从管道中调用此导出程序。
这是我想出的代码,它存储在项目根目录下的文件中 exporters.py
from scrapy.contrib.exporter import JsonLinesItemExporter
class FanItemExporter(JsonLinesItemExporter):
def __init__(self, file, **kwargs):
self._configure(kwargs, dont_fail=True)
self.file = file
self.encoder = ScrapyJSONEncoder(**kwargs)
self.first_item = True
def start_exporting(self):
self.file.write("""{
'product': [""")
def finish_exporting(self):
self.file.write("]}")
def export_item(self, item):
if self.first_item:
self.first_item = False
else:
self.file.write(',\n')
itemdict = dict(self._get_serialized_fields(item))
self.file.write(self.encoder.encode(itemdict))
我只是尝试使用FanItemExporter从我的管道中调用此方法,并尝试导入的变体,但不会产生任何结果。
确实,Scrapy文档没有明确说明放置项目导出器的位置。要使用项目导出器,请按照以下步骤操作。
pipeline.py
项目目录中。它可以是预定义的Item Exporter(例如XmlItemExporter
),也可以是用户定义的(如FanItemExporter
问题中定义的)pipeline.py
。在此类中实例化导入的Item Exporter。详细信息将在答案的后面部分进行解释。settings.py
文件中注册该管道类。以下是每个步骤的详细说明。该问题的解决方案包含在每个步骤中。
如果使用预定义的Item Exporter类,则从scrapy.exporters
模块导入它。
例如: from scrapy.exporters import XmlItemExporter
如果需要自定义导出器,请在文件中定义一个自定义类。我建议将类放在exporters.py
文件中。放置在项目文件夹(这个文件settings.py
,items.py
驻留)。
创建新的子类时,导入始终是一个好主意BaseItemExporter
。如果我们打算完全更改功能,那将是适当的。但是,在这个问题上,大多数功能都接近JsonLinesItemExporter
。
因此,我将附加同一ItemExporter的两个版本。一个版本扩展了BaseItemExporter
类,另一个版本扩展了JsonLinesItemExporter
类
版本1 :扩展BaseItemExporter
既然BaseItemExporter
是父类,start_exporting()
,finish_exporting()
,export_item()
必须overrided,以满足我们的需要。
from scrapy.exporters import BaseItemExporter
from scrapy.utils.serialize import ScrapyJSONEncoder
from scrapy.utils.python import to_bytes
class FanItemExporter(BaseItemExporter):
def __init__(self, file, **kwargs):
self._configure(kwargs, dont_fail=True)
self.file = file
self.encoder = ScrapyJSONEncoder(**kwargs)
self.first_item = True
def start_exporting(self):
self.file.write(b'{\'product\': [')
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))
self.file.write(to_bytes(self.encoder.encode(itemdict)))
第2版 :扩展JsonLinesItemExporter
JsonLinesItemExporter
提供与export_item()
方法完全相同的实现。因此,仅start_exporting()
和finish_exporting()
方法被覆盖。
JsonLinesItemExporter
在文件夹中可以看到执行python_dir\pkgs\scrapy-1.1.0-py35_0\Lib\site- packages\scrapy\exporters.py
from scrapy.exporters import JsonItemExporter
class FanItemExporter(JsonItemExporter):
def __init__(self, file, **kwargs):
# To initialize the object using JsonItemExporter's constructor
super().__init__(file)
def start_exporting(self):
self.file.write(b'{\'product\': [')
def finish_exporting(self):
self.file.write(b'\n]}')
注意 :将数据写入文件时,请务必注意,标准的Item
Exporter类需要二进制文件。因此,必须以二进制模式(b
)打开文件。由于相同的原因,write()
两个版本中的方法都将写入bytes
文件。
创建一个Item Pipeline类。
from project_name.exporters import FanItemExporter
class FanExportPipeline(object):
def __init__(self, file_name):
# Storing output filename
self.file_name = file_name
# Creating a file handle and setting it to None
self.file_handle = None
@classmethod
def from_crawler(cls, crawler):
# getting the value of FILE_NAME field from settings.py
output_file_name = crawler.settings.get('FILE_NAME')
# cls() calls FanExportPipeline's constructor
# Returning a FanExportPipeline object
return cls(output_file_name)
def open_spider(self, spider):
print('Custom export opened')
# Opening file in binary-write mode
file = open(self.file_name, 'wb')
self.file_handle = file
# Creating a FanItemExporter object and initiating export
self.exporter = FanItemExporter(file)
self.exporter.start_exporting()
def close_spider(self, spider):
print('Custom Exporter closed')
# Ending the export to file from FanItemExport object
self.exporter.finish_exporting()
# Closing the opened output file
self.file_handle.close()
def process_item(self, item, spider):
# passing the item to FanItemExporter object for expoting to file
self.exporter.export_item(item)
return item
由于定义了“项目导出管道”,因此将该管道注册到settings.py
文件中。还将字段添加FILE_NAME
到settings.py
文件。该字段包含输出文件的文件名。
将以下行添加到settings.py
文件。
FILE_NAME = 'path/outputfile.ext'
ITEM_PIPELINES = {
'project_name.pipelines.FanExportPipeline' : 600,
}
如果ITEM_PIPELINES
已经取消注释,则将以下行添加到ITEM_PIPELINES
字典中。
'project_name.pipelines.FanExportPipeline' : 600,
这是创建自定义项目导出管道的一种方法。
问题内容: 我正在http://www.cafeaulait.org/javafaq.html上阅读#6.10项,然后我开始怀疑大型企业如何创建自己的JVM实现。一个人会尝试(或可行)实验性的东西吗? 问题答案: 从技术上讲,创建该新JVM所需的所有信息都是该语言和目标平台的公共规范。即使字节码解释在很大程度上相同,JVM还是需要根据其是要在台式机还是手机上运行而有所不同。 一些开始寻找信息的地方
本文向大家介绍Android如何创建自定义ActionBar,包括了Android如何创建自定义ActionBar的使用技巧和注意事项,需要的朋友参考一下 当多个界面都有很多相似部分时,可以考虑创建一个功能较全的模板。而在需要时,可以通过引用模板来实现自己想要实现的功能。比如适配器 Adapter,当很多的适配器都差不多时,就可以通过打造一个通用的适配器来实现。本例中主要是如何创建自定义的 Act
标题说明了一切。我想创建一个自定义的prestashop页面,但我不知道如何创建。我真正想做的是:创建一个按钮,打开一个自定义页面。我在网上找不到任何有用的东西,所以我来这里寻求帮助。有人能告诉我怎么做吗?
问题内容: 如何创建自定义javadoc标记,例如@pre / @post?我找到了一些解释它的链接,但是我还没有运气。这些是一些链接: http://www.developer.com/java/other/article.php/3085991/Javadoc- Programming.html http://java.sun.com/j2se/1.5.0/docs/tooldocs/wind
我正在尝试在log4j2中编写自己的RewritePolicy。文件指出: 然而,我不知道如何将它注入我的配置文件。我如何使它在运行时工作?
问题内容: 我在JFrame上有一个按钮,当单击该按钮时,我希望对话框弹出并带有多个文本区域供用户输入。我一直在四处寻找解决方法,但是我一直感到困惑。有人可以帮忙吗? 问题答案: 如果您不需要太多自定义行为,则JOptionPane可以节省大量时间。它负责OK / Cancel选项的放置和本地化,并且是一种无需定义自己的类即可显示自定义对话框的快捷方法。大多数情况下,JOptionPane中的“