Scrapy:使用itemLoader填充嵌套项

3

我有一个对象,我正在尝试使用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\'))]')

到目前为止,我已经成功填充了每个字段,但是“stats”字段还没有。我查看了这个页面correct way to nest Item data in scrapy,但似乎不再起作用(我无法使其工作,我的错误是TypeError:to_unicode必须接收一个字节、字符串或Unicode对象,得到StatsItem)。
我想使用itemLoader,但我不知道如何使用StatsItem来填充我的“stats”字段。
感谢您的帮助。 编辑 我已经接近成功,但仍然不起作用:
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": "{\"comments_count\": \"0\", \"views_count\": \"42\"}" }

我认为您忘记在ArticleItemstats属性中包含 Field(serializer=MetaItem) - eLRuLL
@kiran.koduru 我认为我不需要 processor,因为我已经设置了 Item Loader 的默认值。 - RogerFromSpace
好的,你能展示一下在你的加载器中如何添加统计字段吗(在parse方法内部)? - eLRuLL
这正是我不知道如何做的。到目前为止,我正在尝试 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()') return json.dumps(list(statsLoader.load_item())) - RogerFromSpace
2
只需返回 statsLoader.load_item(),无需使用 json.dumps - eLRuLL
显示剩余2条评论
1个回答

4
感谢 @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

spider.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对于stats字段是MapCompose(remove_tags)。为了对对象进行序列化,你必须return dict(loader.load_item())而不仅仅是return loader.load_item()

谢谢!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接