博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通过Flask和Redis构造一个动态维护的代理池
阅读量:6292 次
发布时间:2019-06-22

本文共 2285 字,大约阅读时间需要 7 分钟。

代理池的维护

目前有很多网站提供,而且种类齐全,比如各个地区、各个匿名级别的都有,不过质量实在不敢恭维,毕竟都是免费公开的,可能一个代理无数个人在用也说不定。所以我们需要做的是大量抓取这些免费代理,然后筛选出其中可用的代理存储起来供我们使用,不可用的进行剔除。

 

获取代理的途径

 维护一个代理池第一步就是要找到提供免费代理的站点,例如,网页内容如下:

 

 

而且可以看到网页里提供了一些免费代理列表,包括服务器地址、端口、代理种类、地区、更新时间等等信息。

当前我们需要的就是代理服务器和端口信息,将其爬取下来即可。

维护代理

那么问题来了,当我们把这些免费的代理爬取下来后,该怎么去保存他们?

首先我们需要确保这个数据库可以是我们边存边取,另外还需要定时检查队列中那些过期的代理并将它们剔除,所以需要易于存取。

另外怎么区分代理的新旧,如果按照代理网站上给出的代理的修改时间来标识是可行的,但是更简单的方法就是维护一个队列,确保只从一端存入,例如右端,这样就能确保最新的代理一直处于队列的右段,而在队列左端的则是存取时间较长的,那么在使用时我们就可以提取队列右端的代理来使用。

那么对于队列左端的代理我们也不能就这么任其老化,还要做的操作就是把左端的代理提取出来,进行测试,将那些可以使用的放入队列右端,不能使用了的则剔除队列。

通过以上操作,就保证了队列里的代理一直处于可用状态。

所以从目前来看,既能高效处理,又可以做到队列动态维护,合适的方法就是使用Redis数据库的队列。

 

下面这张流程图就是整个代理队列需要具备的功能:

 

可以定义一个类来维护一个Redis队列,比如get方法是从左端取出,put方法是从右端放入,pop方法时从右端取出可用代理。

 

import redis from proxypool.error import PoolEmptyError from proxypool.setting import HOST,PORT,PASSWORD class RedisClient(object):   def __init__(self,host=HOST,port=PORT,password=PASSWORD):     if password:       self._db = redis.Redis(host,port,password)     else:       self._db = redis.Redis(host,port)   def get(self, count=1):     proxies = self._db.Irange("proxies",0, count - 1)     self._db.Itrim("proxis", count, -1)     return proxies   def put(self,proxy):     self._db.rpush("proxies", proxy)   def pop(self,self):     try:       self._db.rpop("proxies").decode('utf-8')     except:       raise PoolEmptyError

 

 

  

 

检测代理

那么如何来检测代理是否可用呢?可以使用这个代理来请求某个网站,如果返回的200则证明这个代理可用,否则代理不可使用。

 

conn = RedisClient()proxies = {'http': proxy}r = requests.get(url,proxies=proxies)if r.status_code == 200:  conn.put(proxy)

  

例如在这里proxy就是要检测的代理,使用requests库设置好这个代理,然后请求百度,正常请求,那就可以将这个代理存入Redis。

 

 

获取可用代理

现在我们维护了一个代理池,那么这个代理池需要是可以公用的。

比如现在有多个爬虫项目都需要用到代理,而代理池的维护作为另外的一个项目,他们之间如果要建立连接,最恰当的方式就是接口。

所以可以利用Web服务器来实现一个接口,其他的项目通过请求这个接口得到内容获取到一个可用代理,这样保证了代理池的通用性。

所以要实现这个还需要一个Web服务器,例如Flask,Tornado等等。

例如使用Flask,定义一个路由,然后调用的RedisClient的pop方法,返回结果即可。

 

@app.route('/get')def get_proxy():   conn = RedisClient()      return conn.pop()

  

这样一来,整个程序运行起来后,请求网页就可以看到一个可用代理了。  

 

 

使用代理

使用代理只需要请求这个站点,就可以拿到使用的代理了。

 

def get_proxy():    r = requests.get('http://127.0.0.1:5000/get')    proxy = r.text    return proxydef crawl(url, proxy):    proxies = {'http': get_proxy()}    r = requests.get(url, proxies=proxies)    #do something

 

  

 

  

样例实现  

 

 

转载于:https://www.cnblogs.com/coder-gao/p/7559801.html

你可能感兴趣的文章
Serverless五大优势,成本和规模不是最重要的,这点才是
查看>>
Nginx 极简入门教程!
查看>>
iOS BLE 开发小记[4] 如何实现 CoreBluetooth 后台运行模式
查看>>
Item 23 不要在代码中使用新的原生态类型(raw type)
查看>>
为网页添加留言功能
查看>>
JavaScript—数组(17)
查看>>
Android 密钥保护和 C/S 网络传输安全理论指南
查看>>
以太坊ERC20代币合约优化版
查看>>
Why I Began
查看>>
同一台电脑上Windows 7和Ubuntu 14.04的CPU温度和GPU温度对比
查看>>
js数组的操作
查看>>
springmvc Could not write content: No serializer
查看>>
Python系语言发展综述
查看>>
新手 开博
查看>>
借助开源工具高效完成Java应用的运行分析
查看>>
163 yum
查看>>
第三章:Shiro的配置——深入浅出学Shiro细粒度权限开发框架
查看>>
80后创业的经验谈(转,朴实但实用!推荐)
查看>>
让Windows图片查看器和windows资源管理器显示WebP格式
查看>>
我的友情链接
查看>>