scrapy爬虫框架——item

什么是Item?

爬虫的主要目标是从非结构化的数据源(通常是web页面)中提取结构化数据。Scrapy spider可以以Python字典的形式返回提取的数据。虽然很方便和熟悉,但Python字典缺乏结构:很容易在字段名中出现拼写错误或返回不一致的数据,特别是在有许多爬行器的大型项目中。

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

Item的声明

Item使用简单的class定义语法以及 Field 对象来声明。例如:

import scrapy

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

所有的item都是用scrapy.Field()来定义,日期对象要序列化为字符串
可以在定义Field时为每一个item对象指定序列化的数据类型

item的使用

item的使用方法与dict非常类似

1、实例化items对象

>>> product = Product(name=‘Desktop PC’, price=1000)
>>> print(product)
Product(name=‘Desktop PC’, price=1000)

2、通过key值或者get方法获取items的值

>>> product[‘name’]
Desktop PC
>>> product.get(‘name’)
Desktop PC

3、给item赋值

>>> product[‘last_updated’] = ‘today’
>>> product[‘last_updated’]
today

4、获取所有的key值

>>> product.keys()
[‘price’, ‘name’]

5、获取所有的value值

>>> product.items()
[(‘price’, 1000), (‘name’, ‘Desktop PC’)]
也可以通过dict(items)的方法转化为字典

使用item来改写book爬虫的代码

# items.py  声明items
class BookItem(scrapy.Item):
    name = scrapy.Field()
    content = scrapy.Field()
    bookname = scrapy.Field()

实例化item对象,将name和bookname存入items中

# book.py
	item = BookItem()
	item['name'] = name
    item['bookname'] = bookname
    item['content'] = content
# 最后返回items
yield item

Item Loader

Item Loader提供了一种解析数据并且填充进item的一种机制,注意:解析到的数据在item内部以列表的形式存储,允许向同一个字段添加多个值。如果在创建加载器时传递了item参数,则如果item的值已经是可迭代的,则按原样存储,如果项是单个值,则用列表包装。
Item Loader的使用
1、首先实例化一个item Loader对象,传入item类,和请求响应
2、itemLoader支持add_xpath语法,add_css选择器和add_value的方法向item中填充数据
3、最后将加载存入Item_Loader中的内容并返回。

from scrapy.loader import ItemLoader
from myproject.items import Product
def parse(self, response):
l = ItemLoader(item=Product(), response=response)
l.add_xpath(‘name’, ‘//div[@class=“product_name”]’)
l.add_xpath(‘name’, ‘//div[@class=“product_title”]’)
l.add_xpath(‘price’, ‘//p[@id=“price”]’)
l.add_css(‘stock’, ‘p#stock]’)
l.add_value(‘last_updated’, ‘today’) # you can also use literal values
return l.load_item()

输入和输出处理器

Item_Loader为每个(item)字段包含一个输入处理器和一个输出处理器。一旦接收到提取的数据(通过add_xpath()、add_css()或add_value()方法),输入处理器就会对其进行处理,并将输入处理器的结果收集到ItemLoader中。在收集所有数据之后,将调用ItemLoader.load_item()方法来填充和获取填充的Item对象。这时调用输出处理器处理之前输入处理器处理过的内容,输出处理器的结果是分配给该项的最终值。
下面这个例子来说明输入处理器和输出处理器的工作流程:

l = ItemLoader(Product(), some_selector)
l.add_xpath(‘name’, xpath1) # (1)
l.add_xpath(‘name’, xpath2) # (2)
l.add_css(‘name’, css) # (3)
l.add_value(‘name’, ‘test’) # (4)
return l.load_item() # (5)

注意
输入和输出处理器的第一个参数都必须是iterable。这些函数的输出可以是任何值。输入处理器的结果将被附加到一个内部列表(在加载程序中),其中包含收集到的值(用于该字段)。输出处理器的结果是最终分配给该项的值。
输入处理器返回的值是内部收集的(在列表中),然后传递给输出处理器来填充字段。

Item Loader的声明方法

1、直接定义一个继承于ItemLoader类的类声明

from scrapy.loader import ItemLoader
from scrapy.loader.processors import TakeFirst, MapCompose, Join
class ProductLoader(ItemLoader):
default_output_processor = TakeFirst()
name_in = MapCompose(unicode.title)
name_out = Join()
price_in = MapCompose(unicode.strip)
# …

可以看到,使用_in后缀声明输入处理器,而使用_out后缀声明输出处理器。您还可以使用ItemLoader.default_input_processor和ItemLoader.default_output_processor属性声明一个默认的输入/输出处理器。

2、在定义Item的时候,添加输入和输出选择器
正如在前一节中看到的,输入和输出处理器可以在项加载器定义中声明,以这种方式声明输入处理器是很常见的。但是,还有一个地方可以指定要使用的输入和输出处理器:Item字段元数据。下面是一个例子:

import scrapy
from scrapy.loader.processors import Join, MapCompose, TakeFirst
from w3lib.html import remove_tags
def filter_price(value):
if value.isdigit():
return value
class Product(scrapy.Item):
name = scrapy.Field(
input_processor=MapCompose(remove_tags),
output_processor=Join(),
)
price = scrapy.Field(
input_processor=MapCompose(remove_tags, filter_price),
output_processor=TakeFirst(),
)

输入和输出处理器的优先顺序如下:
ItemLoader特定于字段的属性:field_in和field_out(优先级最高)
字段元数据(input_processor和output_processor键)
默认项加载器:ItemLoader.default_input_processor()和ItemLoader.default_output_processor()(最低优先级)

使用ItemLoader改写book爬虫代码

由于在ItemLoader内部数据都是以列表或者可迭代对象的方式来传输,因此在定义item是要定义输出处理器。

class BookItem(scrapy.Item):
    name = scrapy.Field(output_processor=TakeFirst())
    content = scrapy.Field(output_processor=TakeFirst())
    bookname = scrapy.Field(output_processor=TakeFirst())
# 1).使用itemloader的方法对数据进行存储,将item对象和selector/response关联
l = ItemLoader(item=BookItem(), selector=chapter)
detail_url=chapter.xpath('./a/@href').extract_first()
# -). 根据xpath进行提取数据信息并填充到item对象的name属性中
l.add_xpath('name', './a/text()')
# -). 将数据信息(书籍名称)填充到item对象的bookname属性中
l.add_value('bookname', response.url.split('/')[-1].rstrip('.html'))
# 最后以元数据的方式返回加载后的item对象,
yield Request(url=self.base_url + detail_url,                          callback=self.parse_chapter_detail,
                          meta={
                              'item': l.load_item()
                          })
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值