class DbProxiesCheck(object): def __init__(self): # 创建操作数据库对象 self.mongo_pool = MongoPool() # 待检测ip队列 self.queue = Queue() # 协程池 self.coroutine_pool = Pool() # 异步回调函数 def __check_callback(self, temp): self.coroutine_pool.apply_async(self.__check_one, callback=self.__check_one()) def run(self): # 处理检测代理ip核心逻辑 proxies = self.mongo_pool.find_all() for proxy in proxies: self.queue.put(proxy) # 开启多异步任务 for i in range(TEST_PROXIES_ASYNC_COUNT): # 异步回调,死循环执行该方法 self.coroutine_pool.apply_async(self.__check_one, callback=self.__check_one()) # 当前线程等待队列任务完成 self.queue.join() def __check_one(self): # 检查一个代理ip可用性 # 从队列中获取一个proxy proxy = self.queue.get() checked_proxy = check_proxy(proxy) if checked_proxy.speed == -1: checked_proxy.score -= 1 if checked_proxy.score == 0: self.mongo_pool.delete(checked_proxy) else: self.mongo_pool.update(checked_proxy) else: checked_proxy.score = MAX_SCORE self.mongo_pool.update(checked_proxy) # 调度队列的task_done方法(一个任务完成) self.queue.task_done() @classmethod def start(cls): ''' 类方法,依据配置文件的时间间隔运行检测数据库中的ip可用性,单位小时 ''' test = DbProxiesCheck() test.run() schedule.every(TEST_RUN_INTERVAL).hours.do(test.run) while 1: schedule.run_pending() time.sleep(60)
class ProxyTest(object): """ 测试代理ip可用性 """ def __init__(self): """ 初始化进程池、队列及数据库操作对象 """ self.pool = Pool() self.queue = Queue() self.mongo_pool = MongoPool() def _test_proxies(self): """ 测试代理ip可用性,并更新到数据库 :return: """ # 从队列中取出一个代理ip proxy = self.queue.get() try: # 检测代理ip proxy = check_proxy(proxy) # 判断此代理ip此次是否有效,若有效则恢复为默认分值,否则分值减1 if proxy.speed == -1: proxy.score -= 1 # 若评分为0,则表示此代理ip不可用,则从数据库中删除此代理ip if proxy.score == 0: self.mongo_pool.delete(proxy) else: # 更新此代理ip self.mongo_pool.update(proxy) else: # 此代理ip恢复为默认分值 proxy.score = DEFAULT_SCORE # 更新此代理ip self.mongo_pool.update(proxy) except Exception as e: print(e) def _test_callback(self, source): """ 检测代理ip(_test_proxies)的回调函数 :param source: 回调函数所需参数 :return: """ # 使其死循环,不断检测代理ip self.pool.apply_async(self._test_proxies, callback=self._test_callback) def run(self): """ 启动代理ip的检测 :return: """ # 从数据库中获取所有代理ip proxies = self.mongo_pool.find() # 判断是否有代理ip if proxies is None or len(proxies) == 0: print("代理ip池为空") return # 依次将代理ip添加到队列中 for proxy in proxies: self.queue.put(proxy) # 开启若干进程,用于检测代理ip for test in range(TEST_ANSYC_COUNT): # 异步非阻塞 self.pool.apply_async(self._test_proxies, callback=self._test_callback) # 让主线程等待异步任务完成 self.pool.join() @classmethod def start(cls): """ 开启检测代理ip服务 :return: """ # 创建并启动检测 test = cls() test.run() # 定时启动检测 schedule.every(TEST_INTERVAL).hours.do(test.run) while True: # 运行任务 schedule.run_pending() time.sleep(1)
class ProxyTester(object): def __init__(self): self.queue = Queue() self.pool = Pool() # 协程池 self.proxy_pool = MongoPool() # 基于MongoDB的代理池 def _test_proxy(self): # 从代理队列中, 获取请求 proxy = self.queue.get() try: # 验证当前的代理 proxy = check_proxy(proxy) # 如果速度为-1就说明请求失败了 if proxy.speed == -1: # 代理的分数-1 proxy.score -= 1 # 如果分数为0, 就删除该代理 if proxy.score == 0: self.proxy_pool.delete(proxy) logger.info('删除代理:{}'.format(proxy)) else: # 如果分数不为0 ,就更新当前的代理 self.proxy_pool.update(proxy) else: # 如果请求成功了, 恢复为最高分数 proxy.score = settings.MAX_SCORE self.proxy_pool.update(proxy) except Exception as ex: logger.exception(ex) self.queue.task_done() def _test_proxy_finish(self, temp): self.pool.apply_async(self._test_proxy, callback=self._test_proxy_finish) def run(self): # 1. 获取所有代理IP proxies = self.proxy_pool.find() # 2. 如果代理池为空, 直接返回 if proxies is None or len(proxies) == 0: print("代理池为空") return # 获取所有的代理, 放到队列中 for proxy in proxies: self.queue.put(proxy) # 开启多个异步任务执行检查IP的任务 for i in range(settings.TESTER_ANSYC_COUNT): self.pool.apply_async(self._test_proxy,callback=self._test_proxy_finish) # 让主线程等待异步任务完成 self.queue.join() @staticmethod def start(): tester = ProxyTester() tester.run() # 每隔2小时检查下代理是否可用 schedule.every(settings.TESTER_INTERVAL).hours.do(tester.run) while True: schedule.run_pending() time.sleep(1)