精通Scrapy网络爬虫
上QQ阅读APP看书,第一时间看更新

4.1 Item和Field

Scrapy提供了以下两个类,用户可以使用它们自定义数据类(如书籍信息),封装爬取到的数据:

● Item基类

自定义数据类(如BookItem)的基类。

● Field类

用来描述自定义数据类包含哪些字段(如name、price等)。

自定义一个数据类,只需继承Item,并创建一系列Field对象的类属性(类似于在Django中自定义Model)即可。以定义书籍信息BookItem为例,它包含两个字段,分别为书的名字name和书的价格price,代码如下:

        >>> from scrapy import Item, Field
        >>> class BookItem(Item):
        ...    name=Field()
        ...    price=Field()

Item支持字典接口,因此BookItem在使用上和Python字典类似,可按以下方式创建BookItem对象:

        >>> book1 = BookItem(name='Needful Things', price=45.0)
        >>> book1
        {'name': 'Needful Things', 'price': 45.0}
        >>> book2 = BookItem()
        >>> book2
        {}
        >>> book2['name'] = 'Life of Pi'
        >>> book2['price'] = 32.5
        {'name': 'Life of Pi', 'price': 32.5}

对字段进行赋值时,BookItem内部会对字段名进行检测,如果赋值一个没有定义的字段,就会抛出异常(防止因用户粗心而导致错误):

        >>> book = BookItem()
        >>> book['name'] = 'Memoirs of a Geisha'
        >>>book['prize']=43.0   # 粗心,把price拼写成了prize.
        Traceback (most recent call last):
          ...
        KeyError: 'BookItem does not support field: prize'

访问BookItem对象中的字段与访问字典类似,示例如下:

        >>> book = BookItem(name='Needful Things', price=45.0)
        >>> book['name']
        'Needful Things'
        >>> book.get('price', 60.0)
        45.0
        >>> list(book.items())
        [('price', 45.0), ('name', 'Needful Things')]

接下来,我们改写第1章example项目中的代码,使用Item和Field定义BookItem类,用其封装爬取到的书籍信息项目目录下的items.py文件供用户实现各种自定义的数据类,在items.py中实现BookItem,代码如下:

        from scrapy import Item, Field

        class BookItem(Item):
          name = Field()
          price = Field()

修改之前的BooksSpider,使用BookItem替代Python字典,代码如下:

        from ..items import BookItem

        class BooksSpider(scrapy.Spider):
          ...
          def parse(self, response):
              for sel in response.css('article.product_pod'):
                book = BookItem()
                book['name'] = sel.xpath('./h3/a/@title').extract_first()
                book['price'] = sel.css('p.price_color::text').extract_first()
                yield book
          ...