Python 无需显式定义要刮取的每个字段即可刮取数据

Python 无需显式定义要刮取的每个字段即可刮取数据,python,scrapy,Python,Scrapy,我想(使用Python Scrapy库)刮取一页数据,而不必定义页面上的每个字段。相反,我希望使用元素的id作为字段名来动态生成字段 起初,我认为最好的方法是有一个收集所有数据的管道,并在拥有所有数据后输出 然后我意识到我需要将数据传递到项目中的管道,但我无法定义项目,因为我不知道它需要哪些字段 解决这个问题的最佳方法是什么?更新: 旧方法不起作用,使事情变得不必要的复杂。以下是实现灵活项目的更好方法: from scrapy.item import BaseItem from scrapy.c

我想(使用Python Scrapy库)刮取一页数据,而不必定义页面上的每个字段。相反,我希望使用元素的
id
作为字段名来动态生成字段

起初,我认为最好的方法是有一个收集所有数据的管道,并在拥有所有数据后输出

然后我意识到我需要将数据传递到项目中的管道,但我无法定义项目,因为我不知道它需要哪些字段

解决这个问题的最佳方法是什么?

更新: 旧方法不起作用,使事情变得不必要的复杂。以下是实现灵活项目的更好方法:

from scrapy.item import BaseItem
from scrapy.contrib.loader import ItemLoader

class FlexibleItem(dict, BaseItem):
    pass

if __name__ == '__main__':
    item = FlexibleItem()
    loader = ItemLoader(item)

    loader.add_value('foo', 'bar')
    loader.add_value('baz', 123)
    loader.add_value('baz', 'test')
    loader.add_value(None, {'abc': 'xyz', 'foo': 555})

    print loader.load_item()

    if 'meow' not in item:
        print "it's not a cat!"
结果:

{'foo': ['bar', 555], 'baz': [123, 'test'], 'abc': ['xyz']} it's not a cat! 您可以做的是重写此
\uuuuuu setitem\uuuuuu
函数,使其不那么严格:

class FlexItem(Item):
    def __setitem__(self, key, value):
        if key not in self.fields:
            self.fields[key] = Field()

        self._values[key] = value
就这样


现在,当您向项目添加数据时,如果该项目没有定义该字段,则将添加该字段,然后数据将正常添加。

此解决方案适用于导出器(
scrapy crawl-t json-o output.json
):


编辑:更新为使用最新的Scrapy

这适用于版本0.24,还允许项目使用项目加载器:

import scrapy
from collections import defaultdict

class FlexibleItem(scrapy.Item):
    fields = defaultdict(scrapy.Field)

    def __setitem__(self, key, value):
        # all keys are supported
        self._values[key] = value

我知道我的答案很晚了,但对于那些仍然需要使用Scrapy的动态项目(当前版本为1)的人,我在Github上创建了一个存储库,包括一个示例

给你


根据您的问题历史记录,我猜这就是Python Scrapy库,对吗?对,包括相关标记就足够了吗?还是我需要更清楚一些。。啊,刚刚注意到我忘记了Python标记,抱歉:)在问题中稍微澄清一下不会有什么坏处,但我刚刚添加了Python标记,这样更清楚了。不需要任何黑客。它适用于新版本的Scrapy。这怎么可能?您的fliflible项目甚至没有foo、bar或baz文件?我无法让您的解决方案与JSON导出器(这里是Scrapy 0.21)一起工作。如我的回答中所示,对字段属性使用defaultdict似乎效果更好。有没有办法让OrderedDict起作用,以便保留动态添加的项目的顺序?
defaultdict(字段)
应该足够了。类是可调用的。
import scrapy

class FlexibleItem(scrapy.Item):
    def __setitem__(self, key, value):
        if key not in self.fields:
            self.fields[key] = scrapy.Field()
        super(FlexibleItem, self).__setitem__(key, value)
import scrapy
from collections import defaultdict

class FlexibleItem(scrapy.Item):
    fields = defaultdict(scrapy.Field)

    def __setitem__(self, key, value):
        # all keys are supported
        self._values[key] = value