1.中间件
中间件是Scrapy里面的一个核心概念。使用中间件可以在爬虫的请求发起之前或者请求返回之后对数据进行定制化修改,从而开发出适应不同情况的爬虫。 分为两大种类:下载器中间件(DownloaderMiddleware)和爬虫中间件(SpiderMiddleware)
1.1爬虫中间件的主要功能
(1)处理引擎传递给爬虫的响应
(2)处理爬虫传递给引擎的请求
(3)处理爬虫传递给引擎的数据项
1.2下载中间件
(1)引擎将request对象讲给下载器之前会经过下载中间件;此时中间件提供了一个方法process_request可以对request对象进行设置随机请求头、IP代理、Cookie等
(2)当下载器完成下载时,获得到response对象,将它交给引擎的过程中,再一次经过下载中间件;此时中间件提供了另一个方法process_response;可以判断response对象的状态码,来决定是否将response提交给引擎
2.下载中间件主要用到的三个方法
- process_request:用来处理正常的请求对象的数据,每个request请求通过下载中间件时,该方法会执行。(我们主要使用的方法)
- process_response:用来处理响应对象的数据
- process_exception:用来处理抛异常的请求对象的数据
2.1 process_request(self,request,spider)
下载器在发送请求之前会执行的,一般可以在这个里面设置随机代理 ip 等
参数: request:发送请求的 request 对象;spider:发送请求的 spider对象
返回值情况:
- 返回 None:如果返回 None,Scrapy 将继续处理该 request,执行中间件中的相应方法,直到合适的下载器处理函数被调用
- 返回 Response 对象:Scrapy 将不会调用任何其他的 process_request 方法,将直接返回这个 response 对象
- 返回 Request 对象:Scrapy则停止调用 process_request方法并重新调度返回的request。当新返回的request被执行后, 相应地中间件链将会根据下载的response被调用
- 如果其raise一个 IgnoreRequest 异常,则安装的下载中间件的 process_exception() 方法会被调用。
2.2 process_response(self,request,response,spider)
下载器下载的数据到引擎中间会执行的方法。
返回值情况:
- 返回 Response 对象,会将这个新的 response 对象传给其他中间件,最终传给爬虫
- 返回 Request 对象:下载器链被切断,返回的 request 会重新被下载器调度下载。
- 如果其抛出一个 IgnoreRequest 异常,则调用request的errback(Request.errback)。如果没有代码处理抛出的异常,则该异常被忽略且不记录(不同于其他异常那样)。
2.3 process_exception
返回值情况:
- 返回 None ,Scrapy将会继续处理该异常,接着调用已安装的其他中间件的 process_exception() 方法,直到所有中间件都被调用完毕,则调用默认的异常处理。
- 返回Response 对象,则已安装的中间件链的 process_response() 方法被调用。Scrapy将不会调用任何其他中间件的 process_exception() 方法。
- 返回 Request 对象, 则返回的request将会被重新调用下载。这将停止中间件的 process_exception() 方法执行,就如返回一个response的那样。
3.替换USER-AGENT
测试ua地址可访问网站 http://httpbin.org/user-agent
获取请求头:https://useragentstring.com/pages/useragentstring.php?typ=Browser
3.1通过测试ua地址的网站,我们实现返回当前使用的user-agent的值
将测试ua地址可访问网站域名复制到爬虫中(我们的请求目标地址)
实际上我们后面添加了start_request方法后,是最开始从start_request开始执行的,现在添加的地址并不起作用
3.2打印我们的响应结果,也就是当前的USER-AGENT
3.3请求重复提交5次(不去重)
3.4执行爬虫
scrapy crawl 爬虫名
当前未对USER-AGENT做任何处理,响应的五个值全部一样
3.5添加USER-AGENT
3.5.1添加地址
将地址列表添加进middlerwares.py文件中的下载中间件类中
3.5.2获取user-agent
使用下载中间件内的process_request方法实现随机从列表中获取一个ua充当头部信息
注意:import radom
3.5.2settings中将下载中间件开启
3.5.3执行爬虫
此时打印出的5个ua不是完全一样的,是随机从列表中取的值
4.替换ip
测试ip地址可访问网站 http://httpbin.org/ip
注意:替换ip地址需要与我们当前请求地址的协议一致,即目标请求地址是http(或https),我们替换就要是http(或https),
4.1替换请求目标地址为http://httpbin.org/ip
执行爬虫,此时响应结果为我们自己的ip地址
4.2方法一(静态替换):
不推荐这种方法,因为代理ip有时效性,每次使用需要替换
(1)添加ip地址和获取方法(同替换ua方法一致)
middlewares中下载中间件类,添加ip地址列表,process_requerst方法中添加获取ip方法
(2)购买ip代理(按流量计费,txt),生成代理ip
(3)添加ip地址列表
(4)执行爬虫,此时生成的结果就不再是我们自己的ip地址了
4.3方法二(动态替换):
注:最终目的为实现ip地址切换,此部分后面的控制ip使用频率方法代码有些问题未实现期望情况
4.3.1购买代理ip(按流量计费,json格式(方便解析))
4.3.2向(代理ip)生成地址的API链接,发送请求并解析,获取ip
(1)可以通过一个插件Json Parser对json内容做一个解析
安装插件:File>settings>Plugins>搜索Json Parser>install>restart;
打开工作窗口:View>Tool Windows>Json Parser
(我在安装插件时未弹出restart始终无法成功安装,猜测可能是版本不兼容问题)
(2)发起请求并对json内容做一个解析,将ip地址与端口数据存储进ip_list中
此方法取得的ip地址也会过期,但由于每刷新一次地址就会变化,新的地址就会重新计时,因此不用担心过期问题
(3)为了爬虫的稳定以及提高ip使用频率,我们每取得5个地址放入ip_list后,每一个ip使用2-3次再切换到下一个ip使用。注意,每次重新请求一组ip前记得把存放的ip_list清空。
将ip_list输出打印,我们可以在后面的执行结果中查看是否成功获取了不同的ip值
(4)process_request会自动执行,我们需要在process_request里调用get_ip
(5)执行爬虫
我们查看输出的ip_list应当每组ip不相同
4.3.3切换ip
4.3.4控制切换ip与获取ip操作
4.3.5控制每个ip使用次数为3,3次后切换下一个ip