欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-08 16:01:02
...

综述

本系列文档用于对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

运行爬虫即可看到效果

其他博文链接