Scrapy1.5基本概念(四)——数据项(Item)

本文为译文,原文见地址:https://docs.scrapy.org/en/latest/topics/items.html

数据项

本文主要目的是,从非结构化的数据源(比如,web页面)提取出结构化的数据。Scrapy爬虫可以提取数据并返回项Python字典一样的数据。虽然让人觉得很方便和熟悉,但是Python字典缺乏结构化:这是很容易在字段名中输入错误或者返回不一致的数据,特别是在有许多爬虫的大型项目中。

为了定义常见的输出数据格式,Scrapy提供了Item类。Item对象是一种简单的容器,用来搜集爬取到的数据。它提供了一个类似于字典的API,具有方便的语法来声明它们的可用字段。

各种Scrapy组件使用Item提供的额外信息:导出器查看已声明的字段,来找出列进行导出;通过Item字段的元数据使序列化可定制;trackref跟踪Item实例来帮助查找内存泄漏(请参见使用trackref调试内存泄漏);等等。

声明数据项

使用简单的类定义语法和字段对象,来声明数据项。下面是一个示例:

import scrapy


class Product(scrapy.Item):
	name = scrapy.Field()
	price = scrapy.Field()
	stock = scrapy.Field()
	last_updated = scrapy.Field(serializer=str)

注意:如果你熟悉Django的话,那么你会注意到Scrapy Item的声明与Django Models很类似,除了Scrapy Item没有不同字段类型的概念外。

数据项字段

Field对象被用来指定每个字段的元数据。比如,上面的示例中演示了last_updated字段的序列化函数。

你可以为每个字段指定任何种类的元数据。Field对象接受的值是没有限制的。出于同样的原因,所有可用的元数据关键字没有引用列表。每一个在Field对象中定义的关键字,都可能会被不同的组件使用,并且仅仅只有这些组件知道这些关键字。你也可以根据你的需求,在你的项目中使用其他Field关键字。Field对象的主要目的在于,提供一种方式在某个地方来定义所有的字段元数据。通常而言,那些行为依赖于每个字段的组件使用某些字段关键字来配置该行为。你必须参考它们的文档,以查看每个组件使用哪些元数据关键字。

需要注意的是,用于声明Item的Field对象不会被指定为类属性。相反,可以通过Item.fields属性来访问它们。

使用数据项

这里有一些使用Items的常见使用示例,使用上面声明的Product。你会注意到它们的API与dict API非常相似。

创建数据项

>>> product = Product(name='Desktop PC', price=1000)
>>> print(product)
{'name': 'Desktop PC', 'price': 1000}

获取字段值

>>> product['name']
'Desktop PC'
>>> product.get('name')
'Desktop PC'
>>> product['price']
1000
>>> product['last_updated']
Traceback (most recent call last):
	...
KeyError: 'last_updated'
>>> product.get('last_updated', 'not set')
'not set'
>>> product['lala']  # 获取未知字段
Traceback (most recent call last):
	...
KeyError: 'lala'
>>> product.get('lala', 'unknown field')
'unknown field'
>>> 'name' in product  # 是否有name字段
True
>>> 'last_updated' in product  # 是否有last_updated字段
False
>>> 'last_updated' in product.fields  # last_updated是一个声明了的字段?
True
>>> 'lala' in product.fields  # lala是一个声明了的字段
False

设置字段值

>>> product['last_updated'] = 'today'
>>> product['last_updated']
'today'
>>> product['lala'] = 'test'  # 设置未知字段
Trackback (most recent call last):
	...
KeyError: 'Product does not support field: lala'

访问所有填充的值

为了访问所有填充字段,只需要使用典型的dict API

>>> product.keys()
dict_keys(['name', 'price', 'last_updated'])
>>> product.items()
ItemsView({'last_updated': 'today', 'name': 'Desktop PC', 'price': 1000})

其他通用任务

复制Item:

>>> product2 = Product(product)
>>> print(product2)
{'last_updated': 'today', 'name': 'Desktop PC', 'price': 1000}
>>> product3 = product2.copy()
>>> print(product3)
{'last_updated': 'today', 'name': 'Desktop PC', 'price': 1000}

从Item创建字典:

>>> dict(product)  # 获取所有填充值来创建字典
{'name': 'Desktop PC', 'price': 1000, 'last_updated': 'today'}

从字典创建Item:

>>> Product({'name': 'Laptop PC', 'price': 1500})
{'name': 'Laptop PC', 'price': 1500}
>>> Product({'name': "laptop PC', 'lala': 1500})  # 警告:字典中存在未知字段
Trackback (most recent call last):
	...
KeyError: 'Product does not support field: lala'

扩展数据项

你可以通过声明你的原始Item的子类型来扩展Item(为了添加更多字段或者改变一些字段的元数据)。

举个栗子:

class DiscountedProduct(Product):
	discount_percent = scrapy.Field(serializer=str)
	discount_expiration_date = scrapy.Field()

你也可以通过如下方式扩展字段元数据——使用前面的字段元数据,并添加更多的值,或者改变已存在的值,如下所示:

class SpecificProduct(Product):
	name = scrapy.Field(Product.field['name'], serializer=my_serializer)

这样就可以添加(或者替换)name字段的serializer元数据关键字,并保持所有之前已经存在的元数据的值。

Item对象

class scrapy.item.Item([arg])

返回一个根据可选的参数arg初始化而来Item对象。
Item复制标准的dict API,包括其构造函数。项目提供的唯一附加属性是:

fields

是一个包含了这个Item的所有声明字段的字典,不仅仅是已经填充了的字段。关键字是字段名,值是Item声明中使用的Field对象。

Field对象

class scrapy.item.Field([arg])

Field类是一个内置字典类的别名,并且Field类不提供任何额外的功能或者属性。换句话说,Field对象就是Python字典。一个单独的类用于支持基于类属性的Item声明语法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值