python - Scrapy::JSONエクスポートに関する問題

python json web-crawler scrapy

そのため、私はScrapyのドキュメントとチュートリアルにかなりの時間を費やしてきました。それ以来、非常に基本的なクローラーにプラグインしています。ただし、出力をJSONファイルに取得できません。明らかな何かが欠けているように感じますが、他のいくつかの例を見て、いくつかの異なることを試してみた後、何かを上げることができませんでした。

念のため、関連するすべてのコードを含めます。ここで取得しようとしているのは、いくつかの特定のアイテムとそれらに関連する価格です。価格はかなり頻繁に変更され、アイテムははるかに低い頻度で変更されます。

これが私のitems.pyです:

class CartItems(Item):
    url = Field()
    name = Field()
    price = Field()


そしてここにクモがあります:

from scrapy.selector import HtmlXPathSelector                                                                                                                                        
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.item import Item, Field

from Example.items import CartItems

class DomainSpider(CrawlSpider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = ['http://www.example.com/path/to/desired/page']


    def parse(self, response):
        hxs = HtmlXPathSelector(response)
        cart = CartItems()
        cart['url'] = hxs.select('//title/text()').extract()
        cart['name'] = hxs.select('//td/text()').extract()[1]
        cart['price'] = hxs.select('//td/text()').extract()[2]
        return cart


たとえば、URL http://www.example.com/path/to/desired/pageのScrapyシェルからhxs.select( '// td / text()')。extract()[1]を実行すると、次の応答が返されます。

u'Text field I am trying to download'


編集:

さて、私はwikiで見つけたパイプラインに従ってパイプラインを作成しました(この数日間、このセクションを掘り下げていたときに、このセクションを逃してしまいました)、XMLの代わりにJSONを使用するように変更しました。

from scrapy.xlib.pydispatch import dispatcher
from scrapy import signals
from scrapy.contrib.exporter import JsonItemExporter

class JsonExportPipeline(object):

    def __init__(self):
        dispatcher.connect(self.spider_opened, signals.spider_opened)
        dispatcher.connect(self.spider_closed, signals.spider_closed)
        self.files = {}

    def spider_opened(self, spider):
        file = open('%s_items.json' % spider.name, 'w+b')
        self.files[spider] = file
        self.exporter = JsonItemExporter(file)
        self.exporter.start_exporting()

    def spider_closed(self, spider):
        self.exporter.finish_exporting()
        file = self.files.pop(spider)
        file.close()

    def process_item(self, item, spider):
        self.exporter.export_item(item)
        return item


これはファイル「example.com_items.json」を出力しますが、含まれるのは「[]」だけです。だから、私はまだ何かがここでは正しくありません。スパイダーに問題がありますか、それともパイプラインが正しく行われていませんか?明らかに私はここで何かを見逃しているので、誰かが私を正しい方向に動かしたり、助けになる可能性のある例を私にリンクしたりできれば、それは最もありがたいことです。
答え
JsonItemExporterはかなり単純です。

class JsonItemExporter(JsonLinesItemExporter):

    def __init__(self, file, **kwargs):
        self._configure(kwargs)
        self.file = file
        self.encoder = json.JSONEncoder(**kwargs)
        self.first_item = True

    def start_exporting(self):
        self.file.write("[")

    def finish_exporting(self):
        self.file.write("]")

    def export_item(self, item):
        if self.first_item:
            self.first_item = False
        else:
            self.file.write(',\n')
        itemdict = dict(self._get_serialized_fields(item))
        self.file.write(self.encoder.encode(itemdict))


だから、私は2つの結論があります:


ファイルが作成されます-パイプラインがアクティブで、spider_openedおよびspider_closedイベントをフックします。
process_itemが呼び出されることはありません。スクレイピングされたアイテムがないので、このパイプラインに渡されたアイテムはありませんか?


また、コードにバグがあると思います:

def spider_opened(self, spider):
    file = open('%s_items.json' % spider.name, 'w+b')
    self.files[spider] = file
    self.exporter = JsonItemExporter(file)
    self.exporter.start_exporting()


self.exporter = JsonItemExporter(file)-これは常にアクティブなエクスポーターが1つしかないことを意味しますか?クモを開いたら、エクスポーターを作成します。そのスパイダーがアクティブな間、別のスパイダーを開くことができ、self.exporterは新しいエクスポーターによって上書きされます。
関連記事

python - 辞書の用語の非構造化テキストを解析して、用語へのリンクを含めます

python - すべてのスレッドが終了したときにのみIPythonに新しいプロンプトを表示させるにはどうすればよいですか

python - Pythonのネットワークマルチスレッド

python - シングルリンククラスタリング

python - マルチプロセッシングキューモジュールを介して関数にリストを渡すときにエラーが発生しました

python - Python + Cairo + GTK / GDKピクセルバッファーの簡単なセットアップ

python - JavaScriptを介してMongoインデックスを追加する

python - タブ化された一連のQDockWidgetのトップQDockWidgetを設定する

python - あるプログラムから別のプログラムでstdoutを読み取る

python - Pythonで数値を分割する方法の数