scrapy----使用Item Loaders对item数据进行提取和解析

1.为什么要使用Item Loaders?它有什么优点呢?

原因:

之前的方式,是将数据的提取和解析混合在一起,但是Item Loaders是将这两个部分分开处理了;爬虫文件name.py中只负责数据的提取;items.py文件负责数据的整理;(可以实现数据解析代码的重用。相当于将功能相同的解析函数封装成为一个公用的函数,任何爬虫需要这个函数,都可以来调用)

优点:

(1). 使关于数据的提取代码更加简洁,结构更加清晰;

(2). 可以实现数据解析(整理)部分的代码的重用;

(3). 提高代码的可维护性;

2.Item Loaders的执行流程

  (1). 当创建item对象(item=XXXXItem())的时候,会去items.py文件中初始化对应的input/output_processor处理器;
  (2). 当item中的处理器初始化完成,回到name.py爬虫文件中,创建item_loader对象;
  (3). item_loader对象创建完成,开始通过add_xpath/add_css/add_value收集数据;
  (4). 每收集到一个数据,就会将该数据传递给对应字段对应的input_processor绑定的函数进行数据的处理;数据处理完成,会暂时保存在ItemLoader中;
 (5). 循环第4步,将每一个字段的数据提取并交给input_processor,直到所有数据提取完毕,所有数据都会被保存在ItemLoader中;

 (6). 调用load_item()函数,给item对象进行赋值;

3.以伯乐在线为例,代码如下

扫描二维码关注公众号,回复: 2136730 查看本文章
bole.py

from scrapy.loader import ItemLoader
item_loader = ItemLoader(item=JobboleItem(), response=response)
        item_loader.add_xpath('title', '//div[@class="entry-header"]/h1/text()')
        item_loader.add_xpath('date_time', '//p[@class="entry-meta-hide-on-mobile"]/text()')
        item_loader.add_xpath('tags', '//p[@class="entry-meta-hide-on-mobile"]/a/text()')
        item_loader.add_xpath('content', '//div[@class="entry"]//text()')
        item_loader.add_xpath('zan_num', '//div[@class="post-adds"]/span[contains(@class, "vote-post-up")]//text()')
        item_loader.add_xpath('keep_num', '//div[@class="post-adds"]/span[contains(@class, "bookmark-btn")]/text()')
        item_loader.add_xpath('comment_num', '//div[@class="post-adds"]/a/span/text()')
        item_loader.add_value('img_src', [response.meta['img_src']])
        item = item_loader.load_item()
        yield item
items.py

from scrapy.contrib.loader.processor import Join, MapCompose, TakeFirst

def convert_datetime(value):
    # 将字符串类型转化成datetime类型
    value = value.replace('·', '').strip()
    try:
        # strptime(时间字符串,转化后的格式): 函数返回值是datetime类型的对象
        date_time = datetime.strptime(value, '%Y/%m/%d')
    except:
        # 如果转化失败,将当前时间作为默认值。
        date_time = datetime.now()

    return date_time


def convert_tags(value):
    # ['自由职业', '1 评论', '职业']
    # 过滤 "评论"
    if "评论" in value:
        return ""
    return value


def zan_number(value):
    # ['','1','赞']
    if value.strip() != "":
        pattern = re.compile(r'\d+')
        num = re.findall(pattern, value)
        if num:
            num = int(num[0])
        else:
            num = 0
        return num


def get_number(value):
    # 提取评论、点赞数
    pattern = re.compile(r'\d+')
    num = re.findall(pattern, value)
    if num:
        num = int(num[0])
    else:
        num = 0
    return num

class JobboleItem(scrapy.Item):
    title = scrapy.Field(
        # MapCompose映射类,可以将ItemLoader传递过来的列表中的元素,依次作用到input_test_title函数上,类似于map()函数。
        # input_processor=MapCompose(input_test_title),
        # Join(): 对列表进行合并,add_xpath/add_css/add_value传过来的列表数据。
        # output_processor=TakeFirst()
    )
    date_time = scrapy.Field(
        input_processor=MapCompose(convert_datetime),
        # TakeFirst(): 获取列表中的首个元素
        output_processor=TakeFirst()
    )
    tags = scrapy.Field(
        input_processor=MapCompose(convert_tags),
        output_processor=Join()
    )
    content = scrapy.Field(
        output_processor=Join()
    )
    zan_num = scrapy.Field(
        # ['', '1', ' 赞']
        input_processor=MapCompose(zan_number),
        output_processor=TakeFirst()
    )
    keep_num = scrapy.Field(
        input_processor=MapCompose(get_number),
        output_processor=TakeFirst()
    )
    comment_num = scrapy.Field(
        input_processor=MapCompose(get_number),
        output_processor=TakeFirst()
    )
    # 图片的源地址
    img_src = scrapy.Field()
    # 图片在本地的下载路径, 该字段只有在图片下载完成以后,才能进行赋值。
    img_path = scrapy.Field()




猜你喜欢

转载自blog.csdn.net/qq_38661599/article/details/80995032