【问题标题】:How to populate a scrapy.Field as a dictionary如何将 scrapy.Field 填充为字典
【发布时间】:2017-04-13 15:53:02
【问题描述】:

我正在使用Scrapy(使用SitemapSpider 蜘蛛)为www.apkmirror.com 构建一个刮板。到目前为止,以下工作:

DEBUG = True

from scrapy.spiders import SitemapSpider
from apkmirror_scraper.items import ApkmirrorScraperItem


class ApkmirrorSitemapSpider(SitemapSpider):
    name = 'apkmirror-spider'
    sitemap_urls = ['http://www.apkmirror.com/sitemap_index.xml']
    sitemap_rules = [(r'.*-android-apk-download/$', 'parse')]

    if DEBUG:
        custom_settings = {'CLOSESPIDER_PAGECOUNT': 20}

    def parse(self, response):
        item = ApkmirrorScraperItem()
        item['url'] = response.url
        item['title'] = response.xpath('//h1[@title]/text()').extract_first()
        item['developer'] = response.xpath('//h3[@title]/a/text()').extract_first()
        return item

ApkMirrorScraperItemitems.py 中定义如下:

class ApkmirrorScraperItem(scrapy.Item):
    url = scrapy.Field()
    title = scrapy.Field()
    developer = scrapy.Field()

如果我使用命令从项目目录运行它,得到的 JSON 输出

scrapy crawl apkmirror-spider -o data.json

是一个 JSON 字典数组,键为 urltitledeveloper,对应的字符串为值。但是,我想修改它,使 developer 的值本身就是一个带有 name 字段的字典,这样我就可以像这样填充它:

item['developer']['name'] = response.xpath('//h3[@title]/a/text()').extract_first()

但是,如果我尝试这个,我会得到KeyErrors,如果我将developerField(根据https://doc.scrapy.org/en/latest/topics/items.html#item-fieldsdict)初始化为developer = scrapy.Field(name=None)。我该怎么办?

【问题讨论】:

    标签: python scrapy scrapy-spider


    【解决方案1】:

    Scrapy 在内部将字段实现为 dicts,但这并不意味着它们应该作为 dicts 访问。当您调用item['developer'] 时,您真正在做的是获取字段的,而不是字段本身。因此,如果尚未设置该值,则会抛出 KeyError。

    考虑到这一点,有两种方法可以解决您的问题。

    第一个,只需将 developer 字段值设置为 dict:

    def parse(self, response):
        item = ApkmirrorScraperItem()
        item['url'] = response.url
        item['title'] = response.xpath('//h1[@title]/text()').extract_first()
        item['developer'] = {'name': response.xpath('//h3[@title]/a/text()').extract_first()}
        return item
    

    第二种,新建一个Developer类,并将developer值设置为该类的一个实例:

    # this can go to items.py
    class Developer(scrapy.Item):
        name = scrapy.Field()
    
    def parse(self, response):
        item = ApkmirrorScraperItem()
        item['url'] = response.url
        item['title'] = response.xpath('//h1[@title]/text()').extract_first()
    
        dev = Developer()        
        dev['name'] = response.xpath('//h3[@title]/a/text()').extract_first()       
        item['developer'] = dev
    
        return item
    

    希望对你有帮助:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-02
      • 1970-01-01
      相关资源
      最近更新 更多