利用python创建自己的代理池,可以自己以后使用。
初始数据
proxypool.setting
# Redis数据库地址
REDIS_HOST = '127.0.0.1'
# Redis端口
REDIS_PORT = 6379
# Redis密码,如无填None
REDIS_PASSWORD = None
REDIS_KEY = 'proxies'
# 代理分数,最高为100分,最低我0分。初始分数为10分
MAX_SCORE = 100
MIN_SCORE = 0
INITIAL_SCORE = 10
# 有效的状态码
VALID_STATUS_CODES = [200, 302]
# 代理池数量界限
POOL_UPPER_THRESHOLD = 50000
# 检查周期
TESTER_CYCLE = 20
# 获取周期
GETTER_CYCLE = 300
# 测试API,建议抓哪个网站测哪个,这里用百度网来测试API
TEST_URL = 'http://www.baidu.com'
# API配置,API地址、端口
API_HOST = '0.0.0.0'
API_PORT = 5555
# 开关
TESTER_ENABLED = True
GETTER_ENABLED = True
API_ENABLED = True
# 最大批测试量
BATCH_TEST_SIZE = 10
异常问题
proxypool.error
class PoolEmptyError(Exception):
def __init__(self):
# Exception类,是所有非退出异常的公共基类。
Exception.__init__(self)
def __str__(self):
# repr函数,返回对象的规范字符串表示形式。
return repr('代理池已经枯竭')
存储模块
proxypool.db
import redis
from proxypool.error import PoolEmptyError
from proxypool.setting import REDIS_HOST, REDIS_PORT, REDIS_PASSWORD, REDIS_KEY
from proxypool.setting import MAX_SCORE, MIN_SCORE, INITIAL_SCORE
from random import choice
import re
class RedisClient(object):
def __init__(self, host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD):
"""
初始化
:param host: Redis 地址
:param port: Redis 端口
:param password: Redis密码
"""
# 创建链接数据库对象
self.db = redis.StrictRedis(host=host, port=port, password=password, decode_responses=True)
def add(self, proxy, score=INITIAL_SCORE):
"""
添加代理,设置分数为最高
:param proxy: 代理
:param score: 分数
:return: 添加结果
"""
# zscore() 方法,返回 "REDIS_KEY" 中元素为 "proxy" 的分数。
# zadd() 方法,将任意数量的元素名称、分数对设置为键 "REDIS_KEY"。
if not re.match('\d+\.\d+\.\d+\.\d+\:\d+', proxy):
print('代理不符合规范', proxy, '丢弃')
return
if not self.db.zscore(REDIS_KEY, proxy):
return self.db.zadd(REDIS_KEY, score, proxy)
def random(self):
"""
从数据库中随机获取有效代理,首先尝试获取最高分数代理,如果不存在,按照排名获取,否则异常
:return: 随机代理
"""
# zrangebyscore() 方法,返回排序集 "REDIS_KEY" 中带分数的值,其中分数范围为 MAX_SCORE ~ MAX_SCORE ,即返回 100 分的代理
# 代理的有效程度以分数来区分,分数高,说明代理越稳定。
# 首先查找 100 分的代理,如果没有,则在 0 ~ 100 之间查找最高分的代理,
# 如果还没有,则调用 proxypool.error.PoolEmptyError 抛出异常
result = self.db.zrangebyscore(REDIS_KEY, MAX_SCORE, MAX_SCORE)
if len(result):
return choice(result)
else:
result = self.db.zrevrange(REDIS_KEY, 0, 100)
if len(result):
return choice(result)
else:
raise PoolEmptyError
def decrease(self, proxy):
"""
代理值减一分,小于最小值则删除
:param proxy: 代理
:return: 修改后的代理分数
"""
# zscore() 方法,返回 "REDIS_KEY" 中元素为 "proxy" 的分数。
# zincrby() 方法,按 “-1” 增加排序集 "REDIS_KEY" 中 "proxy" 的分数
# zrem() 方法,从排序集 "REDIS_KEY" 中删除成员 "proxy"
score = self.db.zscore(REDIS_KEY, proxy)
if score and score > MIN_SCORE:
print('代理', proxy, '当前分数', score, '减1')
return self.db.zincrby(REDIS_KEY, proxy, -1)
else:
print('代理', proxy, '当前分数', score, '移除')
return self.db.zrem(REDIS_KEY, proxy)
def exists(self, proxy):
"""
判断是否存在
:param proxy: 代理
:return: 是否存在
"""
# zscore() 方法,返回 "REDIS_KEY" 中元素为 "proxy" 的分数。
return not self.db.zscore(REDIS_KEY, proxy) == None
def max(self, proxy):
"""
将代理设置为MAX_SCORE
:param proxy: 代理
:return: 设置结果
"""
print('代理', proxy, '可用,设置为', MAX_SCORE)
# zadd() 方法,将任意数量的元素名称、分数对设置为键 "REDIS_KEY"。
return self.db.zadd(REDIS_KEY, MAX_SCORE, proxy)
def count(self):
"""
获取数量
:return: 数量
"""
# zcard() 方法,返回排序集 "REDIS_KEY" 中的元素个数
return self.db.zcard(REDIS_KEY)
def all(self):
"""
获取全部代理
:return: 全部代理列表
"""
# zrangebyscore()方法,获取 MIN_SCORE ~ MAX_SCORE 的代理,即所有代理
return self.db.