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は、フィールド名を。と呼ばれる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

そして、あなたは行き​​ます。

これで、アイテムにデータを追加するときに、アイテムにそのフィールドが定義されていない場合、そのフィールドが追加され、その後、データは通常どおりに追加されます。

于 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で機能し、アイテムがアイテムローダーと連携できるようにします。

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 に答える