在我们执行scrapy爬取字段中,会有大量的和下面的代码,当要爬取的网站多了,要维护起来很麻烦,为解决这类问题,我们可以根据scrapy提供的loader机制

    def parse_detail(self, response):
"""
获取文章详情页
:param response:
:return:
"""
article_item = JoBoleArticleItem() #封面图,使用get方法有个好处,如果图片不存在。不会抛异常。
front_image_url = response.meta.get("front_image_url","")
ret_str = response.xpath('//*[@class="dht_dl_date_content"]')
title = response.css("div.entry-header h1::text").extract_first()
create_date = response.css("p.entry-meta-hide-on-mobile::text").extract_first().strip().replace("·", "").strip()
content = response.xpath("//*[@id='post-112239']/div[3]/div[3]/p[1]")
article_item["title"] = title

首先,导入 ItemLoader

from scrapy.loader import ItemLoader

可以查看源码,这里先关注的是item和response两入参

        #通过item loader加载item
item_loader = ItemLoader(item=JoBoleArticleItem(),response=response)
#针对直接取值的情况
item_loader.add_value('front_image_url','front_image_url')
#针对css选择器
item_loader.add_css('title','div.entry-header h1::text')
item_loader.add_css('create_date','p.entry-meta-hide-on-mobile::text')
item_loader.add_css('praise_num','#112547votetotal::text')
#针对xpath的情况
item_loader.add_xpath('content','//*[@id="post-112239"]/div[3]/div[3]/p[1]')
#把结果返回给item对象
article_item = item_loader.load_item()

debug调试,可以看到拿到的信息

不过实际情况,可能1、我们只取返回结果的某个元素。2、拿到返回结果后还需要执行某些函数。 这个scrapy也提供了方法:

在items.py文件里操作,这里用到了MapCompose类

from scrapy.loader.processors import MapCompose

这个类我们可以传递任意多的函数进来处理

导入模块后,

在Field的入参里可以传入这个函数,方式如下,其中MapCompose里填的是函数名,而调用的这个alter_title函数的入参,就是title的拿到的值,即input_processor参数的效果是在传值给item前进行预处理

def alter_title(value):
return value + "-白菜被猪拱了" class JoBoleArticleItem(scrapy.Item):
#标题
title = scrapy.Field(
input_processor = MapCompose(alter_title)
)

debug调试下,

在loader机制中也有类似extract_firest的方法:TakeFirst

from scrapy.loader.processors import MapCompose,TakeFirst

然后在下面的:

经测试 input_processor和output_processor同时存在时,会把input进行预处理拿到的返回值继续给output处理,返回最终结果给item

import datetime
def date_convert(value):
try :
create_date = datetime.datetime.strftime(value,"%Y/%m/%d").date()
except Exception as e:
create_date = datetime.datetime.now().date() return create_date class JoBoleArticleItem(scrapy.Item):
#标题
title = scrapy.Field(
input_processor = MapCompose(alter_title)
)
#创建日期
create_date = scrapy.Field(
# = MapCompose(date_convert),
input_processor = MapCompose(date_convert),
output_processor = TakeFirst()
)

如果要每个字段都要单独调用这个TakeFirst方法,会有些麻烦,可以通过自定义ItemLoader,首先导入ItemLoader进行重载

from scrapy.loader import ItemLoader

点开ItemLoader源码,可以查看到有个default_output_processor

然后我们给ItemLoader重载这个default_output_processor

class ArticleItemLoader(ItemLoader):
#自定义ItemLoader
default_output_processor = TakeFirst()

然后在创建itemloader对象时使用自定义的loader:ArticleItemLoader

        item_loader = ArticleItemLoader(item=JoBoleArticleItem(),response=response)
#针对直接取值的情况
item_loader.add_value('front_image_url','front_image_url')
item_loader.add_value('front_image_path','')
item_loader.add_value('url',response.url)
item_loader.add_value('url_object_id',get_md5(response.url))
item_loader.add_value('content','')

debug调试,可以看到获取到的value由list变成str

PS:这里只是把默认的output_processor制定了一个方法,所以如果存在某些item 不想调用默认的output_processor,可以继续在add_value方法里单独传output方法。

问题:

1、调试时遇到下面这错误,一般是由于传递给items.py的数据里缺少了字段、传递的字段和数据表里的字段的类型不符等

2

3、使用itemloader爬取时,返回的数据类型是list,再存入item容器前,是支持对数据进行预处理的,即输入处理器和输出处理器,可以通过MapCompose这个类来依次对list的元素进行处理,

但如果lsit为【】则不会进行处理,这种情况需要重载MapCompose类的__call__方法,如下,我给vallue增加一个空的str“”

class MapComposeCustom(MapCompose):
#自定义MapCompose,当value没元素是传入""
def __call__(self, value, loader_context=None):
if not value:
value.append("")
values = arg_to_iter(value)
if loader_context:
context = MergeDict(loader_context, self.default_loader_context)
else:
context = self.default_loader_context
wrapped_funcs = [wrap_loader_context(f, context) for f in self.functions]
for func in wrapped_funcs:
next_values = []
for v in values:
next_values += arg_to_iter(func(v))
values = next_values
return values

第十篇 scrapy item loader机制的更多相关文章

  1. 第三百四十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—craw母版l创建自动爬虫文件—以及 scrapy item loader机制

    第三百四十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—craw母版l创建自动爬虫文件—以及 scrapy item loader机制 用命令创建自动爬虫文件 创建爬虫文件是根据scrap ...

  2. 二十三 Python分布式爬虫打造搜索引擎Scrapy精讲—craw母版l创建自动爬虫文件—以及 scrapy item loader机制

    用命令创建自动爬虫文件 创建爬虫文件是根据scrapy的母版来创建爬虫文件的 scrapy genspider -l  查看scrapy创建爬虫文件可用的母版 Available templates: ...

  3. 第十篇 SQL Server安全行级安全

    本篇文章是SQL Server安全系列的第十篇,详细内容请参考原文. 不像一些其他industrial-strength数据库服务,SQL Server缺乏一个内置保护个别数据记录的机制,称为行级安全 ...

  4. Python开发【第二十篇】:缓存

    Python开发[第二十篇]:缓存redis&Memcache   点击这里 Python之路[第九篇]:Python操作 RabbitMQ.Redis.Memcache.SQLAlchemy ...

  5. [Android] Android 用于异步加载 ContentProvider 中的内容的机制 -- Loader 机制 (LoaderManager + CursorLoader + LoaderManager.LoaderCallbacks)

    Android 用于异步加载 ContentProvider 中的内容的机制 -- Loader 机制 (LoaderManager + CursorLoader + LoaderManager.Lo ...

  6. 【译】第十篇 SQL Server安全行级安全

    本篇文章是SQL Server安全系列的第十篇,详细内容请参考原文. 不像一些其他industrial-strength数据库服务,SQL Server缺乏一个内置保护个别数据记录的机制,称为行级安全 ...

  7. 第四天,同步和异常数据存储到mysql,item loader方法

    github对应代码:伯乐在线文章爬取     一. 普通插入方法 1. 连接到我的阿里云,用户名是test1,然后在navicat中新建数据库

  8. python应用:爬虫框架Scrapy系统学习第四篇——scrapy爬取笔趣阁小说

    使用cmd创建一个scrapy项目: scrapy startproject project_name (project_name 必须以字母开头,只能包含字母.数字以及下划线<undersco ...

  9. [scrapy]Item Loders

    Items Items就是结构化数据的模块,相当于字典,比如定义一个{"title":"","author":""},i ...

随机推荐

  1. SpringBoot2.0拦截器 与 1.X版本拦截器 的实现

    1.5  版本 先写个拦截器,跟xml配置方式一样,然后将拦截器加入spring容器管理 .接着创建 配置文件类 继承 WebMvcConfigurerAdapter 类,重写父类方法addInter ...

  2. 洛谷P1629 邮递员送信 最短路-Djistra

    先上一波题目qwq https://www.luogu.org/problem/P1629· 复习了一波 dijstra 的 priority_queue(优先队列)优化的写法 tips: 求单项路中 ...

  3. vue对象侦测

    http://blog.csdn.net/yihanzhi/article/details/74200618 数组:this.$set(this.arr,index,value)

  4. display: flex属性介绍

    参考文章: 阮大神的:Flexbox 布局的最简单表单(主要讲解项目item上的属性) 另一位大神的:布局神器display:flex(整体讲解的非常详细) 之前没有仔细看flex布局(弹性布局),设 ...

  5. Javascript基础一(介绍)

    Javascript的发展历史: JavaScript在设计之初只是为了做表单验证.但是现如今,JavaScript已经成为了一门功能全面的编程语言,已经是WEB中不可缺少的一部分,如今的JavaSc ...

  6. 微信小程序のwxss选择器

    一.什么是选择器 选择器就是选择标签所用样式的模式,即:以什么方式设置样式. 二.微信小程序的样式选择器 .calss就是选择器的一种 三.选择器的优先级 element表示样式元素:.element ...

  7. teb教程6

    代价地图的转换 简介:本部分关于怎样把代价地图转换插件应用到转换占据栅格costmap2d到几何形状来优化(测试阶段) teb_local_planner包支持costmap_converter插件, ...

  8. vCenter 6.0 如何用client登录

    使用Vmware client  输入vCenter的IP地址 然后用户名使用administrator@vsphere.local 再输入密码,即可登录vCenter了. web端也是一样,但是我遇 ...

  9. 【Javascript DOM读书笔记】chapter8 充实文档内容

    本章目的 作者举出了第一个实例,为一篇 web 页面动态创建缩略语(abbreviation)的列表.大家知道,我们可以使用 <abbr>...</abbr> 来指示一个缩略语 ...

  10. Python爬虫总结——常见的报错、问题及解决方案

    在爬虫开发时,我们时常会遇到各种BUG各种问题,下面是我初步汇总的一些报错和解决方案. 在以后的学习中,如果遇到其他问题,我也会在这里进行更新. 各位如有什么补充,欢迎评论区留言~~~ 问题: IP被 ...