爬虫框架Scrapy(3)使用Item封装数据

news/2024/7/19 12:09:28 标签: python, 爬虫

文章目录

    • 使用 Item 封装数据
      • (一)Item 基类
        • 1. 自定义 Item
        • 2. 拓展 Item
      • (二)Field 元数据
      • (三)在多个爬虫里使用 Item

使用 Item 封装数据

我们首先来看上一篇文章在最后所写的那个实例中的 spider.py :

python">import scrapy


class BooksSpider(scrapy.Spider):
    name = 'books'
    allowed_domains = ['books.toscrape.com']
    start_urls = ['http://books.toscrape.com/']

    def parse(self, response):
        # 提取数据
        for book in response.css('article.product_pod'):
            name = book.xpath('./h3/a/@title').extract_first()
            price = book.css('p.price_color::text').extract_first()
            yield {
                'name': name,
                'price': price,
            }

        # 提取链接
        next_url = response.css('ul.pager li.next a::attr(href)').extract_first()
        if next_url:
            next_url = response.urljoin(next_url)
            yield scrapy.Request(next_url, callback=self.parse)

在该案例中,我们使用了 Python 字典存储一本书的信息,但字典可能有以下缺点:

  • 无法一目了然地了解数据中包含哪些字段,影响代码可读性;
  • 缺乏对字段名字的检测,容易因程序员的笔误而出错;
  • 不便于携带元数据(传递给其他组件的信息)。

为解决上述问题,在 Scrapy 中可以使用自定义的 Item 类封装爬取到的数据。

(一)Item 基类

1. 自定义 Item

Scrapy提供了 Item 和 Field 类,可以用他们自定义数据类,封装爬取到的数据。

  • Item:自定义数据类的基类
  • Field:描述自定义数据类包含那些字段

自定义一个数据类,只需要继承 Item,并创建一系列 Field 对象的类属性。例如,在前面的示例中,我们使用 Item 基类封装数据如下:

python">from scrapy import Item, Field

class BookItem(Item): 
    name = Field()
    price = Field()

Item 支持字典接口,因此 BookItem 在使用上和 Python 字典类似。因此,访问 BookItem 对象中的字段与访问字典类似。

修改之前的 BooskSpider,使用 BookItem 替代 Python 字典,代码如下:

python">from ..items import BookItem

class BooksSpider(scrapy.Spider):
    ...
    def parse(self,response):
        for sel in response.css('article.product_pod'):
            book = BookItem()
            book['name'] = sel.xpath('./h3/a/@title').extract_first()
            book['price'] = sel.css('p.price_color::text').extract_first()
            yield book
    ...

2. 拓展 Item

根据需求对已有的自定义数据类(Item子类)进行拓展。例如:toscrapy 项目中又添加了一个新的 Spider,它负责另一个网站爬取信息:

python"># 继承BookItem,定义一个ForeigenBookItem类,在其中添加一个翻译字段
class ForeignBookItem(BookItem):
    translator = Field()

该类 ForeignBookItem 也可以在对应的爬虫文件里使用。

(二)Field 元数据

数据由 Spider 交给 Scrapy 引擎后,可能会被传递给其他组件 (Item Pipeline、Exporter) 处理。可以使用 Field 的元数据传递额外的信息给处理数据的某个组件(例如告诉组件以何种方式处理数据)。访问一个 Item 对象的 fields 属性,将得到一个包含所有 Field 对象的字典;Field 是 Python 字典的子类,可以通过键值对获取 Field 对象中的元素。

接下来,看一个应用 Field 元数据的实际例子。假设我们要把爬取到的书籍信息写入 CSV 文件,那每一项数据最终由Scrapy 提供的 CsvItemExporter 写入文件,在爬取过程中提取到的信息并不总是一个字符串,有时可能是一个字符串列表,例如:

book['authors'] = ['李雷', '韩梅梅', '吉姆']

但在写入 CSV 文件时,需要将列表内所有字符串串行化成一个字符串,串行化的方式有很多种,例如:

1. '李雷|韩梅梅|吉姆' # '|'.join(book['authors']) 
2. '李雷;韩梅梅;吉姆' # ';'.join(book['authors']) 
3. "['李雷', '韩梅梅', '吉姆']" # str(book['authors'])

我们可以通过 authors 字段的元数据告诉 CsvItemExporter 如何对 authors 字段串行化:

class BookItem(Item):
	...
	authors = Field(serializer=lambda x: '|'.join(x))
	...

其中,元数据的键 serializer 是 CsvItemExporter 规定好的,它会用该键获取元数据,即一个串行化函数对象,并使用这个串行化函数将 authors 字段串行化成一个字符串。

(三)在多个爬虫里使用 Item

例如有两个爬虫:腾讯爬虫和京东爬虫,使用 Item 的方法如下:

  • Step 1:在 items.py 里面创建不同的类,分别保存各自的字段

    python">class TencentItem(scrapy.Item):
        """腾讯爬虫要爬取的字段"""
        """定义好字段,并不代表真正的值,只是占一个位置,用的时候直接赋值就行"""
        position = scrapy.Field()
        category = scrapy.Field()
        date = scrapy.Field()
    
    class JdItem(scrapy.Item):
        """京东爬虫要爬取的字段"""
        """定义好字段,并不代表真正的值,只是占一个位置,用的时候直接赋值就行"""
        position = scrapy.Field()
        category = scrapy.Field()
        date = scrapy.Field()
    
  • Step 2:然后在不同的爬虫程序里使用对应的类即可

    在腾讯的爬虫里,导入和使用 Item

    python">import scrapy
    from tencent.items import TencentItem
    
    class TencentSpiderSpider(scrapy.Spider):
        ...
        def parse(self, response):
            pass
            for tr in tr_list:
                """使用定义好的腾讯爬虫的类的字段"""
                item = TencentItem()
                yield item
    

    在京东的爬虫中,同样的用法

    python">import scrapy
    from JD.items import JdItem
    
    class JdSpiderSpider(scrapy.Spider):
        ...
        def parse(self, response):
            pass
            for tr in tr_list:
                """使用定义好的腾讯爬虫的类的字段"""
                item = JdItem()
                yield item
    
  • Step 3:对于多个爬虫,在pipelines,py中可以进行判断,分别对不同的爬虫的字段进行不同的处理。isinstance()函数就是用来判断一个对象是否是一个已知的类型

    python">from tencent.items import TencentItem, JdItem
    
    class TencentPipeline(object):
        def process_item(self, item, spider):
            '''针对与不同的爬虫字段类的对象,做不同的处理'''
            if isinstance(item, TencentItem):
                ...
            if isinstance(item, JdItem):
                ...
            return item
    

上述文章内容如有错误,欢迎各位读者在评论区留言!


http://www.niftyadmin.cn/n/1190204.html

相关文章

Css display值与解释

Css display值与解释-(详细可见CSS手册的CSS display手册)参数:block :块对象的默认值。用该值为对象之后添加新行none :隐藏对象。与visibility属性的hidden值不同,其不为被隐藏的对象保留其物理空间inline :内联对象的默认值。用…

爬虫框架Scrapy(4)Spider的用法

文章目录一. Spider 的用法1. Spider 运行流程2. Spider 类分析二. 请求与响应1. Request 对象2. Response 对象一. Spider 的用法 在 Scrapy 中,要抓取网站的链接配置、抓取逻辑、解析逻辑里其实都是在 Spider 中配置的。本节我们就专门了解一下 Spider 的基本用法…

爬虫框架Scrapy(5)DownLoader Middleware 的用法

文章目录四. DownLoader Middleware 的用法1. 使用说明2. 核心方法3. 项目实战四. DownLoader Middleware 的用法 Downloader Middleware 即下载中间件,它是处于 Scrapy 的 Request 和 Response 之间的处理模块。Scheduler 从队列中拿出一个 Request 发送给 Downlo…

隐藏Tengine的版本信息

http {.....server_tokens on;server_info on;server_tag bass;reset_timedout_connection on;keepalive_timeout 120;keepalive_requests 100;sendfile on;tcp_nodelay on;tcp_nopush off;..... }当网页不存在时会显示如下图: 修改为: serv…

爬虫框架Scrapy(6)Spider Middleware 的用法

文章目录五. Spider Middleware 的用法1. 使用说明2. 核心方法五. Spider Middleware 的用法 Spider Middleware 是介入到 Scrapy 的 Spider 处理机制的钩子框架。当 Downloader 生成 Response 之后,Response 会被发送给 Spider,在发送给 Spider 之前&a…

android graphic(15)—fence

为何须要fence fence怎样使用 软件实现的opengl 硬件实现的opengl 上层使用canvas画图 上层使用opengl画图 下层合成 updateTexImage doComposeSurfaces DisplayDevice和FramebufferSurface 关于fence。不错的參考文章http://blog.csdn.net/jinzhuojun/article/details/…

爬虫框架Scrapy(7)Itme Pipeline 的用法

文章目录一. Itme Pipeline 的用法1. 实现 Item Pipeline2. 核心方法(1)process_item(item, spider)(2)open_spider(self, spider)(3)close_spider(spider)(4)from_crawler(cls, cra…

Vue.js 基础指令实例讲解(各种数据绑定、表单渲染大总结)——新手入门、高手进阶第一篇...

Vue.js 是一套构建用户界面的渐进式框架。他自身不是一个全能框架——只聚焦于视图层。因此它非常容易学习,非常容易与其它库或已有项目整合。在与相关工具和支持库一起使用时,Vue.js 也能完美地驱动复杂的单页应用。他的语法和 AngularJS特别相像&#…