下载中间件
下载中间件是scrapy提供⽤于⽤于在爬⾍过程中可修改Request和Response, ⽤于扩展scrapy的功能
-----------------下载中间件-------------------------------
- 使⽤⽅法: 编写⼀个Download Middlewares和我们编写⼀个pipeline⼀样,定义⼀个 类,然后再settings中开启
- Download Middlewares默认⽅法:
- 处理请求,处理响应,对应两个⽅法:
process_request(self,request,spider): #当每个request通过下载中间件时,该⽅法被调⽤
process_response(self,request,response,spider): #当下载器完成http请求,传递响应给引擎的时候调⽤
-----------------------------process_request()----------------------------------------------
process_request(request,spider):
当每个Request对象经过下载中间件时会被调⽤,优先级越⾼的中间件,越先调 ⽤;该⽅法应该返回以下对象:None/Response对象/Request对象/抛出 IgnoreRequest异常
- 返回Response对象:scrapy不会再调⽤其他中间件的process_request⽅ 法,也不会去发起下载,⽽是直接返回该Response对象
- 返回Request对象:scrapy不会再调⽤其他中间件的process_request()⽅ 法,⽽是将其放置调度器待调度下载
- 如果这个⽅法抛出异常,则会调⽤process_exception⽅法
-------------------------------- process_response()------------------------------------------
process_response(request,response,spider)
当每个Response经过下载中间件会被调⽤,优先级越⾼的中间件,越晚被调 ⽤,与process_request()相反;该⽅法返回以下对象:Response对 象/Request对象/抛出IgnoreRequest异常。
- 返回Response对象:scrapy会继续调⽤其他中间件的process_response⽅ 法;
- 返回Request对象:停⽌中间器调⽤,将其放置到调度器待调度下载;
- 抛出IgnoreRequest异常:Request.errback会被调⽤来处理函数,如果没有 处理,它将会被忽略且不会写进⽇志。
-------------------------------------------下载中间件修改请求头--------------------------------------
设置随机请求头
-----为什么设置请求头??----
------------------------------------
爬⾍在频繁访问⼀个⻚⾯的时候,这个请求如果⼀直保持⼀致。那么很容易被服 务器发现,从⽽禁⽌掉这个请求头的访问。因此我们要在访问这个⻚⾯之前随机 的更改请求头,这样才可以避免爬⾍被抓。随机更改请求头,可以在下载中间件实 现。在请求发送给服务器之前,随机的选择⼀个请求头。这样就可以避免总使⽤ ⼀个请求头
-----------请求头--------------
图2.1
----测试请求头网址----
测试请求头⽹址: http://httpbin.org/user-agent
----------------------------
------------------------------------代码一(方式一)----------------------------------------------------------scrapy下载中间件中的代码(middlewares)
1.在爬虫中间件中重新定义一个类UserAgentDownloadweMiddleware
2.在scrapy设置中打开下载中间件中的类
class UserAgentDownloadweMiddleware:
#方式一
#请求头列表
USER_AGENTS = [ "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)", "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)", "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)", "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0", ]
#配置ua要在设置中打开下载中间件(DOWNLOADER_MIDDLEWARES)而不是爬虫中间件(SPIDER_MIDDLEWARES)
def process_request(self,request,spider):
user_agent=random.choice(self.USER_AGENTS)
request.headers['User-Agent']=user_agent
---------在scrapy设置项中打开下载中间件选项
图1.3
------------爬虫项目代码(打印测试请求头网址的响应结果)
import scrapy
class UaSpider(scrapy.Spider):
name = 'ua'
allowed_domains = ['httpbin.org']
start_urls = ['http://httpbin.org/user-agent']
def parse(self, response):
print(response.text)
yield scrapy.Request(self.start_urls[0],dont_filter=True)
#scrapy会对request的URL去重(RFPDupeFilter),加上dont_filter则告诉它这个URL不参与去重,
# 而且不会被allowed_domains域名过滤掉
--------------代码二(方式二)----------------------------------------------------------------------
-------------------
------------------引入请求头的第三方包
fake_useragent 包是请求头的第三方包,此包可以随机产生一个请求头,用于模拟U-A.
pip install fake_usergent #安装fake_useragent包
----代码-------
------------
-------下载中间件代码------
class UserAgentDownloadweMiddleware:
#方式二
def process_request(self,request,spider):
ua=UserAgent()
user_agent_str=ua.random #产生随机一个请求头
request.headers['User-Agent']=user_agent_str
------
-------scrapy设置代码
------
-----------爬虫代码
import scrapy
class UaSpider(scrapy.Spider):
name = 'ua'
allowed_domains = ['httpbin.org']
start_urls = ['http://httpbin.org/user-agent']
def parse(self, response):
print(response.text)
yield scrapy.Request(self.start_urls[0],dont_filter=True)
#scrapy会对request的URL去重(RFPDupeFilter),加上dont_filter则告诉它这个URL不参与去重,
# 而且不会被allowed_domains域名过滤掉