这篇文章中写了常用的下载中间件的用法和例子。 编写自己的下载器中间件编写下载器中间件,需要定义以下一个或者多个方法的python类 为了演示这里的中间件的使用方法,这里创建一个项目作为学习,这里的项目是关于爬去httpbin.org这个网站 创建好后的目录结构如下: 这里我们先写一个简单的代理中间件来实现ip的伪装 def parse(self, response): print(response.text) 然后通过命令行启动爬虫:scrapy crawl httpbin 在最下面我们可以看到"origin": "114.250.88.66"
而我们要做就是通过代理中间件来实现ip的伪装,在middleares.py中写如下的中间件类: class ProxyMiddleare(object): logger = logging.getLogger(__name__) def process_request(self,request, spider): self.logger.debug("Using Proxy") request.meta['proxy'] = 'http://127.0.0.1:9743' return None 这里因为我本地有一个代理翻墙地址为:http://127.0.0.1:9743 所以直接设置为代理用,代理的地址为日本的ip 然后我们再次启动爬虫:scrapy crawl httpbin
详细说明class Scrapy.downloadermiddleares.DownloaderMiddlewareprocess_request(request,spider) 当每个request通过下载中间件时,该方法被调用,这里有一个要求,该方法必须返回以下三种中的任意一种:None,返回一个Response对象,返回一个Request对象或raise IgnoreRequest。三种返回值的作用是不同的。 None:Scrapy将继续处理该request,执行其他的中间件的相应方法,直到合适的下载器处理函数(download handler)被调用,该request被执行(其response被下载)。 Response对象:Scrapy将不会调用任何其他的process_request()或process_exception() 方法,或相应地下载函数;其将返回该response。 已安装的中间件的 process_response() 方法则会在每个response返回时被调用。 Request对象:Scrapy则停止调用 process_request方法并重新调度返回的request。当新返回的request被执行后, 相应地中间件链将会根据下载的response被调用。 raise一个IgnoreRequest异常:则安装的下载中间件的 process_exception() 方法会被调用。如果没有任何一个方法处理该异常, 则request的errback(Request.errback)方法会被调用。如果没有代码处理抛出的异常, 则该异常被忽略且不记录。 process_response(request, response, spider) process_response的返回值也是有三种:response对象,request对象,或者raise一个IgnoreRequest异常 如果其返回一个Response(可以与传入的response相同,也可以是全新的对象), 该response会被在链中的其他中间件的 process_response() 方法处理。 如果其返回一个 Request 对象,则中间件链停止, 返回的request会被重新调度下载。处理类似于 process_request() 返回request所做的那样。 如果其抛出一个 IgnoreRequest 异常,则调用request的errback(Request.errback)。 如果没有代码处理抛出的异常,则该异常被忽略且不记录(不同于其他异常那样)。 这里我们写一个简单的例子还是上面的项目,我们在中间件中继续添加如下代码:
然后在spider中打印状态码: 这样当我们重新运行爬虫的时候就可以看到如下内容 process_exception(request, exception, spider) 当下载处理器(download handler)或 process_request() (下载中间件)抛出异常(包括 IgnoreRequest 异常)时,Scrapy调用 process_exception()。 process_exception() 也是返回三者中的一个: 返回 None 、 一个 Response 对象、或者一个 Request 对象。 如果其返回 None ,Scrapy将会继续处理该异常,接着调用已安装的其他中间件的 process_exception() 方法,直到所有中间件都被调用完毕,则调用默认的异常处理。 如果其返回一个 Response 对象,则已安装的中间件链的 process_response() 方法被调用。Scrapy将不会调用任何其他中间件的 process_exception() 方法。 如果其返回一个 Request 对象, 则返回的request将会被重新调用下载。这将停止中间件的 process_exception() 方法执行,就如返回一个response的那样。 这个是非常有用的,就相当于如果我们失败了可以在这里进行一次失败的重试,例如当我们访问一个网站出现因为频繁爬取被封ip就可以在这里设置增加代理继续访问,我们通过下面一个例子演示 scrapy genspider google www.google.com 这里我们创建一个谷歌的爬虫, 然后启动scrapy crawl google,可以看到如下情况: 这里我们就写一个中间件,当访问失败的时候增加代理 这样我重新启动爬虫:scrapy crawl google,可以看到如下: 这里如果我们不想让重试,可以把重试中间件关掉: 这样设置之后我们就把失败重试的中间件给关闭了,设置为None就表示关闭这个中间件,重新启动爬虫我们也可以看出没有进行重试直接报错了 我们将代理中间件的代理改成如下,表示遇到异常的时候给请求加上代理,并返回request,这个样就会重新请求谷歌 重新启动谷歌爬虫,我们可以看到,我们第一次返回我们打印的日志信息GET Exception,然后加上代理后成功访问了谷歌,这里我的代理是日本的代理节点,所以访问到的是日本的谷歌站
|
|