Scrapy 规则化爬虫(2)——Item Loaders

Scrapy 规则化爬虫(2)——Item Loader


目录

  • Scrapy 规则化爬虫(2)——Item Loader
  • 前言
  • 一、Item Loader
    • 参数
    • 方法
  • 二、使用过程
  • 三、处理器
    • 内置处理器方法
    • 优先级
  • 四.Item Loader Context
  • 总结


前言

在scrapy中我们可以利用Item进行保存数据,但是都是由代码构造而成,例如在spider中对需要提取的字段逐个提取并进行解析,数量少可以,但是数量过大不利于后期维护。而Item Loaders给我们提供了更便捷的机制。可以理解为Item是保存数据的容器,Item Loaders是填充数据的机制。

  • Item Loaders可以将提取,解析进行分离
  • spider中只进行数据提取,item中进行解析

一、Item Loader

参数

item:Item对象。可以利用add_xpath,add_css,add_value等方法填充Item

selector:Selector对象。提取填充数据的选择器

response:Response对象。提取的响应对象

方法

#实例化
l = ItemLoader(item=Product(), response=response)
#添加数据
l.add_xpath('字段','xpath')
l.add_css('字段','css')
l.add_value('字段','值')
#替换数据  replace_css,replace_xpath,replace_value
l.replace_value('字段','替换的值')
#返回给定字段的值
l.get_collected_values('字段')
#字段处理,
l.get_css('css',re)
l.get_xpath('xpath',re)
l.get_value('值',re)

#嵌套加载器,用于同一位置的数据放置在一个字段中,例如提取class="name"的所有标签,
l.nested_css('css')

二、使用过程

#在spider中编写
#1.引入
from scrapy.loader import ItemLoader
from myproject.items import Product   #已提前在item中写了Product

def parse(self, response):
#2对ItemLoader实例化.
    l = ItemLoader(item=Product(), response=response)
#3.调用方法进行数据提取
    l.add_xpath('name', '//div[@class="product_name"]')#xpath方式,提取到后会对应字段的input_processor()进行处理,然后暂存在itemloader中。
    l.add_xpath('name', '//div[@class="product_title"]')   #我们从不同位置提取数据也写入了name字段中。
    l.add_xpath('price', '//p[@id="price"]')
    l.add_css('stock', 'p#stock')#css方式
    l.add_value('last_updated', 'today') # value方式,直接将字符串填入
#4.调用load_item()方法将上面收集到的数据分配到Item中
    return l.load_item()


三、处理器

  • 在spider中,我们提取了数据,但是并未进行解析,解析工作我们在item中进行
  • 处理器分为输入处理器,和输出处理器,在上一部分,我们了解了当我们提取数据时,数据就是先经过输入处理器后,才保存在itemloader中的。
  • 当我们调用load_item()分配数据时我们又经过输出处理器。

我们可以通过两种方式定义处理器

#创建loaders.py文件,声明项目处理器
from itemloaders.processors import TakeFirst, MapCompose, Join
from scrapy.loader import ItemLoader

class ProductLoader(ItemLoader):
'''
default_output_processor,default_input_processor是默认处理器
_in:输入处理器
_out:输出处理器
'''
    default_output_processor = TakeFirst()

    name_in = MapCompose(str.title)
    name_out = Join()

    price_in = MapCompose(str.strip)
    ……

#在item中声明输入输出处理器
import scrapy
from itemloaders.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(),
    )

内置处理器方法

from itemloaders.processors import Join, MapCompose, TakeFirst,Compose,Identity,SelectJmes

#(一)Identity:不进行处理,返回原来的数据

#(二)TakeFirse:返回列表第一个非空值,类似于原来的ertract_first,一般用于output_processor
processor = TackFirst()
processor(['',1,2])
print(processor)   #结果是1
 
#(三)Join:将列表内容拼接,默认空格连接
processor = Join()#可设置连接符
processor(['1','2','3'])
print(processor)  #结果:1 2 3

#(四)Compose:多个函数构成的处理器。我们可以传给他多个函数,输入的值将依次经过这些函数处理输出
#遇到None,会停止处理,我们可以添加参数更改:stop_on__none = True
processor = Compose(str.upper,lambda s: s.strip)
processor(' hello world')
print(processor) #结果:HELLO WORLD

#(五)MapCompose:与compose类似,但是可以迭代处理列表值
processor = Compose(str.upper,lambda s: s.strip)
processor([' hello',' world'])
print(processor) #结果:['HELLO','WORLD']

#(六)SelectJmes: 给定key值,查询json中对应的value值,需要安装jsonpath库
from itemloaders.processors import SelectJmes
proc = SelectJmes("foo")
proc({'foo': 'bar'})
print(proc)  #结果:'bar'

优先级

  1. 项目加载器字段特定属性:field_in和field_out(最高优先级)
  2. 字段元数据(input_processor和output_processor键)
  3. 项目加载器默认值:ItemLoader.default_input_processor()和
    ItemLoader.default_output_processor()(最低优先级)

四.Item Loader Context

Item Loader Context是任意键值的字典,它可以被所有input/output处理器之间共享,可以修改input/output处理器的行为。
下面是一个例子,假如我们爬取多个网站,在数据中我们想定义数据源来自那个网站,此时我们可以使用content。

#spider.py
#在实例化时添加content
l = ItemLoader(item,site = response.url)
#我们可以通过l.context查看返回的值

#items.py
def source(value,loader_context):
	site = loader_context.get('site')
	if site == '第一个网站的url':
		return '第一个网站名称'
	else:
		return '第二个网站名称'

#我们可以在输入/输出处理器中使用,这里我们写一个项目处理器
class TestItemLoader(ItemLoader):
	site_in = MapCompose(source)

总结

当我们熟练使用Item Loaders 后,就会发现,它是多么的强大,他可以时我们的逻辑更清晰,维护更方便。
官方文档:Item Loaders

你可能感兴趣的:(scrapy框架,python)