专栏首页志学PythonScrapy(6)Item loader 加载器详解

Scrapy(6)Item loader 加载器详解

项目加载器提供了一个方便的方式来填补从网站上刮取的项目。

声明项目加载器 项目加载器的声明类:Items。例如: from scrapy.loader import ItemLoader from scrapy.loader.processors import TakeFirst, MapCompose, Join class DemoLoader(ItemLoader): default_output_processor = TakeFirst() title_in = MapCompose(unicode.title) title_out = Join() size_in = MapCompose(unicode.strip) # you can continue scraping here 在上面的代码可以看到,输入处理器使用 _id 作为后缀以及输出处理器声明使用_out 作为后缀声明。 ItemLoader.default_input_processor 和 ItemLoader.default_output_processor 属性用于声明默认输入/输出处理器。 使用项目加载器来填充项目 要使用项目加载器, 先用类似字典的对象, 或项目使用 Loader.default_item_class 属性指定 Item 类实例化。 可以使用选择器来收集值到项目加载器。 可以在同一项目字段中添加更多的值, 项目加载器将使用相应的处理程序来添加这些值 下面的代码演示项目是如何使用项目加载器来填充: from scrapy.loader import ItemLoader from demoproject.items import Demo def parse(self, response): l = ItemLoader(item = Product(), response = response) l.add_xpath("title", "//div[@class='product_title']") l.add_xpath("title", "//div[@class='product_name']") l.add_xpath("desc", "//div[@class='desc']") l.add_css("size", "div#size]") l.add_value("last_updated", "yesterday") return l.load_item() 如上图所示,有两种不同的XPath,使用 add_xpath()方法从标题(title)字段提取: 1. //div[@class="product_title"] 2. //div[@class="product_name"] 此后,类似请求用于内容描述(desc)字段。size数据使用 add_css()方法提取和last_updated 使用add_value()方法使用值“yesterday”来填充。 完成所有收集数据的,调用 ItemLoader.load_item() 方法返回填充并使用 add_xpath(),add_css()和 dadd_value()方法提取数据项。

输入和输出处理器

一个项目加载器的各个字段包含一个输入处理器和一个输出处理器。

当提取数据时,输入处理器处理结果,交将结果存储在数据加载器。

接下来,收集数据后,调用 ItemLoader.load_item() 方法来获得 Item 对象。

最后,指定输出处理器到该项目的结果。

下面的代码演示针对特定字段如何调用输入和输出处理器:

l = ItemLoader(Product(), some_selector)
l.add_xpath("title", xpath1) # [1]
l.add_xpath("title", xpath2) #  [2]
l.add_css("title", css) # [3]
l.add_value("title", "demo") # [4]
return l.load_item() # [5]

第1行: 标题(title)的数据是从xpath1提取并通过输入处理器,其结果被收集并存储在 ItemLoader 中。

第2行: 同样地,标题(title)从xpath2提取并通过相同的输入处理器,其结果收集的数据加到[1]中。

第3行: 标题(title)被从css选择萃取和通过相同的输入处理器传递并将收集的数据结果加到[1]及[2]。

第4行: 接着,将“demo”值分配并传递到输入处理器。

第5行: 最后,数据是从所有字段内部收集并传递给输出处理器,最终值将分配给项目

声明输入和输出处理器

输入和输出的处理器在项目加载器(ItemLoader )定义声明。除此之外,它们还可以在项目字段的元数据指定。

例如:

import scrapy
from scrapy.loader.processors import Join, MapCompose, TakeFirst
from w3lib.htmll import remove_tags

def filter_size(value):
    if value.isdigit():
        return value

class Item(scrapy.Item):
    name = scrapy.Field(
        input_processor = MapCompose(remove_tags),
        output_processor = Join(),
    )
    size = scrapy.Field(
       input_processor = MapCompose(remove_tags, filter_price),
       output_processor = TakeFirst(),
    )

>>> from scrapy.loader import ItemLoader
>>> il = ItemLoader(item=Product())
>>> il.add_value('title', [u'Hello', u'<strong>world</strong>'])
>>> il.add_value('size', [u'<span>100 kg</span>'])
>>> il.load_item()

它显示的输出结果如下:

{'title': u'Hello world', 'size': u'100 kg'}

项目加载器上下文

项目加载器上下文是输入和输出的处理器中共享的任意键值的字典。

例如,假设有一个函数parse_length:

def parse_length(text, loader_context):
    unit = loader_context.get('unit', 'cm')
    # You can write parsing code of length here
    return parsed_length

通过接收loader_context参数,它告诉项目加载器可以收到项目加载器上下文。有几种方法可以改变项目加载器上下文的值:

修改当前的活动项目加载器上下文:

loader = ItemLoader (product)
loader.context ["unit"] = "mm"

在项目加载器实例中修改:

loader = ItemLoader(product, unit="mm")

在加载器项目声明与项目加载器上下文实例输入/输出处理器中修改:

class ProductLoader(ItemLoader):
    length_out = MapCompose(parse_length, unit="mm")

ItemLoader对象

它是一个对象,它返回一个新项加载器到填充给定项目。它有以下类:

class scrapy.loader.ItemLoader([item, selector, response, ]**kwargs)

嵌套加载器

这是使用从文档解析分段的值来创建嵌套加载器。如果不创建嵌套装载器,需要为您想提取的每个值指定完整的XPath或CSS。

例如,假设要从一个标题页中提取数据:

<header>
  <a class="social" href="http://facebook.com/whatever">facebook</a>
  <a class="social" href="http://twitter.com/whatever">twitter</a>
  <a class="email" href="mailto:someone@example.com">send mail</a>
</header>

接下来,您可以通过添加相关的值到页眉来创建头选择器嵌套装载器:

loader = ItemLoader(item=Item())
header_loader = loader.nested_xpath('//header')
header_loader.add_xpath('social', 'a[@class = "social"]/@href')
header_loader.add_xpath('email', 'a[@class = "email"]/@href')
loader.load_item()

重用和扩展项目加载器

项目加载器的设计以缓解维护,当要获取更多的蜘蛛时项目变成一个根本的问题。

举例来说,假设一个网站自己的产品名称是由三条短线封闭的(例如: ---DVD---)。 您可以通过重复使用默认产品项目加载器,如果你不希望它在最终产品名称所示,下面的代码删除这些破折号:

from scrapy.loader.processors import MapCompose
from demoproject.ItemLoaders import DemoLoader

def strip_dashes(x):
    return x.strip('-')

class SiteSpecificLoader(DemoLoader):
    title_in = MapCompose(strip_dashes, DemoLoader.title_in)

可用内置处理器

以下是一些常用的内置处理器:

class scrapy.loader.processors.Identity

回原始的值而并不修改它。 例如:

>>> from scrapy.loader.processors import Identity
>>> proc = Identity()
>>> proc(['a', 'b', 'c'])
['a', 'b', 'c']

class scrapy.loader.processors.TakeFirst

回一个值来自收到列表的值即非空/非null值。 例如:

>>> from scrapy.loader.processors import TakeFirst
>>> proc = TakeFirst()
>>> proc(['', 'a', 'b', 'c'])
'a'

class scrapy.loader.processors.Join(separator = u' ')

回附连到分隔符的值。默认的分隔符是 u'',这相当于于 u' '.join 的功能。例如:

>>> from scrapy.loader.processors import Join
>>> proc = Join()
>>> proc(['a', 'b', 'c'])
u'a b c'
>>> proc = Join('<br>')
>>> proc(['a', 'b', 'c'])
u'a<br>b<br>c'

class scrapy.loader.processors.SelectJmes(json_path)

查询使用提供JSON路径值,并返回输出。

例如:

>>> from scrapy.loader.processors import SelectJmes, Compose, MapCompose
>>> proc = SelectJmes("hello")
>>> proc({'hello': 'scrapy'})
'scrapy'
>>> proc({'hello': {'scrapy': 'world'}})
{'scrapy': 'world'}

下面是一个查询通过导入JSON值的代码:

>>> import json
>>> proc_single_json_str = Compose(json.loads, SelectJmes("hello"))
>>> proc_single_json_str('{"hello": "scrapy"}')
u'scrapy'
>>> proc_json_list = Compose(json.loads, MapCompose(SelectJmes('hello')))
>>> proc_json_list('[{"hello":"scrapy"}, {"world":"env"}]')
[u'scrapy']

本文分享自微信公众号 - 志学Python(lijinwen1996329ken),作者:志学Python

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • webpack打包原理入门探究(七)其他文件处理

    这个 file-loader 是处理 css样式中的 图片地址,index.html的图片地址相对路径没有问题,但是如果处理 组件中的 图片的相对路径是会有一些...

    公众号---志学Python
  • webpack打包原理入门探究(六)less|sass-loader初探

    在 src/app.js 引入 src/styles/less/common.less

    公众号---志学Python
  • webpack打包原理入门探究(五)css-loader初探

    在 src/app.js 引入 src/styles/css/common.css

    公众号---志学Python
  • 干货 | 无监督学习和transformers如何在OpenAI手里玩出新花样

    AI 科技评论按:OpenAI 近期更新了一篇博客,他们利用一个任务无关的可扩展系统在多语言任务上取得了卓越进展。论文及代码已经公布。他们的方法结合了 tran...

    AI科技评论
  • 无监督学习和 transformers 如何在 OpenAI 手里玩出新花样

    AI 研习社按:OpenAI 近期更新了一篇博客,他们利用一个任务无关的可扩展系统在多语言任务上取得了卓越进展。论文及代码已经公布。他们的方法结合了 trans...

    AI研习社
  • 前沿 | 使用Transformer与无监督学习,OpenAI提出可迁移至多种NLP任务的通用模型

    OpenAI 的系统分为两阶段,首先研究者以无监督的方式在大型数据集上训练一个 Transformer,即使用语言建模作为训练信号,然后研究者在小得多的有监督数...

    机器之心
  • 【GitLab CI/CD】记一个问题 `too large archive`

    事情是这样子的,我自己搭建了 GitLab ,并导入了我在 GitHub 所有的仓库,并打算未来就在这里提交我的代码了。一方面是因为 GitHub 实在是太慢了...

    宋天伦
  • 利用vertical-align:middle实现在整个页面居中

    如果想让一个div或一张图片相对于整个页面居中,用vertical-align:middle可以很简单地解决。

    跟着阿笨一起玩NET
  • 如何在三个月内获得三年的工作经验?

    我是攻城师
  • Android系统启动——8 附录2:相关守护进程简介

    binder的服务总管,负责binder服务的注册和查找 代码在init.rc 602行

    隔壁老李头

作者介绍

精选专题

活动推荐

扫码关注云+社区

领取腾讯云代金券