使用scrapy框架开发一款爬虫,或多或少都会用到中间件。常见的中间件有UserAgent中间件、代理中间件等等。其主要作用就是在爬虫请求的过程中,通过自定义内置的一些方法,来改变如请求的结构,从而伪装请求客户端。
比如,在UserAgent中间件中,通过编写process_request
方法,将请求中的headers添加自定义ua,或者随机ua来实现动态UserAgent。
class UserAgentMiddleware:
def process_request(self, request, spider):
request.headers.setdefault('User-Agent', random_ua())
当然,仅仅编写自定义中间件是不够的。还需要在配置文件中,开启该中间件。
DOWNLOADER_MIDDLEWARES = {
……,
'SpiderPorject.middlewares.UserAgentMiddleware': 1
}
通过两步走:1.编写中间件;2.开启中间件。即可实现简单的中间件开发。框架开发者已经足够精简业务编写的流程。接下来抱着学习的态度,看看到底是如何实现的。
MiddlewareManager
MiddlewareManager
是所有中间件的基类,所有中间件指的是:
- DownloaderMiddlewareManager:下载中间件
- SpiderMiddlewareManager:爬虫中间件
- ExtensionManager:扩展中间件
- ItemPipelineManager:数据管道中间件
我们先从最初的父类_MiddlewareManager_来看。
该类有一个静态方法from_settings
来初始化这个类,在里面主要做一件事,就是获取配置文件中的中间件path。何为中间件path?看看上面,我们是如何启用UserAgent中间件的。在DOWNLOADER_MIDDLEWARES
中SpiderPorject.middlewares.UserAgentMiddleware
就是这个中间件的路径。通过方法load_object
把路径映射成类,并通过create_instance
实例化该类,存入数组middlewares
中。最后把middlewares
交给_MiddlewareManager_。然后类在初始化的时候遍历middlewares
调用方法_add_middleware
。
class MiddlewareManager:
def __init__(self, *middlewares):
self.middlewares = middlewares
self.methods = defaultdict(deque)
for mw in middlewares:
self._add_middleware(mw)
@classmethod
def from_settings(cls, settings, crawler=None):
mwlist = cls._get_mwlist_from_settings(settings)
middlewares = []
enabled = []
for clspath in mwlist:
try:
mwcls = load_object(clspath)
mw = create_instance(mwcls, settings, crawler