我正在尝试创建一个自定义xml Feed,它将包含蜘蛛抓取的项目,以及存储在spider定义中的一些其他高级信息。输出应存储在S3上。
所需的输出如下所示:
<xml>
<title>my title defined in the spider</title>
<description>The description from the spider</description>
<items>
<item>...</item>
</items>
</xml>
为此,我定义了一个自定义导出器,它能够在本地导出所需的输出文件。
spider.py:
class DmozSpider(scrapy.Spider):
name = 'dmoz'
allowed_domains = ['dmoz.org']
start_urls = ['http://www.dmoz.org/Computers/']
title = 'The DMOZ super feed'
def parse(self, response):
...
yield item
exporters.py:
from scrapy.conf import settings
class CustomItemExporter(XmlItemExporter):
def __init__(self, *args, **kwargs):
self.title = kwargs.pop('title', 'no title found')
self.link = settings.get('FEED_URI', 'localhost')
super(CustomItemExporter, self).__init__(*args, **kwargs)
def start_exporting(self):
...
self._export_xml_field('title', self.title)
...
settings.py:
FEED_URI = 's3://bucket-name/%(name)s.xml'
FEED_EXPORTERS = {
'custom': 'my.exporters.CustomItemExporter',
}
我能够通过运行以下命令来运行整个事件并在s3上获得输出:
scrapy crawl dmoz -t custom
或者,如果我想在本地导出json:scrapy crawl -o dmoz.json dmoz
但是在这一点上,我无法检索蜘蛛标题以将其放入输出文件中。
我尝试实现一个自定义管道,它在本地输出数据(以下是众多例子):
pipelines.py:
class CustomExportPipeline(object):
def __init__(self):
self.files = {}
@classmethod
def from_crawler(cls, crawler):
pipeline = cls()
crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
return pipeline
def spider_opened(self, spider):
file = open('%s_feed.xml' % spider.name, 'w+b')
self.files[spider] = file
self.exporter = CustomItemExporter(
file,
title = spider.title),
)
self.exporter.start_exporting()
问题是,文件存储在本地,这会使Feedexport.py中定义的FeedExporter逻辑短路,处理所有不同的存储。 管道中没有来自FeedExporter的信息,我想重用所有逻辑而不重复代码。我错过了什么吗?谢谢你的帮助。
答案 0 :(得分:1)
这是我的解决方案:
覆盖scrapy的FeedExporter
<强>的myproject / feedexport.py:强>
from scrapy.extensions.feedexport import FeedExporter as _FeedExporter
from scrapy.extensions.feedexport import SpiderSlot
class FeedExporter(_FeedExporter):
def open_spider(self, spider):
uri = self.urifmt % self._get_uri_params(spider)
storage = self._get_storage(uri)
file = storage.open(spider)
extra = {
# my extra settings
}
exporter = self._get_exporter(file, fields_to_export=self.export_fields, extra=extra)
exporter.start_exporting()
self.slot = SpiderSlot(file, exporter, storage, uri)
我想要做的只是将这些额外的设置传递给导出器,但是它的构建方式,除了覆盖之外别无选择。 为了同时支持其他scrapy导出格式,我必须考虑在某些scrapy导出器中将dont_fail设置覆盖为True以防止它们失败
用新的替换scrapy的Feed导出器
<强>的myproject / feedexport.py:强>
EXTENSIONS = {
'scrapy.extensions.feedexport.FeedExporter': None,
'myproject.feedexport.FeedExporter': 0,
}
...或者2个Feed导出器会同时运行