Scrapy笔记05- Item详解

Item是保存结构数据的地方,Scrapy可以将解析结果以字典形式返回,但是Python中字典缺少结构,在大型爬虫系统中很不方便。

Item提供了类字典的API,并且可以很方便的声明字段,很多Scrapy组件可以利用Item的其他信息。

定义Item

定义Item非常简单,只需要继承scrapy.Item类,并将所有字段都定义为scrapy.Field类型即可

import scrapy

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

Item Fields

Field对象可用来对每个字段指定元数据。例如上面last_updated的序列化函数指定为str,可任意指定元数据,不过每种元数据对于不同的组件意义不一样。

Item使用示例

你会看到Item的使用跟Python中的字典API非常类似

创建Item

>>> product = Product(name='Desktop PC', price=1000)
>>> print product
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'] # getting unknown field
Traceback (most recent call last):
...
KeyError: 'lala' >>> product.get('lala', 'unknown field')
'unknown field' >>> 'name' in product # is name field populated?
True >>> 'last_updated' in product # is last_updated populated?
False >>> 'last_updated' in product.fields # is last_updated a declared field?
True >>> 'lala' in product.fields # is lala a declared field?
False

设置值


>>> product['last_updated'] = 'today'
>>> product['last_updated']
today >>> product['lala'] = 'test' # setting unknown field
Traceback (most recent call last):
...
KeyError: 'Product does not support field: lala'

>>> product.keys()访问所有的值

['price', 'name']

>>> product.items()
[('price', 1000), ('name', 'Desktop PC')]

Item Loader为我们提供了生成Item的相当便利的方法。Item为抓取的数据提供了容器,而Item Loader可以让我们非常方便的将输入填充到容器中。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()

注意上面的name字段是从两个xpath路径添累加后得到。

输入/输出处理器

每个Item Loader对每个Field都有一个输入处理器和一个输出处理器。输入处理器在数据被接受到时执行,当数据收集完后调用ItemLoader.load_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)

执行流程是这样的:

  1. xpath1中的数据被提取出来,然后传输到name字段的输入处理器中,在输入处理器处理完后生成结果放在Item Loader里面(这时候没有赋值给item)
  2. xpath2数据被提取出来,然后传输给(1)中同样的输入处理器,因为它们都是name字段的处理器,然后处理结果被附加到(1)的结果后面
  3. 跟2一样
  4. 跟3一样,不过这次是直接的字面字符串值,先转换成一个单元素的可迭代对象再传给输入处理器
  5. 上面4步的数据被传输给name的输出处理器,将最终的结果赋值给name字段

自定义Item Loader

使用类定义语法,下面是一个例子

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_processorItemLoader.default_input_processor.

在Field定义中声明输入/输出处理器

还有个地方可以非常方便的添加输入/输出处理器,那就是直接在Field定义中

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(),
)

优先级:

  1. 在Item Loader中定义的field_infield_out
  2. Filed元数据(input_processoroutput_processor关键字)
  3. Item Loader中的默认的

Tips:一般来讲,将输入处理器定义在Item Loader的定义中field_in,然后将输出处理器定义在Field元数据中

Item Loader上下文

Item Loader上下文被所有输入/输出处理器共享,比如你有一个解析长度的函数

def parse_length(text, loader_context):
unit = loader_context.get('unit', 'm')
# ... length parsing code goes here ...
return parsed_length

初始化和修改上下文的值

loader = ItemLoader(product)
loader.context['unit'] = 'cm' loader = ItemLoader(product, unit='cm') class ProductLoader(ItemLoader):
length_out = MapCompose(parse_length, unit='cm')

内置的处理器

  1. Identity 啥也不做
  2. TakeFirst 返回第一个非空值,通常用作输出处理器
  3. Join 将结果连起来,默认使用空格’ ‘
  4. Compose 将函数链接起来形成管道流,产生最后的输出
  5. MapCompose 跟上面的Compose类似,区别在于内部结果在函数中的传递方式. 它的输入值是可迭代的,首先将第一个函数依次作用于所有值,产生新的可迭代输入,作为第二个函数的输入,最后生成的结果连起来返回最终值,一般用在输入处理器中。
  6. SelectJmes 使用json路径来查询值并返回结果
 

Scrapy笔记05- Item详解的更多相关文章

  1. 转 Scrapy笔记(5)- Item详解

    Item是保存结构数据的地方,Scrapy可以将解析结果以字典形式返回,但是Python中字典缺少结构,在大型爬虫系统中很不方便. Item提供了类字典的API,并且可以很方便的声明字段,很多Scra ...

  2. qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)

    原博主博客地址:http://blog.csdn.net/qq21497936本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78516 ...

  3. 自学Zabbix4.2 web监控项创建+item详解

    自学Zabbix4.2 web监控项创建+item详解 1. web监控项创建 1.1  Scenario 选项卡 Name: 监控项的名称 Application: 放到哪个应用中 Authenti ...

  4. expect学习笔记及实例详解【转】

    1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示:1.1 首行加上/usr/bin/expect1.2 spawn: 后面加上需要执行的shell命令,比如说sp ...

  5. Scrapy的Item_loader机制详解

    一.ItemLoader与Item的区别 ItemLoader是负责数据的收集.处理.填充,item仅仅是承载了数据本身 数据的收集.处理.填充归功于item loader中两个重要组件: 输入处理i ...

  6. Hive笔记--sql语法详解及JavaAPI

    Hive SQL 语法详解:http://blog.csdn.net/hguisu/article/details/7256833Hive SQL 学习笔记(常用):http://blog.sina. ...

  7. 算法笔记--sg函数详解及其模板

    算法笔记 参考资料:https://wenku.baidu.com/view/25540742a8956bec0975e3a8.html sg函数大神详解:http://blog.csdn.net/l ...

  8. Android笔记——四大组件详解与总结

     android四大组件分别为activity.service.content provider.broadcast receiver. ------------------------------- ...

  9. Struts2学习笔记(二)——配置详解

    1.Struts2配置文件加载顺序: default.properties(默认常量配置) struts-default.xml(默认配置文件,主要配置bean和拦截器) struts-plugin. ...

  10. Struts2学习笔记二 配置详解

    Struts2执行流程 1.简单执行流程,如下所示: 在浏览器输入请求地址,首先会被过滤器处理,然后查找主配置文件,然后根据地址栏中输入的/hello去每个package中查找为/hello的name ...

随机推荐

  1. kubeadm部署K8S集群v1.16.3

    本次先更新kubeadm快速安装K8S,二进制安装上次没写文档,后续更新,此次最新的版本是V1.16.3 1.关闭防火墙.关闭selinux.关闭swapoff -a systemctl stop f ...

  2. 基于JRebel开发的MybatisPlus热加载插件

    前言 前天项目中使用了mybatis-plus,但是搭配Jrebel开发项目时,发现修改mapper的xml,或者mapper方法中的注解,Jrebel并没有能够reload mapper.于是就有了 ...

  3. 【记录】【idea】【mysql】Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezone' property manually.解决问题

    idea连接mysql报错Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezone' property ...

  4. MarkDown的一些基本语法

    Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式. Markdown的语法简洁明了.学习容易,而且功能比纯文本更强,因此有很多人用它写 ...

  5. json工具类(一)——alibaba包

    package com.ruoyi.common.utils.json; import java.util.HashMap; import java.util.List; import java.ut ...

  6. Web应急:网站被植入Webshell

    网站被植入webshell,意味着网站存在可利用的高危漏洞,攻击者通过利用漏洞入侵网站,写入webshell接管网站的控制权.为了得到权限 ,常规的手段如:前后台任意文件上传,远程命令执行,Sql注入 ...

  7. 【须弥SUMERU】分布式安全服务编排实践

    一.概要 1.分布式安全服务编排概念 2.须弥(Sumeru)关键实现思路 3.应用场景 二.前言 在笔者看来,安全防御的本质之一是增加攻击者的攻击成本,尤其是时间成本.那么从防御的角度来说,如何尽早 ...

  8. Linux 笔记 - 第二十四章 配置 Tomcat

    一.前言 Tomcat 是 Apache 软件基金会(Apache Software Foundation)Jakarta 项目中的核心项目,由 Apache.Sun 和其他一些公司及个人共同开发.使 ...

  9. 我得新博客上线了采用Vue+Layui的结合开发,后台采用asp.net mvc

    地址:www.zswblog.xyz 写完这个博客项目我真的很开心! 希望博客园的大佬们能去看看,如果可以希望帮我在Layui的年度案例点一个赞,谢谢! 地址:https://fly.layui.co ...

  10. Asp.Net页面刷新防止跳转到其他浏览器或新的选项卡

    前端页面js代码: <head> <script> window.name = "PremaritalCheckup_ManSocietyAgreeForm" ...