9

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

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

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

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

4

4 回答 4

17

更新:

旧方法不适用于项目加载器,并且不必要地使事情复杂化。这是实现灵活项目的更好方法:

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']}
它不是猫!

旧解决方案:

好的,我找到了解决方案。这有点“黑客”,但它有效..

Scrapy Item 将字段名称存储在一个名为 的字典中fields。向 Item 添加数据时,它会检查该字段是否存在,如果不存在则抛出错误:

def __setitem__(self, key, value):
    if key in self.fields:
        self._values[key] = value
    else:
        raise KeyError("%s does not support field: %s" %\
              (self.__class__.__name__, key))

您可以做的是覆盖此__setitem__函数以使其不那么严格:

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

        self._values[key] = value

你去吧。

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

于 2011-02-22T11:13:46.900 回答
4

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

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)

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

于 2014-06-23T01:12:17.833 回答
3

这适用于 0.24 版本,并且还允许 Items 与 Item Loaders 一起使用:

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
于 2015-05-22T22:32:36.867 回答
1

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

干得好

https://github.com/WilliamKinaan/ScrapyDynamicItems

于 2015-08-11T14:36:56.730 回答