【问题标题】:Scrapy :: Issues with JSON exportScrapy :: JSON导出问题
【发布时间】:2011-12-11 23:29:19
【问题描述】:

所以,我花了相当多的时间阅读 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 shell 运行 hxs.select('//td/text()').extract()[1],那么我会得到以下响应:

u'Text field I am trying to download'

编辑:

好的,所以我写了一个管道,它遵循我在 wiki 中找到的管道(我在过去几天挖掘这个部分时不知何故错过了这一部分),只是改用 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”,但它只包含“[]”。所以,我的东西还是不在这里。是蜘蛛的问题,还是管道没有正确完成?显然我在这里遗漏了一些东西,所以如果有人可以将我推向正确的方向,或者链接我任何可能有帮助的示例,那将不胜感激。

【问题讨论】:

    标签: python json web-crawler scrapy


    【解决方案1】:

    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_openedspider_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 将被新的导出器覆盖。

    【讨论】:

      【解决方案2】:

      我从 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
      

      【讨论】:

        猜你喜欢
        • 2015-02-27
        • 1970-01-01
        • 1970-01-01
        • 2014-02-19
        • 1970-01-01
        • 2018-09-13
        • 2016-10-18
        • 2021-01-28
        • 2022-01-21
        相关资源
        最近更新 更多