zoukankan      html  css  js  c++  java
  • Scrapy 使用 Item 封装数据、使用 Item Pipline处理数据

    1、Item 和 Field

      Scrapy 提供一下两个类,用户可以使用它们自定义数据类,封装爬取到的数据:

      (1)Item类

        自定义数据类(如 BookItem)的基类

      (2)Field

        用来描述自定义数据类包含那些字段(如 name、age等)

      自定义一个数据类,只需继承 Item ,并创建一系列 Field 对象的类属性(类似 Django 中自定义 Model)即可。以自定义书籍信息 BookItem为例 

    >>>from scrapy import Item, Field
    >>> class BookItem(Item):
        name = Field()
        price = Field(0

      Item 支持字典接口,因此 BookItem 在使用上和 Python 字典类似,可安一下方式创建BookItem对象:

    >>> book = BookItem(name = 'jj', price = 45.0)
    >>> book
    {'name': 'jj', 'price': 45.0}
    >>> book['name']
    'jj'
    >>> book2 = BookItem()
    >>> book2
    {}
    >>> book2['name'] = 'jjj'
    >>> book2['price'] = 32.5
    >>> book2
    {'name': 'jjj', 'price': 32.5}

    2、Item Pipeline 处理数据

      在 Scrapy 中,Item Pipeline 是处理数据的组件,一个 Item Pipeline 就是一个包涵特定接口的类,同城负责一种功能的数据处理,在一个项目中可以同时启用多个 Item Pipeline,他们按指定次序连起来,形成一条数据处理流水线。

      以下就是 Item Pipeline 的几种典型应用:

      (1)清洗数据

      (2)验证数据的有效性

      (3)过滤掉重复的数据

      (4)将数据存入数据库

     通过一个需求来讲解 Item Pipeline 的使用,比我如我们爬取的书籍价格是以英镑为单位的;如果我们期望爬去的书价是人命币价格,就需要用英镑价格乘以汇率算出人命币价格(处理数据),此时可以实现一个接个转换的 Item Pipeline 来完成这个工作。

      实现 Item Pipeline

        在创建 Scrapy 项目时,会自动生成一个 pipeline.py 文件,它用来放置用户自定义的 Item Pipeline:

    class PriceConverPieline(object):
        
        # 英镑兑换人命币汇率
        exchange_rate = 8.5309
    
        def process_item(self, item, spider):
            # 提取 Item 的price字段
            # 去掉前面英镑符号,转换为float 类型,乘以汇率
            price = float(item['price'[1:]])*self.exchange_rate
    
            # 保留 2 为小数,赋值回item的price 字段
            item['price'] = '¥%.2f'% price
    
            return item

    对上面的代码解释如下:

      (1)一个 Item  Pipeline 不需要继承特定的基类,只需要实现某些特定方法,例如 process_item、open_spider、close_spider

      (2)一个Item Pipeline必须实现一个Process_item(item, spider)方法,该该方法用来处理每一项由Spider 爬取的数据,其中的两个参数:

        <1> Item   爬取到的一项数据(Item 或者字典)

        <2> Spider   爬取此项数据的 Spider对象

      上述代码中的 process_item 方法实现非常简单,将书籍的英镑价格转换为浮点数,乘以汇率并保留 2 为小数,然后复制回item的price字段,最后返回被处理过的item

      可以看出,process_item 方法是 Item Pipeline 的核心,对该方法需要做两点补充说明:

        (1)如果process_item 下处理某项 item 时返回了一项数据(item或字典),返回的数据会传递到下一级的 Item Pipeline(如果有)继续处理

        (2)如果process_item 在处理某项 item 时抛出(raise)一个DropItem异常(scrapy.exceptions.DropItem),该项 item 便会被抛弃,不在传递给后面的 Item Ppieline继续处理,也不会导出到文件。通常,我们在检测到无效数据或想要过滤数据时,抛出 DropItem异常。

      除了必须实现process_item方法外,还有3个比较常用的方法,可用于需求选择实现:

      (1)open_spider(self, spider)

        Spider 打开时(处理数据前)回调该方法,同城方法用于在开始处理数据之前完成某些初始化工作,如连接数据库

      (2)close_spider(self, spider)

        Spider 关闭时(处理数据后)回调该方法,同城该方法用于在处理完成数据之后完成某些清理工作,如关闭数据库

      (3)from_crawler(cls, crawler)

        创建 Item Pipeline对象时回调该方法,通常,在该方法中通过 crawler.setting 读取配置,根据配置创建Item Pipeine对象

    3、启用 Item Pipeline

      在 Scrapy 中,Item Pipeline是可选的组件,想要启用某个(或某些)Item Pipeline,需要在配置文件settings.py中进行配置

    ITEM_PIPELINE = {
      'example.pipelines.PriceConverterPipeline' : 300     
    }

    ITEM_PIPELINE 是一个字典,我们想要启用 Item Pipelne添加到这个字典中,其中每一项的键是每一个Item Pipelne类的导入路径,值是 0 ~ 1000 的数字,同事启用多个 Item Pipeline 时,Scrapy根据这些数值决定各 Item Pipeline 处理数据的先后次序,数字小的在前面。使用PriceConverterPipelien对数据处理后,books.csv 中的书价转换为人民币价格

    4、过滤重复数据

      为了确保爬取到的书籍信息中没有重复项,可以实现一个去重 Item Pipeline,这里我们一书名作为主键进行去重,实现DuplicatesPipeline

    from scrapy.ecceptions import DropItem
    
    class DuplicatedPipeline(object):
        
        def __nit__(self):
            self.book_set = set()
    
    
         def process_item(self, item, spider):
             name = item['name']
            if name in self.book_set:
                raise DropItem('Dupliccate book found: %s' % item)
    
            self.book_set.add(name)
            return item

    对上述代码解释如下:

      (1)增加构造方法,在其中初始化用于对书名去重的集合

      (2)在 process_item 方法中, 先取出 item 的 name 字段,检查书名是否已在集合中,如果在,就是重复数据,抛出DropItem异常。将 item 抛弃,否则,将 item的 name 字段存入集合,返回 item 

    5、将数据存入 MongoDB 

      有时,我们想把爬取到的数据存入某种数据库中,可以实现 Item Pipeline完成此类任务

      下面实现一个能将数据存入 MongoDB数据库的 Item Piipeline,代码如下:

    from scrapy.item import import Item
    import pymongo
    
    class MongeDBPipeline(object):
        
        DB_URI = 'mongodb://localhost:27017/'
        DB_NAME = 'scrapy_data'
    
        def open_spider(self, spider):
            self.client = pymongo.MongoClient(self.DB_URI)
    
        def close_spider(self, spider):
            self.client.close()
    
        def process_item(self, spider):
            collection = self.db[spider,name]
            post = dict(item) if isinstance(item, Item) else item
            collection.insert_one(post)
            return item

    对上述代码解释如下:

      (1)在类属性中定义两个常量:

        <1>DB_URI  数据库的 URI 地址

        <2> DB_NAME  数据库的名字

      (2)在Spider整个爬取过程中,数据库的连接和关闭操作只需要进行一次,应在开始处理数据前连接数据库,并在处理完所有数据之后关闭数据路

        <1>open_spider(spider)

        <2> close_spider(spider)

      

  • 相关阅读:
    《python核心编程第二版》第8章习题
    《python核心编程第二版》第7章习题
    虚拟Ip技术如何实现备机容灾
    LeetCode算法编程连载之五
    GIT使用入门篇(管理自已的代码)
    LeetCode算法编程之连载四(二分法)
    LeetCode算法编程之连载三
    LeetCode算法编程之连载二
    LeetCode算法编程之连载一
    Python 使用flush函数将缓冲区数据立即写磁盘
  • 原文地址:https://www.cnblogs.com/jcjc/p/10907295.html
Copyright © 2011-2022 走看看