蒋振飞的博客 - Flask+Redis维护代理池   
正在加载蒋振飞的博客...
V3.0
蒋振飞的博客

Flask+Redis维护代理池

发布时间: 2018年08月06日 发布人: 蒋振飞 热度: 569 ℃ 评论数: 0

声明:此篇文章主要是观看静觅教学视频后做的笔记,原教程地址https://cuiqingcai.com/

  普通代理

    因为之前都是学习测试,不需要对网站频繁的搜索爬取,所以代理使用似乎关系不大,不过为了防止IP被封,也是一个很重要的知识点。之前使用代理也都是查找一些代理网站,手动将IP设置添加到proxies参数中,比较麻烦,而且代理IP也有可能出现无法正常访问的情况。

import requests
proxies = {
  "http": "http://127.0.0.1:9743",
  "https": "https://127.0.0.1:9743",
}
response = requests.get("https://www.taobao.com", proxies=proxies)

    维护代理池

1.为什么要用代理池
    ①许多网站有专门的反爬虫措施,可能遇到封IP等问题  。
    ②互联网上公开了大量免费代理,利用好资源。
    ③通过定时的检测维护同样可以得到多个可用代理。

2.代理池的要求
    ①多站抓取,异步检测。
    ②定时筛选,持续更新。
    ③提供接口,易于提取。

3.代理池的架构
   proxy_pool.jpeg

4.代理池的获取途径   
    现在,新增一个解决思路,那就是通过Flask+Redis维护代理池。免费代理的质量可能不是太好,可能一个代理无数个人在用也说不定,主要实现就是从免费代理网站大量抓取这些免费代理,然后筛选出其中可用的代理存储起来供我们使用,不可用的进行剔除,以西刺免费代理IP为例。proxy_list.png        

    可以看到网页里提供了一些免费代理列表,包括服务器地址、端口、代理种类、地区、更新时间等等信息。当前我们需要的就是代理服务器和端口信息,将其爬取下来即可

5.维护代理
    代理被爬取下来之后,就要解决代理的保存问题。首先我们需要确保的目标是可以边取边存,另外还需要定时检查队列中不可用的代理将其剔除,所以需要易于存取。
    另外怎样区分哪些是最新的可用的,哪些是旧的,如果用修改时间来标注是可以的,不过更简单的方法就是维护一个队列,只从一端存入,例如右端,这样就能确保最新的代理在队列右端,而在左端则是存入时间较长的代理,如果要取一个可用代理,从队列右端取一个就好了。那么对于队列的左端,不能让它一直老化下去,还需要做的操作就是定时从队列左端取出代理,然后进行检测,如果可用,重新将其加入右端。
    通过以上操作,就保证了代理一直是最新可用的。所以目前来看,既能高效处理,又可以做到队列动态维护,合适的方法就是利用Redis数据库的队列。可以定义一个类来维护一个Redis队列,比如get方法是批量从左端取出代理,put方法是从右端放入可用代理,pop方法是从右端取出最新可用代理。

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

6.检测代理
    可以使用这个代理来请求某个站点,比如百度,如果获得正常的返回结果,那证明代理可用,否则代理不可用。

import requests

conn = RedisClient()
proxies = {'http': proxy}
r = requests.get('https://www.baidu.com', proxies=proxies)
if r.status_code == 200:
    conn.put(proxy)

7.获取可用代理
    通过redis-desktop可以看到一个proxies的键,其内容就是一些可用的IP代理,也就是所维护的代理池。
   2018-08-07 10-25-49屏幕截图.png
    维护了一个代理池,那么这个代理池需要是可以公用的。比如现在有多个爬虫项目都需要用到代理,而代理池的维护作为另外的一个项目,他们之间如果要建立连接,最恰当的方式就是接口。所以可以利用Web服务器来实现一个接口,其他的项目通过请求这个接口得到内容获取到一个可用代理,这样保证了代理池的通用性。所以要实现这个还需要一个Web服务器,例如Flask,Tornado等等。例如使用Flask,定义一个路由,然后调用RedisClient的pop方法,返回结果即可。

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

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

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

web_ip.jpg

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

    可以定义一个简单的方法,返回网页内容即代理,然后在爬取方法里设置代理使用即可。

10.代理池功能测试
    在了解了前面内容之后,现学现用,马上用代理池测试访问了我的站点。

11.代理池完整源码
    我是从崔家华老师的github上下载下来的,源码可参考:https://github.com/Germey/ProxyPool  

    下载后发现源码不能正常安装,发现是在setup.py文件中有个参数配置错误

# 将
packages=[
        'proxy-pool'
    ],
# 改为
packages=[
        'proxypool'
    ],

    修改后的项目地址:https://github.com/XiaoFei-97/ProxyPool

打赏 蒋振飞

取消

感谢您的支持,我会继续努力的!

扫码支持
一分也是爱     一块不嫌多

点击 支付宝 或 微信 打赏蒋振飞

打开支付宝扫一扫,即可进行扫码打赏哦

评论列表