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

爬虫(十六):Scrapy框架(三) Spider Middleware、Item Pipeline的更多相关文章

  1. python爬虫入门(六) Scrapy框架之原理介绍

    Scrapy框架 Scrapy简介 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬 ...

  2. 第三百三十五节,web爬虫讲解2—Scrapy框架爬虫—豆瓣登录与利用打码接口实现自动识别验证码

    第三百三十五节,web爬虫讲解2—Scrapy框架爬虫—豆瓣登录与利用打码接口实现自动识别验证码 打码接口文件 # -*- coding: cp936 -*- import sys import os ...

  3. 第三百三十四节,web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息

    第三百三十四节,web爬虫讲解2—Scrapy框架爬虫—Scrapy爬取百度新闻,爬取Ajax动态生成的信息 crapy爬取百度新闻,爬取Ajax动态生成的信息,抓取百度新闻首页的新闻rul地址 有多 ...

  4. 第三百三十三节,web爬虫讲解2—Scrapy框架爬虫—Scrapy模拟浏览器登录—获取Scrapy框架Cookies

    第三百三十三节,web爬虫讲解2—Scrapy框架爬虫—Scrapy模拟浏览器登录 模拟浏览器登录 start_requests()方法,可以返回一个请求给爬虫的起始网站,这个返回的请求相当于star ...

  5. 第三百三十二节,web爬虫讲解2—Scrapy框架爬虫—Scrapy使用

    第三百三十二节,web爬虫讲解2—Scrapy框架爬虫—Scrapy使用 xpath表达式 //x 表示向下查找n层指定标签,如://div 表示查找所有div标签 /x 表示向下查找一层指定的标签 ...

  6. 第三百三十一节,web爬虫讲解2—Scrapy框架爬虫—Scrapy安装—Scrapy指令

    第三百三十一节,web爬虫讲解2—Scrapy框架爬虫—Scrapy安装—Scrapy指令 Scrapy框架安装 1.首先,终端执行命令升级pip: python -m pip install --u ...

  7. scrapy框架中Download Middleware用法

    scrapy框架中Download Middleware用法   Downloader Middleware处理的过程主要在调度器发送requests请求的时候以及网页将response结果返回给sp ...

  8. Python爬虫进阶之Scrapy框架安装配置

    Python爬虫进阶之Scrapy框架安装配置 初级的爬虫我们利用urllib和urllib2库以及正则表达式就可以完成了,不过还有更加强大的工具,爬虫框架Scrapy,这安装过程也是煞费苦心哪,在此 ...

  9. scrapy框架(三)

    scrapy框架(三) CrawlSpider类 创建CrawlSpider  # 创建项目后 $ scrapy genspider -t crawl spider_name website_doma ...

随机推荐

  1. “数据接口请求异常:error”,Layui-table使用遇到的最大一个坑

    后台返回的json格式必须和官方给的一模一样 code必须为0, code必须为0, code必须为0, code必须为0

  2. build hadoop, spark, hbase cluster

    1,something: 1,arc land 506  git branch 507  git status 508  git reset multicloud/qcloud/cluster_man ...

  3. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 显示代码

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  4. 使用gcc编译c语言解码ascii码

    vi test.c 输入代码: #include<stdio.h> int main(void) { char *p = (char *)"\xE6\x8A\xB1\xE6\xA ...

  5. Python中self的用法

    在Python类中规定,函数的第一个参数是实例对象本身,并且约定俗成,把其名字写为self.其作用相当于java中的this,表示当前类的对象,可以调用当前类中的属性和方法. 在python中,类是通 ...

  6. Vue源码(下篇)

    上一篇是mount之前的添加一些方法,包括全局方法gloal-api,XXXMixin,initXXX,然后一切准备就绪,来到了mount阶段,这个阶段主要是 解析template 创建watcher ...

  7. C语言笔记 14_标准库&assert&ctype&errno&float&limits

    C 标准库 <assert.h> 简介 C 标准库的 assert.h头文件提供了一个名为 assert 的宏,它可用于验证程序做出的假设,并在假设为假时输出诊断消息. 已定义的宏 ass ...

  8. Pytorch model saving and loading 模型保存和读取

    It is really useful to save and reload the model and its parameters during or after training in deep ...

  9. python 爬虫原理

    简单来说互联网是由一个个站点和网络组成的大网,我们通过浏览器访问站点,站点把HTML.JS.CSS代码返回给浏览器,这些代码经过浏览器解析.渲染,将丰富多彩的网页呈现我们眼前: 一.爬虫是什么? 如果 ...

  10. Law of large numbers and Central limit theorem

    大数定律 Law of large numbers (LLN) 虽然名字是 Law,但其实是严格证明过的 Theorem weak law of large number (Khinchin's la ...