【问题标题】:scrapy: Populate nested items with itemLoaderscrapy:使用 itemLoader 填充嵌套项目
【发布时间】:2016-12-26 16:18:57
【问题描述】:

我有这个对象,我正在尝试用 itemLoader 填充:

{
  "domains": "string",
  "date_insert": "2016-12-23T11:25:00.213Z",
  "title": "string",
  "url": "string",
  "body": "string",
  "date": "2016-12-23T11:25:00.213Z",
  "authors": [
    "string"
  ],
  "categories": [
    "string"
  ],
  "tags": [
    "string"
  ],
  "stats": {
    "views_count": 0,
    "comments_count": 0
  }
}

这是我的 items.py

class StatsItem(scrapy.Item):
    views_count=scrapy.Field()
    comments_count=scrapy.Field()

class ArticleItem(scrapy.Item):
    domain = scrapy.Field()
    date_insert=scrapy.Field()
    date_update=scrapy.Field()
    date=scrapy.Field()
    title=scrapy.Field()
    url=scrapy.Field()
    body=scrapy.Field(
        output_processor=Join())
    date=scrapy.Field()
    authors=scrapy.Field(
        output_processor=Identity())
    categories=scrapy.Field(
        output_processor=Identity())
    tags=scrapy.Field()
    stats=scrapy.Field()

我的蜘蛛的一部分:

def parse(self, response):
    loader = ArticleItemLoader(response=response)
    parsed_uri = urlparse(response.url)
    domain = '{uri.scheme}://{uri.netloc}/'.format(uri=parsed_uri)

    loader.add_css('authors','span.meta-author')
    loader.add_css('title', 'h1.title-article')
    loader.add_value('url', response.url)
    loader.add_xpath('date_insert', '//div[@class=\'meta\']/time[@itemprop=\'datePublished\']/@datetime')
    loader.add_xpath('date_update', '//div[@class=\'meta\']/time[@itemprop=\'dateModified\']/@datetime')
    loader.add_value('domain', domain)
    loader.add_xpath('categories', '//ul[@class=\'breadcrumbs\']//li[not(contains(@class, \'home\'))]')

到目前为止,我已成功填充除“统计信息”以外的所有字段。我已经检查了这个页面correct way to nest Item data in scrapy,但它似乎不再工作了(我不能让它工作,我的错误是 TypeError: to_unicode must receive a bytes, str or unicode object, got StatsItem)

我想使用 itemLoader,但我不知道如何使用我的 StatsItem 填充我的“统计信息”

感谢帮助

编辑 我很接近,但它仍然不起作用:

loader.add_value('stats', self.getStats(response))

def getStats(self, response):
    statsLoader = StatsItemLoader(response=response)
    statsLoader.add_xpath('comments_count', '//div[@class=\'btn-count\']//a/text()')
    statsLoader.add_value('views_count', '42')
    return json.dumps(dict(statsLoader.load_item()))

但我的输出是这样的: { [...] "stats": "{\"cmets_count\": \"0\", \"views_count\": \"42\"}" }

【问题讨论】:

  • 我认为您忘记在 stats 属性中包含 Field(serializer=MetaItem) ArticleItem
  • 从上面的代码中,您确定不需要像文档中的this example 那样为您的StatsItem 提供input_processoroutput_processor
  • @kiran.koduru 我想我不需要processor,因为我设置了项目加载器默认值。
  • @eLRull 我试过Field(serializer=StatsItem) 但没用
  • 只返回statsLoader.load_item() 不需要json.dumps

标签: python scrapy scrapy-spider


【解决方案1】:

感谢@eLRuLL,我设法找到了一个不错的解决方案:

items.py:

class StatsItem(scrapy.Item):
    views_count=scrapy.Field()
    comments_count=scrapy.Field()

class ArticleItem(scrapy.Item):
    [...]
    stats=scrapy.Field(
        input_processor=Identity())


class StatsItemLoader(ItemLoader):
    default_input_processor=MapCompose(remove_tags)
    default_output_processor=TakeFirst()
    default_item_class=StatsItem

蜘蛛.py:

def parse(self, response):
    [...]
    loader.add_value('stats', self.getStats(response))
    [...]

def getStats(self, response):
    statsLoader = StatsItemLoader(response=response)
    statsLoader.add_xpath('comments_count', '//div[@class=\'btn-count\']//a/text()')
    statsLoader.add_value('views_count', '42')
    return dict(statsLoader.load_item())

最初它不起作用,因为我的 input_processor 是 MapCompose(remove_tags) 用于统计字段。为了序列化对象你必须return dict(loader.load_item()) 而不仅仅是return loader.load_item()

谢谢!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2017-01-29
    • 2017-11-23
    • 1970-01-01
    相关资源
    最近更新 更多