Python爬虫5.2 — scrapy框架pipeline模块的使用

综述

本系列文档用于对Python爬虫技术的学习进行简单的教程讲解,巩固自己技术知识的同时,万一一不小心又正好对你有用那就更好了。
Python 版本是3.7.4

上一篇文章我们简单入门了Scrapy框架,并且使用Scrapy框架实现了一个爬虫项目。这一篇我们就详细的介绍一下Scrapy框架中的pipeline使用方法(虽然上篇文章我们也稍微详细的讲了pipeline存储数据的优化方式,这篇我们主要讲解如果一个项目多个爬虫,如何使用一个pipeline进行接收数据的问题)。

pipeline核心方法

我们可以自定义Pipeline,只需要实现指定的方法,其中必须要实现的一个方法是:process_item(item, spider)

另外还有如下几个比较实用的方法:

  • open_spider(spider)
  • close_spider(spider)
  • close_spider()方法是在Spider关闭的时候自动调用的。在这里我们可以做一些收尾工作,如关闭数据库连接等。其中,参数spider就是被关闭的Spider对象。
  • from_crawler(cls, crawler)

process_item(item, spider)

process_item()是必须要实现的方法,被定义的ItemPipeline会默认调用这个方法对Item进行处理。比如,我们可以进行数据处理或者将数据写入到数据库等操作。它必须返回Item类型的值或者抛出一个DropItem异常

close_spider(spider)

open_spider()方法是在Spider开启的时候被自动调用的。在这里我们可以做一些初始化操作,如开启数据库连接等。其中,参数spider就是被开启的Spider对象。

close_spider(spider)

close_spider()方法是在Spider关闭的时候自动调用的。在这里我们可以做一些收尾工作,如关闭数据库连接等。其中,参数spider就是被关闭的Spider对象。

from_crawler(cls, crawler)

from_crawler()方法是一个类方法,用@classmethod标识,是一种依赖注入的方式。它的参数是crawler,通过crawler对象,我们可以拿到Scrapy的所有核心组件,如全局配置的每个信息,然后创建一个Pipeline实例。参数cls就是Class,最后返回一个Class实例。

使用pipeline

从pipeline的字典形式可以看出来,pipeline可以有多个,而且确实pipeline能够定义多个。

为什么需要多个pipeline:

  1. 一个spider的内容可能要做不同的操作,比如存入不同的数据库中
  2. 可能会有多个spider,不同的pipeline处理不同的item的内容

注意:

  1. 使用pipeline需要在setting.py中进行配置
  2. pipeline的权重值越小优先级越高
  3. pipeline中process_item不能修改为其他名称

一个spider多个item类型结构情况

我们使用命令创建一个spider程序:

scrapy genspider qsbk_spider qiushibaike.com

将需要配置的信息配置好,这里不再说明。然后在qsbk_spider.py中写入如下代码:

import scrapy


class QsbkSpiderSpider(scrapy.Spider):
    name = 'qsbk_spider'
    allowed_domains = ['qiushibaike.com']
    start_urls = ['http://qiushibaike.com/']

    def parse(self, response):
        item = {}
        # 我们进行奇数偶数的不同参数处理
        for i in range(0, 50):
            if (i % 2) == 0:
                # 偶数处理
                item['come_from'] = 'oushu'
                item['data'] = i
            else:
                # 奇数处理
                item['come_from'] = 'jishu'
                item['data'] = i
            yield item

然后再pipelines.py中写入如下代码:

class MyspiderPipeline(object):
    def process_item(self, item, spider):

        # 增加if判断传来的item是什么数据,然后进行相对应的逻辑判断
        if item['come_from'] == 'jishu':
            # code..
            print('%d 是奇数' % item['data'])
        else:
            # code ..
            print('%d 是偶数' % item['data'])

        return item

运行成功即可查看效果。或者在pipeline定义多个类,代码如下:

class MyspiderPipeline(object):
    def process_item(self, item, spider):

        # 增加if判断传来的item是什么数据,然后进行相对应的逻辑判断
        if item['come_from'] == 'jishu':
            # code..
            print('%d 是奇数' % item['data'])

        return item


class MyspiderPipeline1(object):
    def process_item(self, item, spider):
        # 增加if判断传来的item是什么数据,然后进行相对应的逻辑判断
        if item['come_from'] == 'oushu':
            # code..
            print('%d 是偶数' % item['data'])

        return item

然后再配置文件中配置:

ITEM_PIPELINES = {
    'mySpider.pipelines.MyspiderPipeline': 300,
    'mySpider.pipelines.MyspiderPipeline1': 301,
}

运行可以查看到同样的效果。

多个spider情况

多个spider我们也可以使用上面的那种方式进行处理,再item中增加数据标识,然后根据标识进行不同的处理。除上述外,我们还可以使用另一种方式判断。具体使用方法如下:

我分别使用三个命令创建了三个spider程序:

# 爬取糗百的“文字”模块
scrapy genspider qsbk1_spider qiushibaike.com
# 爬取糗百的“糗图”模块
scrapy genspider qsbk2_spider qiushibaike.com
# 爬取糗百的“穿越模块”
scrapy genspider qsbk3_spider qiushibaike.com

分别运行完三条创建爬虫命令之后,你会在spider文件夹下发现新增了qsbk1_spider.pyqsbk2_spider.pyqsbk3_spider.py三个文件,这就是我们新建的三个爬虫模块文件(项目目录结构就不在这里贴了)。可以通过命令scrapy list查看项目中创建的爬虫列表。

在三个文件中分别写入如下代码:

  1. qsbk1_spider.py
    import scrapy
    
    
    class Qsbk1SpiderSpider(scrapy.Spider):
        name = 'qsbk1_spider'
        allowed_domains = ['qiushibaike.com']
        start_urls = ['https://www.qiushibaike.com/text/']
    
        def parse(self, response):
            item = {}
            # 这是qsbk1_spider返回的数据
            for i in range(0, 10):
                item['come_from'] = 'qsbk1'
                item['data'] = i
                yield item
    
  2. qsbk2_spider.py
    import scrapy
    
    
    class Qsbk2SpiderSpider(scrapy.Spider):
        name = 'qsbk2_spider'
        allowed_domains = ['qiushibaike.com']
        start_urls = ['https://www.qiushibaike.com/pic/']
    
        def parse(self, response):
            item = {}
            # 这是qsbk2_spider返回的数据
            for i in range(10, 20):
                item['come_from'] = 'qsbk2'
                item['data'] = i
                yield item
    
  3. qsbk3_spider.py
    import scrapy
    
    
    class Qsbk3SpiderSpider(scrapy.Spider):
        name = 'qsbk3_spider'
        allowed_domains = ['qiushibaike.com']
        start_urls = ['https://www.qiushibaike.com/history/']
    
        def parse(self, response):
            item = {}
            # 这是qsbk3_spider返回的数据
            for i in range(20, 30):
                item['come_from'] = 'qsbk3'
                item['data'] = i
                yield item
    

最后三个爬虫爬取的数据都放到了pipeline中,这就需要我们在pipeline中进行判断是那个爬虫传过来的数据。pipelines.py代码如下:

class MyspiderPipeline(object):
    def process_item(self, item, spider):

        # 这是我们可以根据spider来进行判断
        if spider.name == 'qsbk1_spider':
            print("这是qsbk1的数据:", item)
        elif spider.name == 'qsbk2_spider':
            print("这是qsbk2的数据:", item)
        elif spider.name == 'qsbk3_spider':
            print("这是qsbk3的数据:", item)
        else:
            print('未知数据')
        return item

运行爬虫即可看到相应的打印效果。

使用多个items进行区分

编写items.py代码如下:

import scrapy


class Qsbk1Item(scrapy.Item):
    """
    qsbk1爬虫items类
    """
    num = scrapy.Field()


class Qsbk2Item(scrapy.Item):
    """
    qsbk2爬虫items类
    """
    num = scrapy.Field()


class Qsbk3Item(scrapy.Item):
    """
    qsbk3爬虫items类
    """
    num = scrapy.Field()

编写qsbk1_spider.py代码如下(其他两个爬虫类似):

import scrapy
# 引入对应的items类
from mySpider.items import Qsbk1Item


class Qsbk1SpiderSpider(scrapy.Spider):
    name = 'qsbk1_spider'
    allowed_domains = ['qiushibaike.com']
    start_urls = ['https://www.qiushibaike.com/text/']

    def parse(self, response):
        for i in range(0, 10):
            item = Qsbk1Item(num=i)
            yield item

编写pipeline.py代码如下:

# 引入对应的items类
from mySpider.items import Qsbk1Item
from mySpider.items import Qsbk2Item
from mySpider.items import Qsbk3Item


class MyspiderPipeline(object):
    def process_item(self, item, spider):

        # 这是我们可以根据items类来进行判断
        if isinstance(item, Qsbk1Item):
            print("这是qsbk1的数据:", item)
        elif isinstance(item, Qsbk2Item):
            print("这是qsbk2的数据:", item)
        elif isinstance(item, Qsbk3Item):
            print("这是qsbk3的数据:", item)
        else:
            print('未知数据')
        return item

运行爬虫即可看到效果

其他博文链接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章