简介
-
使用中间件可以在爬虫的请求发起之前或者请求返回之后对数据进行定制化修改,从而开发出适应不同情况的爬虫
-
在
Scrapy
中有两种中间件:下载器中间件(Downloader Middleware
)和爬虫中间件(Spider Middleware
)
Downloader Middleware
-
下载器中间件是介于
Scrapy
的request
/response
处理的钩子框架,是用于全局修改Scrapy request
和response
的一个轻量、底层的系统 -
用于更换代理
IP
,更换Cookies
,更换User-Agent
,自动重试。 -
Scrapy
其实自带了UA
中间件(UserAgentMiddleware
)、代理中间件(HttpProxyMiddleware
)和重试中间件(RetryMiddleware
) -
从原则上说,要自己开发这3个中间件,需要先禁用
Scrapy
里面自带的这3个中间件。要禁用Scrapy
的中间件,需要在settings.py
里面将这个中间件的顺序设为None
process_request(request, spider)
Request
被Scrapy
引擎调度给Downloader
之前,process_request()
方法就会被调用,也就是在Request
从队列里调度出来到Downloader
下载执行之前,我们都可以用process_request()
方法对Request
进行处理。
方法的返回值必须为None
、Response
对象、Request
对象之一,或者抛出IgnoreRequest
异常。
process_response(request, response, spider)
Downloader
执行Request
下载之后,会得到对应的Response
。Scrapy
引擎便会将Response
发送给Spider
进行解析。
在发送之前,我们都可以用process_response()
方法来对Response
进行处理。方法的返回值必须为Request
对象、Response
对象之一,或者抛出IgnoreRequest
异常
process_exception(request, exception, spider)
当Downloader
或process_request()
方法抛出异常时,例如抛出IgnoreRequest
异常,process_exception()
方法就会被调用。
方法的返回值必须为None
、Response
对象、Request
对象之一
随机更换代理IP示例
- 修改
middlewares.py
文件,添加以下代码
# 随机更换代理IP示例
import random
from scrapy.conf import settings
class ProxyMiddleware(object):
# 这个方法中的代码会在每次爬虫访问网页之前执行
def process_request(self, request, spider):
proxy = random.choice(settings['PROXIES'])
request.meta['proxy'] = proxy
- 修改
settings.py
文件,添加几个代理IP
,然后激活中间件
PROXIES = ['https://114.217.243.25:8118',
'https://125.37.175.233:8118',
'http://1.85.116.218:8118']
DOWNLOADER_MIDDLEWARES = {
# 后面的数字表示这种中间件的顺序
# 数字越小的中间件越先执行
# 最简单的办法就是从543开始,逐渐加一,这样一般不会出现什么大问题
'demo.middlewares.ProxyMiddleware': 543,
}
Spider Middleware
当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
进行处理
process_spider_input(response, spider)
当Response
被Spider Middleware
处理时,process_spider_input()
方法被调用
process_spider_output(response, result, spider)
当Spider
处理Response
返回结果时,process_spider_output()
方法被调用
process_spider_exception(response, exception, spider)
当Spider
或Spider Middleware
的process_spider_input()
方法抛出异常时,process_spider_exception()
方法被调用
process_start_requests(start_requests, spider)
process_start_requests()
方法以Spider
启动的Request
为参数被调用,执行的过程类似于process_spider_output()
,只不过它没有相关联的Response
,并且必须返回Request
发表评论