目标
爬虫中经常遇到被封杀IP的情况,最有效的方式就是使用代理IP。我们可以在一些平台上购买代理IP,但是价格比较昂贵。另外很多IP代理网站也提供了一些免费的代理IP,可以爬取下这些代理IP,并使用webAPI方式提供代理IP服务。
为什么要用代理池?
许多网站有专门的反爬虫措施,可能遇到封IP等问题。
互联网上公开了大量免费代理,利用好资源。
通过定时的检测维护同样可以得到多个可用代理。
代理池的要求?
多站抓取,异步检测
定时筛选,持续更新
提供接口,易于提取
代理池架构?
代理池的实现
项目完整代码已托管到github:https://github.com/panjings/p…
从程序的入口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。
转载请注明:XAMPP中文组官网 » 使用Redis+Flask维护动态代理池