+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2019-07(3)

2019-08(102)

2019-09(104)

2019-10(17)

2019-11(10)

2019-12(16)

2020-01(30)

2020-02(17)

爬虫(十六):Scrapy框架(三) Spider Middleware、Item Pipeline

发布于2020-02-10 14:50     阅读(417)     评论(0)     点赞(30)     收藏(3)


作者:@小灰灰
本文为作者原创,转载请注明出处:https://www.cnblogs.com/liuhui0308/p/12127771.html


1. Spider Middleware

Spider Middleware是介入到Scrapy的Spider处理机制的钩子框架。

当Downloader生成Response之后,Response会被发送给Spider,在发送给Spider之前,Response会首先经过Spider Middleware处理,当Spider处理生成Item和Request之后,Item Request还会经过Spider Middleware的处理。

Spider Middleware有三个作用:

  • 我们可以在Downloader生成的Response发送给Spider之前,也就是在Response发送给Spider之前对Response进行处理。
  • 我们可以在Spider生成的Request发送给Scheduler之前,也就是在Request发送给Scheduler之前对Request进行处理。
  • 我们可以在Spider生成的Item发送给Item Pipeline之前,也就是在Item发送给Item Pipeline之前对Item进行处理。

1.1 使用说明

需要说明的是,Scrapy其实已经提供了许多Spider Middleware,它们被SPIDER_MIDDLEWARES_BASE这个变盘所定义。

SPIDER_MIDDLEWARES_BASE变量的内容如下:

复制代码
{
    'scrapy.spidermiddlewares.httperror.HttpErrorMiddleware':50,
    'scrapy spidermiddlewares offsite Of site iddleware':500,
    'scrapy.spidermiddlewares.referer.RefererMiddleware':700,
    'scrapy.spidermiddlewares.urllength.UrllengthMiddleware':800,
    'scrapy.spidermiddlewares.depth.DepthMiddleware':900,
}
复制代码

和Downloader Middleware一样,Spider Middleware首先加入到SPIDER_MIDDLEWARES设置中,该设置会和Scrapy中SPIDER_MIDDLEWARES_BASE定义的Spider Middleware合并。然后根据键值的数字优先级排序,得到一个有序列表。第一Middleware是最靠近引擎的,最后一个Middleware是最靠近Spide的。

1.2 核心方法

Scrapy内置的Spider Middleware为Scrapy提供了基础的功能。如果我们想要扩展其功能,只需要实现某几个方法即可。

每个Spider Middleware都定义了以下一个或多个方法的类,核心方法有如下4个。

  • process_spider_input(response,spider)
  • process_spider_output(response,result,spider)
  • process_spider_exception(response,exception,spider)
  • proce ss_start_requests(start_requests,spider)

只需要实现其中一个方法就可以定义一个Spider Middleware。

(1) process_spider_input(response,spider)

当Response被Spider Middleware处理时,process_spider_input()方法被调用。

process_spider_input()方法的参数有如下两个:

response,是Response对象,即被处理的Response。

spider,是Spider对象,即该Response对应的Spider。

process_spider_input()应该返回None或者抛出一个异常。

如果它返回None,Scrapy将会继续处理该Response,调用所有其他的Spider Middleware,直到Spider处理该Response。

如果它抛出一个异常,Scrapy将不会调用任何其他Spider Middleware的process_spider_input()方法,而调用Request的errback()方法。errback的输出将会被重新输入到中间件中,使用process_spider_output()方法来处理,当其抛出异常时则调用process_spider_exception()来处理。

(2) process _spider_output(response,result,spider)

当Spider处理Response返回结果时,process_spider_output()方法被调用。process_spider_output()方法的参数有如下三个:

response,是Response对象,即生成该输出的Response。

result,包含Request或Item对象的可迭代对象,即Spider返回的结果。

spider,是Spider对象,即其结果对应的Spider。

process_spider_output()必须返回包含Request或Item对象的可迭代对象。

(3) process_spider_exception(response,exception,spider)

当Spider或Spider Middleware的process_spider_input()方法抛出异常时,process_spider_exception()方法被调用。

process_spider_exception()方法的参数有如下三个:

response,是Response对象,即异常被抛出时被处理的Response。

exception,是Exception对象,即被抛出的异常。

spider,是Spider对象,即抛出该异常的Spider。

process_spider_exception()必须要么返回None,要么返回一个包含Response或Item对象的可迭代对象。

如果它返问None,Scrapy将继续处理该异常,调用其他Spider Middleware中的process_spider_exception()方法,直到所有Spider Middleware都被调用。

如果它返回一个可迭代对象,Spider Middleware的process_spider_output()方法被调用,其他的process_spider_exception()不会被调用。

(4) process_start_requests (start_requests,spider)

process_start_requests()方法以Spider启动的Request为参数被调用,执行的过程类似于process_spider_output(),只不过它没有相关联的Response并且必须返回Request。

proces s_start_requests()方法的参数有如下两个:

start_requests,是包含Request的可迭代对象,即Start Requests。

spider,是Spider对象,即Start Requests所属的Spider。

process_start_requests()必须返回另一个包含Request对象的可迭代对象。

2. Item Pipeline

Item Pipeline是项目管道。

Item Pipeline的调用发生在Spider产生Item之后。当Spider解析完Response之后,Item就会传递到Item Pipeline,被定义的Item Pipeline组件会依次调用,完成一连串的处理过程,比如数据清洗、存储等。

Item Pipeline主要功能有四点:

清理HTML数据。

验证爬取数据,检查爬取字段。

查重并丢弃重复内容。

将爬取结果保存到数据库。

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

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

open_spider(spider)

close_spider(spider)

from_crawler(cls,crawler)

2.1 常用方法

(1) process_item(item,spider)

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

process_itern()方法的参数有两个:

item,是Item对象,即被处理的Item。

Spider,是Spider对象,即生成该Item Spider。

process_item()方法的返回类型归纳如下:

如果它返回的是Item对象,那么此Item会被低优先级的Item Pipeline的process_item()方法处理,直到所有的方法被调用完毕。

如果它抛出的是DropItem异常,那么此Item会被丢弃,不再进行处理。

(2) open_spider(self,spider)

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

(3) close_spider(spider)

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

(4) from_crawler(cls,crawler)

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

2.2 管道示例

(1) 价格验证和删除没有价格的商品

调整price那些不包含增值税(price_excludes_vat属性)的项目的属性,并删除那些不包含价格的项目:

复制代码
from scrapy.exceptions import DropItem

class PricePipeline(object):

    vat_factor = 1.15

    def process_item(self, item, spider):
        if item.get('price'):
            if item.get('price_excludes_vat'):
                item['price'] = item['price'] * self.vat_factor
            return item
        else:
            raise DropItem("Missing price in %s" % item)
复制代码

(2) 将项目写入JSON文件

将所有已删除的项目存储到一个items.json文件中,每一行包含一个以JSON格式序列化的项目:

复制代码
import json

class JsonWriterPipeline(object):

    def open_spider(self, spider):
        self.file = open('items.json', 'w')

    def close_spider(self, spider):
        self.file.close()

    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + "\n"
        self.file.write(line)
        return item
复制代码

(3) 将项目写入MongoDB

在这个例子中,我们将使用pymongo将项目写入MongoDB。MongoDB地址和数据库名称在Scrapy设置中指定;MongoDB集合以item类命名。

复制代码
import pymongo

class MongoPipeline(object):

    collection_name = 'scrapy_items'

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'),
            mongo_db=crawler.settings.get('MONGO_DATABASE', 'items')
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        self.db[self.collection_name].insert_one(dict(item))
        return item
复制代码

(4) 截取项目的截图

从process_item()方法返回Deferred。它使用Splash渲染项目URL的屏幕截图。Pipeline向本地运行的Splash示例发出请求。下载请求并延迟回调激活后,它会将项目保存到文件并将文件名添加到项目中。

复制代码
import scrapy
import hashlib
from urllib.parse import quote


class ScreenshotPipeline(object):
    """Pipeline that uses Splash to render screenshot of
    every Scrapy item."""

    SPLASH_URL = "http://localhost:8050/render.png?url={}"

    def process_item(self, item, spider):
        encoded_item_url = quote(item["url"])
        screenshot_url = self.SPLASH_URL.format(encoded_item_url)
        request = scrapy.Request(screenshot_url)
        dfd = spider.crawler.engine.download(request, spider)
        dfd.addBoth(self.return_item, item)
        return dfd

    def return_item(self, response, item):
        if response.status != 200:
            # Error happened, return item.
            return item

        # Save screenshot to file, filename will be hash of url.
        url = item["url"]
        url_hash = hashlib.md5(url.encode("utf8")).hexdigest()
        filename = "{}.png".format(url_hash)
        with open(filename, "wb") as f:
            f.write(response.body)

        # Store filename in item.
        item["screenshot_filename"] = filename
        return item
复制代码

(5) 重复过滤

一个过滤器,用于查找重复项目,并删除已处理的项目。假设我们的项目具有唯一ID,但我们的spider会返回具有相同ID的多个项目:

复制代码
from scrapy.exceptions import DropItem

class DuplicatesPipeline(object):

    def __init__(self):
        self.ids_seen = set()

    def process_item(self, item, spider):
        if item['id'] in self.ids_seen:
            raise DropItem("Duplicate item found: %s" % item)
        else:
            self.ids_seen.add(item['id'])
            return ite
复制代码


所属网站分类: 技术文章 > python文章

作者:python好学吗

链接: http://www.pythonheidong.com/blog/article/230410/

来源:python黑洞网 www.pythonheidong.com

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

30 0

赞一赞 or 踩一踩

收藏该文
已收藏

评论内容:(最多支持255个字符)

相似文章

  5171. 最接近的因数

  Python实现生成西瓜数据集的Excel文件

  Leetcode - 删除排序数组中的重复项

  python第五天-字符串

  数据结构|LeetCode(力扣)经典题:队列

  python学习笔记(3)

  TYD_初识python数据可视化库-Matplotlib

  Scrapy安装与应用教程

  python实现修改文件中的内容

  mac环境下python3.6安装pyhanlp工具包

优质资源排行榜

 python经典电子书大合集下载 下载次数 8138

 零基础java开发工程师视频教程全套,基础+进阶+项目实战(152G) 下载次数 7550

 零基础前端开发工程师视频教程全套,基础+进阶+项目实战(共120G) 下载次数 7442

 零基础大数据全套视频400G 下载次数 7006

 零基础php开发工程师视频教程全套,基础+进阶+项目实战(80G) 下载次数 6893

 零基础软件测试全套系统教程 下载次数 6506

 全套人工智能视频+pdf 下载次数 6443

 IOS全套视频教程 基础班+就业班 下载次数 4680

 编程小白的第一本python入门书(高清版)PDF下载 下载次数 3648

10  effective python编写高质量Python代码的59个有效方法 pdf下载 下载次数 3361

11  Python深度学习 pdf下载 下载次数 3156

12  笨办法学python pdf下载 下载次数 3087

13  Python Cookbook第三版中文PDF下载高清完整扫描原版 下载次数 3024

14  树莓派Python编程指南 pdf下载 下载次数 3011

15  python从入门到精通视频(全60集)python视频教程下载 下载次数 3009

16  python项目开发视频 下载次数 3002

17  使用python+pygame开发的小游戏《嗷大喵快跑》源码下载 下载次数 3000

18  黑马2017年java就业班全套视频教程 下载次数 2992

19  Python基础教程 pdf下载 下载次数 2988

20  python实战项目 平铺图像板系统源码下载,适用于想要保存,标记和共享图像,视频和网页的用户 下载次数 2987

21  利用python实现程序内存监控脚本 下载次数 2987

22  老男孩python自动化视频 下载次数 2983

23  老王python基础+进阶+项目视频教程 下载次数 2974

24  尚硅谷Go学科全套视频 下载次数 2972

25  某硅谷Python项目+AI课程+核心基础视频教程 下载次数 2968

26  Web前端实战精品课程 下载次数 2967

27  Python算法教程_中文版 pdf下载 下载次数 2966

28  tron python小游戏 下载次数 2963

29  [小甲鱼]零基础入门学习Python 下载次数 2962

30  老男孩python全栈开发15期 下载次数 2958

31  2017最新web前端开发完整视频教程附源码 下载次数 2948

32  最新全套完整JAVAWEB2018开发视频 下载次数 2926

33  流畅的Python PDF下载高清完整扫描原版 下载次数 2919

34  Spring boot实战视频6套下载 下载次数 2910

35  python全套视频十五期(116G) 下载次数 2908

36  Python高性能编程 pdf下载 下载次数 2906

37  Python项目实战 下载次数 2887

38  30个小时搞定Python网络爬虫 含源码 下载次数 2884

39  简明python教程 (A Byte of Python)pdf下载 下载次数 2884

40  利用Python进行数据分析 pdf下载 下载次数 2884

41  python全自动抢火车票教程-python视频教程下载 下载次数 2883

42  尚硅谷大数据之Hadoop视频 下载次数 2876

43  Python A~B~C~ python视频教程下载 下载次数 2866

44  数据结构与算法视频(小甲鱼讲解-全) 下载次数 2864

45  web小程序表白天数倒计时源码下载 下载次数 2863

46  python基础视频教程 下载次数 2862

47  go语言全套视频 下载次数 2855

48  清华学霸尹成Python爬虫视频-ok 下载次数 2846

49  黑马前端36期最全视频和代码 下载次数 2843

50  2018最新全套web前端视频教程+源码下载 下载次数 2841