[Spider Middleware] - spider中间件
摘要:关于scrapy中spider middleware的用法。
spider middlerware位于引擎和Spider之间,当Downloader生成Response之后,Response会被发送到Spider,在发送给Spider之前,Response会首先经过Spider Middleware处理,当Spider处理生成Item和Request之后,Item和Request还会经过Spider Middleware的处理。
使用说明
首先把自定义的spider middlerware加入到settings.py文件的SPIDER_MIDDLEWARES设置中,然后该设置会和Scarpy中SPIDER_MIDDLEWARES_BASE定义的Spider Middleware合并。然后根据键值的数字优先级排序,得到一个有序列表,第一个最靠近引擎,最后一个靠近Spider。
spider middleware的方法说明
当Response被Spider Middleware处理时,process_spider_input()方法被调用。
process_spider_input(response,spider)
参数说明:
process_spider_input()方法的参数有如下两个:
- resonse,是Response 对象,即被处理的Response。
- spider,是Spider 对象,即该Response对应的Spider。
返回值:
process_spider_input()应该返回None或者抛出一个异常
- 如果它返回None,Scrapy将会继续处理该Response,调用其他的Spider Middlerware,直到Spider处理该Response。
- 如果它抛出一个异常,Scrapy将不会调用任何其他的Spider Middleware的process_spider_input方法,而调用Request的errback()方法。errback的输出将被使用process_spider_output()方法来处理。如果Request对象没有errback方法则直接调用process_spider_exception()来处理。
当Spider 处理Response 返回结果时,process spider_ output()方法被调用。
process_spider_output(response,result,spider)
参数说明:
process_spider_output()方法的参数有如下三个:
- response,是Response对象,即生成该输出的response。
- result,包含Request或Item对象的可迭代对象,即Spider返回的结果。
- spider,是Spider对象,即其结果对应的Spider。
返回值:
process_spider_output()必须返回包含Request或者Item对象的可迭代对象。
当Spider 或Spider Middleware 的process_spider _input()方法抛出异常时,process_spider_exception()
方法被调用。
process_spider_exception(response,exception,spider)
参数说明:
process_spider_exception()方法的参数有如下三个:
- response,是Response对象,即异常被抛出时处理的Response。
- exception,是Exception对象,即被抛出的异常。
- spider,是Spider对象,即抛出该异常的Spider。
返回值:
process_spider_exception() 必须要么返回None,要么返回一个包含Response 或 item对象的可迭代对象。
如果process_spider_exception返回None,代表该方法推卸掉责任,并没处理异常,而是直接交给下一个process_spider_exception,全都返回None,则异常最终交给Engine抛出
当使用start_urls变量或者start_request方法时发出请求时被调用,执行的过程类似于process_spider_output(),只不过其没有相关联的response并且必须返回request(不是item)。
process_start_requests(start_requests, spider)
参数说明:
process_start_requests()方法的参数有如下二个:
- start_requests(包含Request的可迭代对象) - start requests
- spider,是Spider对象,start request所属的spider
返回值:
必须返回一个包含Request对象的可迭代对象。
关于三个函数的使用
详情请看:scrapy 中间件 - Rannie` - 博客园
如果数值最小spider中间件中的process_spider_input先调用,然后调用数值次小的。如果抛出异常,并且存在errback,则先调用errback,然后调用数值最大的spider中间件中的process_spider_output,然后在调用数值次大的process_spider_output。
如果抛出异常,并且不存在errback,调用数值最大的spider中间件中的process_spider_exception,然后在调用数值次大的process_spider_exception。
因为按照数值大小,从引擎到spider排序,process_spider_input从引擎流向spider,process_spider_output从spider流向引擎。
实验代码如下:
baiduspider.py爬虫文件
import scrapy
class BaiduspiderSpider(scrapy.Spider):
name = 'baiduspider'
allowed_domains = ['baidu.com']
start_urls = ['http://baidu.com/']
def start_requests(self):
yield scrapy.Request(url='http://www.baidu.com/',
callback=self.parse,
errback=self.parse_err,
)
def parse(self, response):
pass
def parse_err(self,res):
return [1,2,3,4,5]
middlewares2.py中间件文件
from scrapy import signals
class SpiderMiddleware1(object):
def process_spider_input(self, response, spider):
print("input1")
def process_spider_output(self, response, result, spider):
print('output1',list(result))
return result
def process_spider_exception(self, response, exception, spider):
print('exception1')
class SpiderMiddleware2(object):
def process_spider_input(self, response, spider):
print("input2")
raise TypeError('input2 抛出异常')
def process_spider_output(self, response, result, spider):
print('output2',list(result))
return result
def process_spider_exception(self, response, exception, spider):
print('exception2')
class SpiderMiddleware3(object):
def process_spider_input(self, response, spider):
print("input3")
return None
def process_spider_output(self, response, result, spider):
print('output3',list(result))
return result
def process_spider_exception(self, response, exception, spider):
print('exception3')
settings.py文件
SPIDER_MIDDLEWARES = {
'errback1.middlewares2.SpiderMiddleware1': 543,
'errback1.middlewares2.SpiderMiddleware2': 544,
'errback1.middlewares2.SpiderMiddleware3': 545,
}
代码文件:
errback1.rar
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。