使用Redis+Flask维护动态代理池

目标

爬虫中常常遇到被封杀IP的状况,最有效的方式就是使用代理IP。咱们能够在一些平台上购买代理IP,可是价格比较昂贵。另外不少IP代理网站也提供了一些免费的代理IP,能够爬取下这些代理IP,并使用webAPI方式提供代理IP服务。python

为何要用代理池?

  • 许多网站有专门的反爬虫措施,可能遇到封IP等问题。
  • 互联网上公开了大量免费代理,利用好资源。
  • 经过定时的检测维护一样能够获得多个可用代理。

代理池的要求?

  • 多站抓取,异步检测
  • 定时筛选,持续更新
  • 提供接口,易于提取

代理池架构?

代理池的实现

项目完整代码已托管到github: https://github.com/panjings/p...

项目结构以下:git

从程序的入口run.py开始分析:github

from proxypool.api import app
from proxypool.schedule import Schedule

def main():
    
    s = Schedule()
    // 运行调度器
    s.run()
    // 运行接口
    app.run()

if __name__ == '__main__':
    main()

run.py中不难看出,首先运行了一个调度器,接着运行了一个接口。web

调度器schedule.py代码:redis

class Schedule(object):
    @staticmethod
    def valid_proxy(cycle=VALID_CHECK_CYCLE):
        """
        Get half of proxies which in redis
        """
        conn = RedisClient()
        tester = ValidityTester()
        while True:
            print('Refreshing ip')
            count = int(0.5 * conn.queue_len)
            if count == 0:
                print('Waiting for adding')
                time.sleep(cycle)
                continue
            raw_proxies = conn.get(count)
            tester.set_raw_proxies(raw_proxies)
            tester.test()
            time.sleep(cycle)

    @staticmethod
    def check_pool(lower_threshold=POOL_LOWER_THRESHOLD,
                   upper_threshold=POOL_UPPER_THRESHOLD,
                   cycle=POOL_LEN_CHECK_CYCLE):
        """
        If the number of proxies less than lower_threshold, add proxy
        """
        conn = RedisClient()
        adder = PoolAdder(upper_threshold)
        while True:
            if conn.queue_len < lower_threshold:
                adder.add_to_queue()
            time.sleep(cycle)

    def run(self):
        print('Ip processing running')
        valid_process = Process(target=Schedule.valid_proxy)
        check_process = Process(target=Schedule.check_pool)
        valid_process.start()
        check_process.start()

Schedule中首先声明了valid_proxy(),用来检测代理是否可用,其中ValidityTester()方法中的test_single_proxy()方法是实现异步检测的关键。
接着check_pool()方法里面传入了三个参数:两个代理池的上下界限,一个时间。其中PoolAdder()add_to_queue()方法中使用了一个从网站抓取ip的类FreeProxyGetter()FreeProxyGetter()定义在getter.py里面。flask

接口api.py的代码:api

from flask import Flask, g

from .db import RedisClient

__all__ = ['app']

app = Flask(__name__)


def get_conn():
    """
    Opens a new redis connection if there is none yet for the
    current application context.
    """
    if not hasattr(g, 'redis_client'):
        g.redis_client = RedisClient()
    return g.redis_client


@app.route('/')
def index():
    return '<h2>Welcome to Proxy Pool System</h2>'


@app.route('/get')
def get_proxy():
    """
    Get a proxy
    """
    conn = get_conn()
    return conn.pop()


@app.route('/count')
def get_counts():
    """
    Get the count of proxies
    """
    conn = get_conn()
    return str(conn.queue_len)


if __name__ == '__main__':
    app.run()

不难看出,在api.py中利用了flask框架的特性定义了各类接口。架构

具体代码实现请参考github。app

相关文章
相关标签/搜索