(3)Scrapy的Items(项目)

1.Items(项目)

通常抓取的目标源一般都是非结构化来源,例如网页HTML等。我们需要从中提取结构化数据(解析数据)。Spider(蛛蛛)可以将提取的数据返回为Item(项目)对象,即定义键值对的Python对象。Scrapy支持多种类型的Item。创建Item时,您可以使用所需的任何类型的Item对象接收解析数据。

2.Item Type(项目类型)

Scrapy通过itemadapter库支持以下类型的Item:Dictionaries(字典)、Item objects(项目对象)、Dataclass objects(数据类对象)和Attrs objects(属性对象)。

数据类型是dict字典。

跟dict字典类似的API功能。允许定义字段名称。允许定义字段元数据,可用于自定义序列化。提供trackref跟踪Item对象以帮助查找内存泄漏。支持浅复制Item.copy()、深复制Item.deepcopy()。
fields
包含此项目的所有声明字段的字典,而不仅仅是填充的字段。键是字段名称,值是Item声明Field中使用的对象。
示例:

from scrapy.item import Item, Field

class BaiduNewsBoardItem(Item):
    Title = scrapy.Field()
    Content = scrapy.Field()
    ImgUrl = scrapy.Field()
    NewsUrl = scrapy.Field()
HotSearchIndex = scrapy.Field()

dataclass()支持序列化定义Item的数据类型。

from dataclasses import dataclass

@dataclass
class BaiduNewsBoardItem_Dataclass:
    Title: str
    Content: str
    ImgUrl: str
    NewsUrl: str
    HotSearchIndex: int

attr支持序列化转换Item属性对象。

import attr

@attr.s
class BaiduNewsBoardItem_Attr:
    Title = attr.ib()
    Content = attr.ib()
    ImgUrl = attr.ib()
    NewsUrl = attr.ib()
HotSearchIndex = attr.ib()

3.使用Item对象

Item子类使用简单的类定义语法和Field对象来声明。这是一个例子:

import scrapy

class BaiduNewsBoardItem(scrapy.Item):
    Title = scrapy.Field()
    Content = scrapy.Field()
    ImgUrl = scrapy.Field()
    NewsUrl = scrapy.Field()
    HotSearchIndex = scrapy.Field()
CreateTime = scrapy.Field(serializer=str)

Item.Field对象用于指定每个字段的元数据。例如CreateTime字段序列化成字符元数据。意味着您可以为每个字段指定任何类型的元数据,Field对象接受的值没有限制。
●创建Item对象

>>>item = BaiduNewsBoardItem(Title='测试数据',HotSearchIndex=1)
{'HotSearchIndex': 1, 'Title': '测试数据'}

●获取Item字段值

>>>title = item['Title']
测试数据

>>>hot_search_index = item.get('HotSearchIndex')
1

>>>content = item['Content']
Traceback (most recent call last):
    ...

KeyError: ''Content''

>>> item.get('Content', 'not set')
not set

>>> item['UKF']  # 获取未知字段
Traceback (most recent call last):
    ...

KeyError: 'UnknownField'

>>> item.get('UKF', 'unknown field')
'unknown field'

>>>'Title' in item  # 标题字段是否已填充?
True

>>>'Content' in item  # 内容字段是否已填充?
False

>>>'Content' in item.fields  # 内容字段是声明的字段吗?
True

>>>'UKF' in item.fields  # UKF是一个声明字段吗?
False
>>>item = BaiduNewsBoardItem()
>>>item['Title'] = "测试数据"
测试数据

>>>item['UKF'] = 'test' # 设置未知字段
Traceback (most recent call last):
    ...

KeyError: 'BaiduNewsBoardItem does not support field: UKF'

要访问所有填充的值,只需使用典型的字典dict API:

>>>keys = item.keys()
['Title', 'HotSearchIndex']

>>>items = item.items()
{'HotSearchIndex': 1, 'Title': '测试数据'}

复制Item分为深浅复制。深浅复制的区别我的理解是:
copy相当于一个替身,只是表面的假象,真主换动作了替身也要随着变。
deepcopy当作一对双胞胎,虽然相似,但实际上是各自独立的特征。
●浅复制

>>>item_copy1 = item.copy()
>>>item_copy2 = BaiduNewsBoardItem(item)
{'HotSearchIndex': 1, 'Title': '测试数据'}

●深复制

>>>item_deepcopy = item.deepcopy()
{'HotSearchIndex': 1, 'Title': '测试数据'}
>>>item_dic = dict(item)  # 从所有填充的值创建字典dict
{'HotSearchIndex': 1, 'Title': '测试数据'}
>>> item = BaiduNewsBoardItem({'Title': '测试数据', 'HotSearchIndex': 1})
{'HotSearchIndex': 1, 'Title': '测试数据'}

>>>item = BaiduNewsBoardItem({'Title': '测试数据', 'HotSearchIndex': 1, 'UKF': 'unknown field'})
Traceback (most recent call last):
    ...

KeyError: 'BaiduNewsBoardItem does not support field: UKF'

您可以通过声明原始Item的子类来扩展Items(以添加更多字段或更改某些字段的某些元数据)。例如:

from project.items import BaiduNewsBoardItemExtend
>>>item = BaiduNewsBoardItemExtend(Title='测试数据',HotSearchIndex=1,Author='测试人员',UpdateTime=datetime.datetime.now())
{'Author': '测试人员','HotSearchIndex': 1,'Title': '测试数据','UpdateTime': datetime.datetime(2022, 8, 12, 12, 30, 21, 741303)}

您还可以通过使用以前的字段元数据并附加更多值或更改现有值来扩展字段元数据,如下所示:

class BaiduNewsBoardItemSpecific(BaiduNewsBoardItem):
Title = scrapy.Field(BaiduNewsBoardItem.fields['Title'], serializer=str)

这会添加(或替换)该字段的serializer元数据键Title,保留所有先前存在的元数据值。

参考文献:
Scrapy项目https://docs.scrapy.org/en/latest/topics/items.html

Original: https://blog.csdn.net/wzk153/article/details/126273095
Author: 老葱头蒸鸡
Title: (3)Scrapy的Items(项目)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/789724/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球