Python爬虫框架scrapy实现downloader_middleware设置proxy代理功能示例


Posted in Python onAugust 04, 2018

本文实例讲述了Python爬虫框架scrapy实现downloader_middleware设置proxy代理功能。分享给大家供大家参考,具体如下:

一、背景:

小编在爬虫的时候肯定会遇到被封杀的情况,昨天爬了一个网站,刚开始是可以了,在settings的设置DEFAULT_REQUEST_HEADERS伪装自己是chrome浏览器,刚开始是可以的,紧接着就被对方服务器封杀了。

代理:

代理,代理,一直觉得爬去网页把爬去速度放慢一点就能基本避免被封杀,虽然可以使用selenium,但是这个坎必须要过,scrapy的代理其实设置起来很简单。

注意,request.meta['proxy']=代理ip的API

middlewares.py

class HttpbinProxyMiddleware(object):
  def process_request(self, request, spider):
    pro_addr = requests.get('http://127.0.0.1:5000/get').text
    request.meta['proxy'] = 'http://' + pro_addr
    #request.meta['proxy'] = 'http://' + proxy_ip

设置启动上面我们写的这个代理

settings.py

DOWNLOADER_MIDDLEWARES = {
  'httpbin.middlewares.HttpbinProxyMiddleware': 543,
}

spiders

httpbin_test.py

import scrapy
class HttpbinTestSpider(scrapy.Spider):
  name = "httpbin_test"
  allowed_domains = ["httpbin.ort/get"]
  start_urls = ['http://httpbin.org/get']
  def parse(self, response):
    print(response.text)

origin的值其实就是本地的公网地址,但是因为我们用了代理,这里的ip是美国的一个ip

Python爬虫框架scrapy实现downloader_middleware设置proxy代理功能示例

Python爬虫框架scrapy实现downloader_middleware设置proxy代理功能示例

二、那么问题来了,现在有这么一个场景,如上所述的话,我每个请求都会使用代理池里面的代理IP地址,但是有些操作是不需要代理IP地址的,那么怎么才能让它请求超时的时候,再使用代理池的IP地址进行重新请求呢?

spider:

1、我们都知道scrapy的基本请求步骤是,首先执行父类里面(scrapy.Spider)里面的start_requests方法,

2、然后start_requests方法也是取拿我们设置的start_urls变量里面的url地址

3、最后才执行make_requests_from_url方法,并只传入一个url变量

那么,我们就可以重写make_requests_from_url方法,从而直接调用scrapy.Request()方法,我们简单的了解一下里面的几个参数:

1、url=url,其实就是最后start_requests()方法里面拿到的url地址

2、meta这里我们只设置了一个参数,download_timeout:10,作用就是当第一次发起请求的时候,等待10秒钟,如果没有请求成功的话,就会直接执行download_middleware里面的方法,我们下面介绍。

3、callback回调函数,其实就是本次的本次所有操作完成后执行的操作,注意,这里可不是说执行完上面所有操作后,再执行这个操作,比如说请求了一个url,并且成功了,下面就会执行这个方法。

4、dont_filter=False,这个很重要,有人说过不加的话默认就是False,但是亲测必须得加,作用就是scrapy默认有去重的方法,等于False的话就意味着不参加scrapy的去重操作。亲测,请求一个页面,拿到第一个页面后,抓取想要的操作后,第二页就不行了,只有加上它才可以。

import scrapy
class HttpbinTestSpider(scrapy.Spider):
  name = "httpbin_test"
  allowed_domains = ["httpbin.ort/get"]
  start_urls = ['http://httpbin.org/get']
  def make_requests_from_url(self,url):
    self.logger.debug('Try first time')
    return scrapy.Request(url=url,meta={'download_timeout':10},callback=self.parse,dont_filter=False)
  def parse(self, response):
    print(response.text)

middlewares.py

下面就是上面请求10秒后超时会执行的操作process_exception方法,心细的同学会发现,我们在spider文件里面输出log的时候,是直接输出的,那是因为scrapy早都在父类里面给你定义好了,直接应用就行,但是在middlewares里面需要自己定义一个类变量定义,才能使用引用。

class HttpbinProxyMiddleware(object):
  logger = logging.getLogger(__name__)
  # def process_request(self, request, spider):
  #   # pro_addr = requests.get('http://127.0.0.1:5000/get').text
  #   # request.meta['proxy'] = 'http://' + pro_addr
  #   pass
  #
  # def process_response(self, request, response, spider):
  #   # 可以拿到下载完的response内容,然后对下载完的内容进行修改(修改文本的编码格式等操作)
  #   pass
  def process_exception(self, request, response, spider):
    self.logger.debug('Try Exception time')
    self.logger.debug('Try second time')
    proxy_addr = requests.get('http://127.0.0.1:5000/get').text
    self.logger.debug(proxy_addr)
    request.meta['proxy'] = 'http://{0}'.format(proxy_addr)

settings.py

这里才是关键,我们需要执行middlewares里面的HttpbinProxyMiddleware类下面的方法,这里需要注意的是我取消了下载中间件的retry中间件,因为scrapy本身就有自动重试的方法,为了试验效果,这里取消了默认的重试中间件。

DOWNLOADER_MIDDLEWARES = {
  'httpbin.middlewares.HttpbinProxyMiddleware': 543,
  #设置不参与scrapy的自动重试的动作
  'scrapy.downloadermiddlewares.retry.RetryMiddleware':None
}

注意:

上面我访问的url是httpbin.org,这个网站不用代理也可以打开,这里你可以在不打开FQ工具的时候,访问google.com,因为我自己学习用的代理地址基本都是国内的地址,所以即使是google也是打不开的。

总结:

上面我们介绍了两种scrapy加代理的写法:

1、第一种是直接每次访问都使用代理IP发起请求

2、第二种是在不能正常获取请求结果的时候,再使用代理ip。

3、我们学习了scrapy中如何打印logging日志,从而简单判断问题和执行步骤。

小知识:

['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
 'httpbin.middlewares.HttpbinProxyMiddleware',
 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
 'scrapy.downloadermiddlewares.stats.DownloaderStats']
2017-11-27 23:36:47 [scrapy.middleware] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
 'scrapy.spidermiddlewares.referer.RefererMiddleware',
 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
 'scrapy.spidermiddlewares.depth.DepthMiddleware']

这里我们可以再Terminal下面打印一下,简单介绍一下:

1、在scrapy中的中间件里面,对应的中间件后面的数字越小,执行优先级越高。

2、如果你想取消某个download_middlewares的话就直接如我上面写的,把它Copy出来,加个None,这样它就不执行了。

3、补充,如果你看过scrapy的基本执行流程图的话,就会知道scrapy除了下载中间件,还有个spider中间件,所以用的时候不要用错了。

D:\项目\小项目\scrapy_day6_httpbin\httpbin>scrapy settings --get=DOWNLOADER_MIDDLEWARES_BASE
{"scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware": 300, "scrapy.downloadermiddlewares.useragent.UserAgentMiddleware": 500, "scrapy.downloadermiddlewares.redirect.MetaRefres
hMiddleware": 580, "scrapy.downloadermiddlewares.httpcache.HttpCacheMiddleware": 900, "scrapy.downloadermiddlewares.redirect.RedirectMiddleware": 600, "scrapy.downloadermiddlewares.r
obotstxt.RobotsTxtMiddleware": 100, "scrapy.downloadermiddlewares.retry.RetryMiddleware": 550, "scrapy.downloadermiddlewares.cookies.CookiesMiddleware": 700, "scrapy.downloadermiddle
wares.defaultheaders.DefaultHeadersMiddleware": 400, "scrapy.downloadermiddlewares.stats.DownloaderStats": 850, "scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddlewar
e": 590, "scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": 750, "scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware": 350, "scrapy.downloadermiddlewar
es.ajaxcrawl.AjaxCrawlMiddleware": 560}

更多关于Python相关内容可查看本站专题:《Python Socket编程技巧总结》、《Python正则表达式用法总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
windows下安装Python和pip终极图文教程
Mar 05 Python
理解Python中的绝对路径和相对路径
Aug 30 Python
Python面向对象类继承和组合实例分析
May 28 Python
pycharm执行python时,填写参数的方法
Oct 29 Python
python使用threading.Condition交替打印两个字符
May 07 Python
获取django框架orm query执行的sql语句实现方法分析
Jun 20 Python
Python Selenium 之数据驱动测试的实现
Aug 01 Python
Python数据可视化:顶级绘图库plotly详解
Dec 07 Python
Python实现http接口自动化测试的示例代码
Oct 09 Python
python 实时调取摄像头的示例代码
Nov 25 Python
在vscode中启动conda虚拟环境的思路详解
Dec 25 Python
Python实战之大鱼吃小鱼游戏的实现
Apr 01 Python
Python中矩阵创建和矩阵运算方法
Aug 04 #Python
Python爬虫框架scrapy实现的文件下载功能示例
Aug 04 #Python
python生成1行四列全2矩阵的方法
Aug 04 #Python
查看python下OpenCV版本的方法
Aug 03 #Python
Python 使用PIL中的resize进行缩放的实例讲解
Aug 03 #Python
numpy中loadtxt 的用法详解
Aug 03 #Python
matplotlib给子图添加图例的方法
Aug 03 #Python
You might like
PHP生成随机密码类分享
2014/06/25 PHP
WordPress的主题编写中获取头部模板和底部模板
2015/12/28 PHP
Laravel Intervention/image图片处理扩展包的安装、使用与可能遇到的坑详解
2017/11/14 PHP
javascript模拟select,jselect的方法实现
2012/11/08 Javascript
论JavaScript模块化编程
2016/03/07 Javascript
AngularJS中update两次出现$promise属性无法识别的解决方法
2017/01/05 Javascript
用vue快速开发app的脚手架工具
2018/06/11 Javascript
echarts设置图例颜色和地图底色的方法实例
2018/08/01 Javascript
微信小程序自定义组件实现环形进度条
2020/11/17 Javascript
JavaScript 预解析的4种实现方法解析
2019/09/03 Javascript
node.js中 mysql 增删改查操作及async,await处理实例分析
2020/02/11 Javascript
JS自定义右键菜单实现代码解析
2020/07/16 Javascript
解决Ant Design Modal内嵌Form表单initialValue值不动态更新问题
2020/10/29 Javascript
[00:48]DOTA2国际邀请赛公开赛报名开始 扫码开启逐梦之旅
2018/06/06 DOTA
[01:06:42]VP vs NewBee Supermajor 胜者组 BO3 第二场 6.5
2018/06/06 DOTA
Django小白教程之Django用户注册与登录
2016/04/22 Python
Python 实现数据库(SQL)更新脚本的生成方法
2017/07/09 Python
python删除某个字符
2018/03/19 Python
Python从ZabbixAPI获取信息及实现Zabbix-API 监控的方法
2018/09/17 Python
django项目搭建与Session使用详解
2018/10/10 Python
详解python读取和输出到txt
2019/03/29 Python
python GUI库图形界面开发之PyQt5计数器控件QSpinBox详细使用方法与实例
2020/02/28 Python
pycharm 添加解释器的方法步骤
2020/08/31 Python
python如何获得list或numpy数组中最大元素对应的索引
2020/11/16 Python
美国批发零售网站:GearXS
2016/07/26 全球购物
屈臣氏官方旗舰店:亚洲享负盛名的保健及美妆零售商
2019/03/15 全球购物
日本最大美瞳直送网:Morecontact(中文)
2019/04/03 全球购物
extern在函数声明中是什么意思
2014/01/19 面试题
保密工作整改报告
2014/11/06 职场文书
2015年保管员工作总结
2015/04/30 职场文书
给男朋友的道歉短信
2015/05/12 职场文书
2015年学校政教处工作总结
2015/05/26 职场文书
公司欠款证明
2015/06/24 职场文书
利用javaScript处理常用事件详解
2021/04/14 Javascript
python机器学习创建基于规则聊天机器人过程示例详解
2021/11/02 Python
java代码实现空间切割
2022/01/18 Java/Android