潘景

使用Redis+Flask维护动态代理池
目标爬虫中经常遇到被封杀IP的情况,最有效的方式就是使用代理IP。我们可以在一些平台上购买代理IP,但是价格比较昂...
扫描右侧二维码阅读全文
31
2018/10

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

目标

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

为什么要用代理池?

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

代理池的要求?

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

代理池架构?

代理池的实现

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

项目结构如下:

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

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

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

if __name__ == '__main__':
    main()

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

调度器schedule.py代码:

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里面。

接口api.py的代码:

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。

Last modification:March 8th, 2019 at 03:45 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment