7. 实现代理池的数据库模块
作用:
用于对proxies
集合进行数据库的相关操作
目标
: 实现对数据库增删改查相关操作
步骤
:
- 在
init
中, 建立数据连接, 获取要操作的集合, 在 del
方法中关闭数据库连接
- 提供基础的增删改查功能
- 实现插入功能
- 实现修改该功能
- 实现删除代理: 根据代理的IP删除代理
- 查询所有代理IP的功能
- 提供代理API模块使用的功能
- 实现查询功能: 根据条件进行查询, 可以指定查询数量, 先分数降序, 速度升序排, 保证优质的代理IP在上面.
- 实现根据协议类型 和 要访问网站的域名, 获取代理IP列表
- 实现根据协议类型 和 要访问网站的域名, 随机获取一个代理IP
- 实现把指定域名添加到指定IP的disable_domain列表中.
完整代码
import pymongo
import random
from settings import MONGO_URL, DEFAULT_SCORE
from domain import Proxy
from utils.log import logger
class MongoPool(object):
def __init__(self):
"""初始化"""
self.client = pymongo.MongoClient(MONGO_URL)
self.proxies = self.client['proxy_pool']['proxies']
def __del__(self):
self.client.close()
def insert(self, proxy=None):
"""保存代理IP到数据库中"""
if proxy:
count = self.proxies.count_documents({'_id': proxy.ip})
if count != 0:
return
dic = proxy.__dict__
dic['_id'] = proxy.ip
self.proxies.insert_one(dic)
logger.info("插入新代理IP:{}".format(dic))
else:
logger.error("没有传入要插入的proxy")
def update(self, proxy=None):
"""更新代理"""
if proxy:
self.proxies.update_one({'_id':proxy.ip}, {"$set": proxy.__dict__})
logger.info("更新代理: {}".format(proxy))
else:
logger.error("请求传入要更新的代理")
def find_all(self):
cursor = self.proxies.find()
for item in cursor:
item.pop('_id')
proxy = Proxy(**item)
yield proxy
def delete(self, proxy=None):
"""根据条件删除代理IP"""
if proxy:
self.proxies.delete_one({'_id': proxy.ip})
logger.info('删除代理: {}'.format(proxy))
else:
logger.error("请传入要删除的代理")
def find(self, conditions=None, count=0):
"""
根据条件查询代理IP
:param conditions: # 字典形式的查询条件
:param count: 查询多少条数据
:return: 返回先按分数降序, 后按响应速度升序排列前count条数据, 如果count==0, 就查询所有的,
"""
if conditions is None:
conditions = {}
cursor = self.proxies.find(conditions, limit=count).sort(
[("score", pymongo.DESCENDING), ("speed", pymongo.ASCENDING)])
results = []
for item in cursor:
item.pop('_id')
proxy = Proxy(**item)
results.append(proxy)
return results
def get_proxies(self, protocol=None, domain=None, count=0, nick_type=0):
"""
根据协议类型, 获取代理IP, 默认查询都是高匿的
:param protocol: 协议: http 或 https
:param domain: 要访问网站的域名
:param count: 代理IP的数量, 默认全部
:param nick_type: 匿名程度, 默认为高匿
:return:
"""
conditions = {'nick_type': nick_type}
if domain:
conditions['disable_domains'] = {'$nin':[domain]}
if protocol is None:
conditions['protocol'] = 2
elif protocol.lower() == 'http':
conditions['protocol'] = {'$in': [2, 0]}
elif protocol.lower() == 'https':
conditions["protocol"] = {'$in': [2, 1]}
return self.find(conditions, count=count)
def random(self, protocol=None, domain=None, count=0):
"""
从指定数量代理IP中, 随机获取一个
:param protocol: 协议: http 或 https
:param domain: 要访问网站的域名
:param count: 代理IP的数量
:return: 一个随机获取代理IP
"""
proxy_list = self.get_proxies(protocol, domain=domain, count=count)
return random.choice(proxy_list)
def disable_domain(self, ip, domain):
if self.proxies.count_documents({'_id':ip,'disable_domains':domain}) == 0:
self.proxies.update_one({'_id': ip}, {'$push': {'disable_domains': domain}})
if __name__ == '__main__':
proxy = Proxy('124.89.97.46', '80', protocol=0, nick_type=2, speed=0.36, area='陕西省商洛市商州区')
mongo.delete(proxy)
proxies = mongo.find({'nick_type': 0})
for proxy in proxies:
print(proxy)
总结
:
- 在
init
中, 建立数据连接, 获取要操作的集合, 在 del
方法中关闭数据库连接
- 提供基础的增删改查功能
- 提供代理API模块使用的功能