关于Scrapy框架中yield方法和Downloader中间件的讲解

一、yield方法

1》作用:调用yield方法,将请求(request)发送给Scrapy Engine(引擎)进行处理
2》参数分析:

yield scrapy.Request(       # 该Request对象代表了一个http请求,会经由Downloader去执行,从而产生一个response
	url=task["task_url"],    	# 请求数据库中的url
	callback=xxx,				# callback回调函数,默认不写会调用parse方法
	method='GET',				# 请求方法,默认为get
	headers=xxx,				# 请求头信息(一般在setting.py中的DEFAULT_REQUEST_HEADERS设置即可)
	body=xxx,					# 请求体
	cookies=xxx,				# 要携带的cookie信息(一般在middlewares.py中自定义即可)
	meta=xxx,	               	# 以字典的格式,向其他方法里面传递信息
	encoding='utf-8',			# 字符编码
	priority=0,					# 请求的优先级(数值越低,优先级越高)
	dont_filter=False,         	# 设置请求是否要过滤
	errback=self.handle_err,   	# 当程序处理请求返回有错误时,使用该参数并调用handle_err()函数
)

3》请求方式:
携带的参数相同,如上代码所示。

  • GET请求:调用 yield scrapy.Request() 方法
  • POST请求:调用 yield scrapy.FormRequest() 方法
二、自定义Downloader中间件

Scrapy 内置的 Downloader Middleware 为 Scrapy 提供了基础的功能,但在项目实战中我们往往需要单独定义 Downloader Middleware 。不用担心,这个过程非常简单,我们只需要实现某几个方法即可。

每个 Downloader Middleware 都定义了一个或多个方法的类,核心的方法有如下三个。

  • def process_request(self, request, spider)
  • def process_response(self, request, response, spider)
  • def process_exception(self, request, exception, spider)

我们只需要实现至少一个方法,就可以定义一个 Downloader Middleware 。下面我们来看看这三个方法的详细用法。

1. def process_request(self, request, spider)

每一个Requests 从引擎传递给下载器之前,该方法被调用。也就是在Request从调度队列里调度出来到Downloader下载执行之前,我们都可以用process_request()方法对Request进行处理。

方法的返回值必须为:【None、Response对象、Request对象、或者抛出IgnoreRequest异常】。

process_request()方法的参数有如下两个。

  • request,是Request对象,即被处理的Request。
  • spider,是Spdier对象,即此Request对应的Spider。

返回类型不同,产生的效果也不同。下面归纳一下不同的返回情况并作出解释:

  • 当返回是None时,Scrapy将继续处理该Request,接着执行其他Downloader Middlewareprocess_request()方法,一直到Downloader把Request执行后得到Response才结束。这个过程其实就是修改Request的过程,不同的Downloader Middleware按照设置的优先级顺序依次对Request进行修改,最后送至Downloader执行。
  • 当返回为Response对象时,更低优先级的Downloader Middlewareprocess_request()process_exception()方法就不会被继续调用,每个Downloader Middlewareprocess_response()方法转而被依次调用。调用完毕之后,直接将Response对象发送给Spider来处理。
  • 当返回为Request对象时,更低优先级的Downloader Middlewareprocess_request()方法会停止执行。这个Request会重新放到调度队列里,其实它就是一个全新的Request,等待被调度。如果被Scheduler调度了,那么所有的Downloader Middlewareprocess_request()方法会被重新按照顺序执行。
  • 如果IgnoreRequest异常抛出,则所有的Downloader Middlewareprocess_exception()方法会依次执行。如果没有一个方法处理这个异常,那么Request的errback()方法就会回调 (即:爬虫文件中的 yield 方法中的 “errback” 参数)。如果该异常还没有被处理,那么它便会被忽略。

2.def process_response(self, request, response, spider)

每一个Response 从下载器返回给引擎之前,该方法被调用。也就是Downloader执行Request下载之后,会得到对应的Response,Scrapy引擎便会将Response发送给Spider进行解析。在发送之前,我们都可以用process_response()方法来对Response进行处理。

方法的返回值必须为:【Request对象、Response对象、或者抛出IgnoreRequest异常】。
process_response()方法的参数有如下三个。

  • request,是Request对象,即此Response对应的Request。
  • response,是Response对象,即此被处理的Response。
  • spider,是Spider对象,即此Response对应的Spider。

返回类型不同,产生的效果也不同。下面归纳一下不同的返回情况并作出解释:

  • 当返回为Request对象时,更低优先级的Downloader Middlewareprocess_response()方法不会继续调用。该Request对象会重新放到调度队列里等待被调度,它相当于一个全新的Request。然后,该Request会被process_request()方法顺次处理。

  • 当返回为Response对象时,更低优先级的Downloader Middlewareprocess_response()方法会继续调用,继续对该Response对象进行处理。

  • 如果IgnoreRequest异常抛出,它不会进入到process_exception()方法中,而是Request的errback()方法就会回调 (即:爬虫文件中的 yield 方法中的 “errback” 参数)。如果该异常还没有被处理,那么它便会被忽略。

  • 关于process_response()方法的使用案例,可参考瓜子案例中的middlewares.py文件:瓜子案例


3.def process_exception(self, request, exception, spider)

下载器 出现异常 或 下载器中间件process_request()方法抛出异常时,例如抛出 “IgnoreRequest” 异常,该方法会被调用。

方法的返回值必须为:【None、Response对象、Request对象】。
process_exception()方法的参数有如下三个。

  • request,是Request对象,即产生异常的Request。
  • exception,是Exception对象,即抛出的异常。
  • spdier,是Spider对象,即Request对应的Spider。

返回类型不同,产生的效果也不同。下面归纳一下不同的返回情况并作出解释:

  • 当返回为None时,更低优先级的Downloader Middlewareprocess_exception()会被继续顺次调用,直到所有的方法都被调度完毕。
  • 当返回为Response对象时,更低优先级的Downloader Middlewareprocess_exception()方法不再被继续调用,每个Downloader Middlewareprocess_response()方法转而被依次调用。
  • 当返回为Request对象时,更低优先级的Downloader Middlewareprocess_exception()也不再被继续调用,该Request对象会重新放到调度队列里面等待被调度,它相当于一个全新的Request。然后,该Request又会被process_request()方法顺次处理。

以上内容便是这三个方法的详细使用逻辑。在使用它们之前,请先对这三个方法的返回值的处理情况有一个清晰的认识。在自定义Downloader Middleware的时候,也一定要注意每个方法的返回类型。

注:以上的中间件方法,只要实现至少一个方法就可以自定义一个Downloader中间件了!!!

  • 当需要修改请求头(User_Agent)、设置ip代理时,可以调用中间件的process_request()方法;(最终无返回response结果的时候)
  • 当有出现反爬机制,需要破解反爬时,可以调用中间件的process_response()方法;(最终有返回response结果的时候)
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值