Scrapy :: Проблемы с экспортом JSON - PullRequest
2 голосов
/ 20 октября 2011

Итак, я потратил довольно много времени на просмотр документации и руководств по 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

Если, например, я запускаю hxs.select ('// td / text ()'). Extract () [1] из оболочки Scrapy по URL-адресу http://www.example.com/path/to/desired/page,, тогда я получаю следующий ответ:

u'Text field I am trying to download'

РЕДАКТИРОВАТЬ:

Хорошо, поэтому я написал конвейер, следующий за тем, который я нашел в вики (я как-то пропустил этот раздел, когда копался в этом последние несколько дней),только что изменил использование JSON вместо XML.

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", но все, что он содержит, это "[]".Итак, мне что-то здесь не так.Проблема с пауком, или конвейер сделан неправильно?Очевидно, что я что-то здесь упускаю, так что, если кто-то может подтолкнуть меня в правильном направлении или связать со мной какие-нибудь примеры, которые могут помочь, это было бы очень ценно.

Ответы [ 2 ]

1 голос
/ 18 ноября 2011

Я скопировал ваш код из JsonExportPipeline и протестировал на моей машине.Он отлично работает с моим пауком.

Так что я думаю, что вы должны проверить страницу.

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
1 голос
/ 21 октября 2011

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))

Итак, у меня есть два вывода:

  1. Файл создан - ваш конвейер активен и перехватывает spider_opened и spider_closed события.

  2. 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) - разве это не означает, что постоянно активен только один экспортер? Как только паук открыт, вы создаете экспортер. Пока этот паук активен, можно открыть другого, и self.exporter будет перезаписан новым экспортером.

...