爬虫5.10 — scrapy框架Download Middlewares[下载器中间件]的使用"/>
Python爬虫5.10 — scrapy框架Download Middlewares[下载器中间件]的使用
Python爬虫5.10 — scrapy框架Download Middlewares[下载器中间件]的使用
- 综述
- Download Middlewares(下载器中间件)
- process_request(self, request, spider)
- process_response(self, request, response, spider)
- 中间件其他方法
- 实例说明
- 随机请求头中间件
- IP代理池中间件
- 开放代理开发
- 独享代理开发
- 其他博文链接
综述
本系列文档用于对Python爬虫技术的学习进行简单的教程讲解,巩固自己技术知识的同时,万一一不小心又正好对你有用那就更好了。
Python 版本是3.7.4
本篇文章主要Scrapy
框架的Download Middlewares
(下载器中间件)模块的使用,下载器中间的作用主要用于进行反爬虫。主要内容包含:
- 如何设置请求头
- 设置ip代理
Download Middlewares(下载器中间件)
下载器中间件是引擎和下载器之间通信的中间件。在这个中间件中我们可以设置代理、更换请求头信息等来达到反反爬虫的目的。要写下载器中间,可以在下载器中实现两个方法。一个是process_request(self, request, spider)
,这个方法是在请求发送之前会执行,还有一个是process_response(self, request, response, spider)
,这个方法是数据下载到引擎之前执行。
process_request(self, request, spider)
这个方法是在下载器发送请求之前会执行的,一般可以在这个里卖弄设置随机代理,随机请求头等。
- 参数
- request : 发送请求的request对象。
- spider : 发送请求的spider对象。
- 返回值
- 返回Node:如果返回None,Scrapy将继续吃力该request,执行中间件中的相应的方法,知道合适的下载器处理函数被调用。
- 返回Response对象:Scrapy将不会调用其他的
process_request
方法,将直接返回这个response对象。已经激活的中间件的process_response()
方法则会在每个response
返回时被调用。 - 返回Request对象:不再使用之前的request对象去下载数据,而是根据限制返回request对象返回数据。
- 如果这个方法中抛出了异常,则会调用
process_exception
方法。
process_response(self, request, response, spider)
这个方法是下载器下载的数据到引擎中间会执行的方法。
- 参数
- request:request对象。
- response:被处理的response对象。
- spider:spider对象.
- 返回值
- 返回Response对象:会将这个新的response对象传给其他中间件,最终传给爬虫。
- 返回Request对象:下载器链被切断,返回的resquest会重新被下载器调度下载。
- 如果这个方法中抛出了异常,那么将会调用request的errorback方法,如果没有指定这个方法,那么会抛出一个异常。
中间件其他方法
- from_crawler(cls, crawler):如果存在该函数,from_crawler会被调用使用crawler来创建中间器对象,必须返回一个中间器对象,通过这种方式,可以访问到crawler的所有核心部件,如settings、signals等;
- process_exception(self, request, exception, spider):当process_response()和process_request()抛出异常时会被调用,应该返回以下对象:None/Response对象/Request对象;
- spider_opened(self, spider):当spider开始爬取时发送该信号。该信号一般用来分配spider的资源,不过其也能做任何事。
实例说明
随机请求头中间件
爬虫在频繁访问一个页面的时候,这个请求头如果一直保持一致,那么很容易被服务器发现,从而简直掉这个请求头的访问。因此我们要在访问这个页面之前随机更改请求头,这样才可以避免爬虫被抓。随机更改请求头,可以在下载中间件中实现,在请求发送给服务器之前,随机的选中一个请求头,这样就可以避免总是用一个请求头了。具体开发步骤如下:
- 使用Scrapy命令创建项目、创建爬虫(此步不做代码展示说明);
- 开发修改spider模块文件代码如下:
import scrapyclass HttpbinSpider(scrapy.Spider):name = 'httpbin'allowed_domains = ['httpbin']start_urls = ['']def parse(self, response):print(response.text)yield scrapy.Request(self.start_urls[0], dont_filter=True)
- 开发下载器中间件
middlewares.py
代码如下:import randomclass UseragentDemoDownloaderMiddleware(object):USER_AGENTS = ['Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36','Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/44.0.2403.155 Safari/537.36','Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36','Mozilla/5.0 (X11; Linux i686; rv:64.0) Gecko/20100101 Firefox/64.0','Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0','Mozilla/5.0 (X11; Linux i586; rv:63.0) Gecko/20100101 Firefox/63.0','Mozilla/5.0 (Windows NT 6.2; WOW64; rv:63.0) Gecko/20100101 Firefox/63.0',]def process_request(self, request, spider):user_agent = random.choice(self.USER_AGENTS)request.headers['User-Agent'] = user_agent
- 修改
setting.py
配置文件,开启下载器中间件,代码如下:DOWNLOADER_MIDDLEWARES = {'useragent_demo.middlewares.UseragentDemoDownloaderMiddleware': 543, }
运行即可看到请求头切换打印效果。
Scrapy框架为我们提供了一个请求头代理中间件类UserAgentMiddleware
:
scrapy.downloadermiddlewares.useragent.UserAgentMiddleware
通过配置项USER_AGENT设置用户代理:
settings.py
#...
#UserAgentMiddleware默认打开
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
#...
IP代理池中间件
关于代理IP相关的我们在前面的基础教程文章中已经讲过很多遍,在这里就不再进行说明了。Scrapy框架提供了一个代理代理服务器中间件类HttpProxyMiddleware
:
scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware
用以设置代理服务器,通过设定request.meta['proxy']
来设置代理,会从环境变量http_proxy
、https_proxy
、no_proxy
依次获取。设置代理我们有两种方式,一种设置是开放代理(开放代理就是有ip和port,不用用户名和密码就可使用),另外一种是独享代理,需要用户名和密码才能访问。
我们以的返回进行样理测试样例开发。
开放代理开发
开发中间件类代码如下:
import randomclass IpProxyDownloaderMiddleware(object):PROXIES = ['202.109.157.47:9000','115.28.148.192:8118',]def process_request(self, request, spider):proxy = random.choice(self.PROXIES)print(proxy)request.meta['proxy'] = "http://" + proxy
开发spider爬虫模块代码如下:
import scrapyclass IpproxySpider(scrapy.Spider):name = 'ipproxy'allowed_domains = ['httpbin']start_urls = ['']def parse(self, response):print(response.text)yield scrapy.Request(self.start_urls[0], dont_filter=True)
在setting.py
中设置中间件如下:
DOWNLOADER_MIDDLEWARES = {# 'useragent_demo.middlewares.UseragentDemoDownloaderMiddleware': 543,'useragent_demo.middlewares.IpProxyDownloaderMiddleware': 544,
}
运行查看结构即可,有的部分童鞋会有可能遇到这样的错误:
[scrapy.core.scraper] ERROR: Error downloading <GET ;
Traceback (most recent call last):File "D:\Python\Python37\lib\site-packages\twisted\internet\defer.py", line 1416, in _inlineCallbacksresult = result.throwExceptionIntoGenerator(g)File "D:\Python\Python37\lib\site-packages\twisted\python\failure.py", line 512, in throwExceptionIntoGeneratorreturn g.throw(self.type, self.value, self.tb)File "D:\Python\Python37\lib\site-packages\scrapy\core\downloader\middleware.py", line 44, in process_requestdefer.returnValue((yield download_func(request=request, spider=spider)))File "D:\Python\Python37\lib\site-packages\scrapy\utils\defer.py", line 45, in mustbe_deferredresult = f(*args, **kw)File "D:\Python\Python37\lib\site-packages\scrapy\core\downloader\handlers\__init__.py", line 71, in download_requestreturn handler.download_request(request, spider)File "D:\Python\Python37\lib\site-packages\scrapy\core\downloader\handlers\http11.py", line 68, in download_requestreturn agent.download_request(request)File "D:\Python\Python37\lib\site-packages\scrapy\core\downloader\handlers\http11.py", line 332, in download_requestmethod, to_bytes(url, encoding='ascii'), headers, bodyproducer)File "D:\Python\Python37\lib\site-packages\scrapy\core\downloader\handlers\http11.py", line 253, in requestproxyEndpoint = self._getEndpoint(self._proxyURI)File "D:\Python\Python37\lib\site-packages\twisted\web\client.py", line 1715, in _getEndpointreturn self._endpointFactory.endpointForURI(uri)File "D:\Python\Python37\lib\site-packages\twisted\web\client.py", line 1593, in endpointForURIraise SchemeNotSupported("Unsupported scheme: %r" % (uri.scheme,))
twisted.web.error.SchemeNotSupported: Unsupported scheme: b''
出现这种错误的原因是因为在中间件中进行设置IP代理池的时候没有添加传输协议,在上面的下载中间件中设置代理时,需要添加协议名称,“http://”或者“https://”。即可将此问题解决。
独享代理开发
将上例中间件代码修改为如下即可:
import random
import base64class IpProxyDownloaderMiddleware(object):def process_request(self, request, spider):# 你的独享代理ip和端口号proxy = 'ip:port'user_password = 'username:password'request.meta['proxy'] = "http://" + proxy# bytesb64_user_password = base64.b64encode(user_password.encode('utf-8'))request.headers['Proxy-Authorization'] = 'Basic ' + b64_user_password.decode('utf-8')
其他博文链接
- Python爬虫1.1 — urllib基础用法教程
- Python爬虫1.2 — urllib高级用法教程
- Python爬虫1.3 — requests基础用法教程
- Python爬虫1.4 — requests高级用法教程
- Python爬虫2.1 — BeautifulSoup用法教程
- Python爬虫2.2 — xpath用法教程
- Python爬虫3.1 — json用法教程
- Python爬虫3.2 — csv用法教程
- Python爬虫3.3 — txt用法教程
- Python爬虫4.1 — threading(多线程)用法教程
- Python爬虫4.2 — ajax(动态网页数据抓取)用法教程
- Python爬虫4.3 — selenium基础用法教程
- Python爬虫4.4 — selenium高级用法教程
- Python爬虫4.5 — tesseract(图片验证码识别)用法教程
- Python爬虫5.1 — scrapy框架简单入门
- Python爬虫5.2 — scrapy框架pipeline模块的使用
- Python爬虫5.3 — scrapy框架spider[Request和Response]模块的使用
- Python爬虫5.4 — scrapy框架items模块的使用
- Python爬虫5.5 — scrapy框架logging模块的使用
- Python爬虫5.6 — scrapy框架setting模块的使用
- Python爬虫5.7 — scrapy框架Shell命令的使用
- Python爬虫5.8 — scrapy框架CrawlSpider模块的使用
- Python爬虫5.9 — scrapy框架下载文件和图片
更多推荐
Python爬虫5.10 — scrapy框架Download Middlewares[下载器中间件]的使用
发布评论