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