アップデート:
古い方法はアイテムローダーでは機能せず、不必要に物事を複雑にしていました。柔軟なアイテムを実現するためのより良い方法は次のとおりです。
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は、フィールド名を。と呼ばれるdictに格納しますfields
。アイテムにデータを追加すると、フィールドが存在するかどうかがチェックされ、存在しない場合はスローされてエラーが発生します。
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
そして、あなたは行きます。
これで、アイテムにデータを追加するときに、アイテムにそのフィールドが定義されていない場合、そのフィールドが追加され、その後、データは通常どおりに追加されます。