【Scrapy ITem】Item Loaders(项目加载器)学习初探

       Item Loaders(项目加载器),意义,当项目很大的时候,提取的字段数以百计,做维护是很困难的。
       所以scrapy就提供了ItemLoader这样一个容器,在这个容器里面可以配置item中各个字段的提取规则。可以通过函数分析原始数据,并对Item字段进行赋值,非常的便捷。参考网站:https://blog.csdn.net/zwq912318834/article/details/79530828
       可以这么来看 Item 和 Itemloader:Item提供保存抓取到数据的容器,而 Itemloader提供的是填充容器的机制。
       Itemloader提供的是一种灵活,高效的机制,可以更方便的被spider或source format (HTML, XML, etc)扩展并重写,更易于维护,尤其是分析规则特别复杂繁多的时候。

       使用方法如下
第一步:实例化对象
       首先在Item.py文件中定义一个类,这里定义一个articleDetailItem类
       其次在爬虫文件中使用类似的字典的对象或者自定义的Item对象进行实例化,如下:   

# 文件 boleSpider.py
mport scrapy
from scrapy.loader import ItemLoader
def parse_detail(self, response):
        # 需要实例化ItemLoader, 注意第一个参数必须是实例化的对象...
        atricleItemLoader = ItemLoader(item = articleDetailItem(), response=response)

        然后填充数据,使用标准的三个方法,add_xpath、add_css、add_value。

# 调用xpath选择器,提取title信息
atricleItemLoader.add_xpath('title', '//div[@class="entry-header"]/h1/text()')
# 调用css选择器,提取praise_nums信息
atricleItemLoader.add_css('praise_nums', '.vote-post-up h10::text')
# 直接给字段赋值,尤其需要注意,不管赋值的数据是什么,都会自动转换成list类型
atricleItemLoader.add_value('url', response.url)

       最后将数据提取出去,使用load_item()方法,具体实例如下:

 articleInfo = atricleItemLoader.load_item()

第二步:进一步处理。  如果提取出来的数据需要取其中的一个或者对去除数据进一步处理,需要改写item.py文件,引入 输入处理器input_processor和输出处理器output_processor,实例代码如下:

class articleDetailItem(scrapy.Item):
    # 标题
    title = scrapy.Field()
    # 文章创建时间
    create_date = scrapy.Field(
        # 转换前是'create_date':'\r\n\r\n            2018/03/14 ·  '
        # 转换后是'create_date': datetime.date(2018, 3, 14),
        input_processor = MapCompose(date_convert),
        output_processor = TakeFirst()
    )
    # 文章链接地址
    url = scrapy.Field(
        # 转换前是'url': ['http://blog.jobbole.com/113771/']
        # 转换后是'url': 'http://blog.jobbole.com/113699/'
        output_processor = TakeFirst()
    )

        其中TakeFirst()取第一个,Mapcompose()函数是引入处理函数的,其中的参数date_convert是一个函数名字,这个需要在itmes.py文件中最前边写date_convert这个函数。itmes.py完整代码如下

# 文件items.py
import datetime
import scrapy

# 定义一个时间处理转换函数
# 将 '\r\n\r\n            2018/03/06 ·  ' 转换成 datetime.date(2018, 3, 14)
def date_convert(value):
    try:
        create_date = datetime.datetime.strptime(value, "%Y/%m/%d").date()
    except Exception as e:
        create_date = datetime.datetime.now().date()

    return create_date

# 用于存储解析文章的详细信息
class articleDetailItem(scrapy.Item):
    # 文章创建时间
    create_date = scrapy.Field(
        # 转换前是'create_date':'\r\n\r\n            2018/03/14 ·  '
        # 转换后是'create_date': datetime.date(2018, 3, 14),
        input_processor = MapCompose(date_convert),
        output_processor = TakeFirst()
    )

类似TakeFirst()的函数系统自定义的函数还有很多,常用的如下:
TakeFirst():返回第一个非空(non-null/ non-empty)值,常用于单值字段的输出处理器,无参数。
Identity():最简单的处理器,不进行任何处理,直接返回原来的数据。无参数。
Join():返回用分隔符连接后的值。分隔符默认为空格。不接受Loader contexts():当使用默认分隔符的时候,这个处理器等同于如下这个:u' '.join
Compose():用给定的多个函数的组合,来构造的处理器。list对象(注意不是指list中的元素),依次被传递到第一个函数,然后输出,再传递到第二个函数,一个接着一个,直到最后一个函数返回整个处理器的输出。
默认情况下,当遇到None值(list中有None值)的时候停止处理。可以通过传递参数stop_on_none = False改变这种行为。
MapCompose():与Compose处理器类似,区别在于各个函数结果在内部传递的方式(会涉及到list对象解包的步骤):
输入值是被迭代的处理的,List对象中的每一个元素被单独传入,第一个函数进行处理,然后处理的结果被连接起来形成一个新的迭代器,并被传入第二个函数,以此类推,直到最后一个函数。最后一个函数的输出被连接起来形成处理器的输出。
每个函数能返回一个值或者一个值列表,也能返回None(会被下一个函数所忽略)
这个处理器提供了很方便的方式来组合多个处理单值的函数。因此它常用于输入处理器,因为传递过来的是一个List对象。

重用和扩展ItemLoaders

        从上面的信息来看,ItemLoaders是非常灵活的,但是假设有个需求,所有的字段,我们都要去取第一个,那么如果有300个字段,我们就要添加300次,每个都要写,就会觉得很麻烦。那么有没有办法统一设置呢,答案是有的=>可以定义一个自己的ItemLoader类:ArticleItemLoader(继承自ItemLoader类)
scrapy中默认原始的 ItemLoader 类是这样写的,这个类卸载__init__.py文件中,具体如下:

# E:\Miniconda\Lib\site-packages\scrapy\loader\__init__.py
class ItemLoader(object):

    default_item_class = Item
    # 可以看到是有默认的输入/输出处理器的,而且默认是什么都不做
    default_input_processor = Identity()
    default_output_processor = Identity()
    default_selector_class = Selector

而我们自定义Item类需要在item.py如下填写:

# 文件items.py
from scrapy.loader import ItemLoader

# 需要继承内置的ItemLoader类
class ArticleItemLoader(ItemLoader):
    # 自定义itemloader,默认的输出处理器为取第一个非空元素
    default_output_processor = TakeFirst()
具体的在爬虫.py使用时,们就不能再简单的使用原有的ItemLoader,而是使用我们自己定义的 ArticleItemLoader 来填充数据:
# 文件boleSpider.py
from ArticleSpider.items import articleDetailItem, ArticleItemLoader

# 使用自定义的ArticleItemLoader实例化一个item_loader 对象
# 然后发现,结果都是从list中取出了一个值:说明我们的设置已经生效了。
item_loader = ArticleItemLoader(item = articleDetailItem(), response=response)
item_loader.add_xpath('title', '//div[@class="entry-header"]/h1/text()')

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值