class RunSpider(object): def __init__(self): self.pool = Pool() self.proxy_pool = MongoPool() def _auto_import_instances(self): """根据配置信息, 自动导入爬虫""" instances = [] # 遍历配置的爬虫, 获取爬虫路径 for path in settings.PROXIES_SPIDERS: # 根据路径, 获取模块名 和 类名 module_name, cls_name = path.rsplit('.', maxsplit=1) # 根据模块名导入模块 module = importlib.import_module(module_name) # 根据类名, 从模块中, 获取爬虫类 cls = getattr(module, cls_name) # 创建爬虫对象, 添加到列表中 instances.append(cls()) # 返回爬虫对象列表 return instances def run(self): """启动爬虫""" # 获取代理爬虫 spiders = self._auto_import_instances() # 执行爬虫获取代理 for spider in spiders: # 使用协程异步调用该方法,提高爬取的效率 self.pool.apply_async(self.__run_one_spider, args=(spider, )) # 等待所有爬虫任务执行完毕 self.pool.join() def __run_one_spider(self, spider): try: for proxy in spider.get_proxies(): if proxy is None: # 如果是None继续一个 continue # 检查代理, 获取代理协议类型, 匿名程度, 和速度 proxy = check_proxy(proxy) # 如果代理速度不为-1, 就是说明该代理可用 if proxy.speed != -1: # 保存该代理到数据库中 self.proxy_pool.save(proxy) except Exception as e: logger.exception(e) logger.exception("爬虫{} 出现错误".format(spider)) @classmethod def start(cls): # 创建本类对象 run_spider = RunSpider() run_spider.run() # 每隔 SPIDER_INTERVAL 小时检查下代理是否可用 schedule.every(settings.SPIDER_INTERVAL).hours.do(run_spider.run()) while True: schedule.run_pending() time.sleep(1)
class RunSpiders(object): """ 启动各个爬虫 """ def __init__(self): """ 创建协程池及数据库操作对象 """ self.pool = Pool() self.proxy_pool = MongoPool() @staticmethod def _import_spider_instance(): """ 动态导入各爬虫模块并创建爬虫对象 :return: """ # 存放爬虫对象 instances = [] # 依次导入各爬虫模块并创建爬虫对象 for instance_path in PROXIES_SPIDERS: # 获取爬虫模块路径及爬虫类名称 module_name, class_name = instance_path.rsplit('.', maxsplit=1) # 导入模块 module = importlib.import_module(module_name) # 获取模块中的爬虫对象 _class = getattr(module, class_name) # 创建爬虫对象,并加入爬虫列表中 instances.append(_class()) return instances def _run_spider(self, spider): """ 开启爬虫 :param spider: :return: """ try: # 获取代理ip数据 for proxy in spider.get_proxies(): if proxy is None: continue # 检测此代理ip proxy = check_proxy(proxy) # 判断此代理ip是否有效 if proxy.speed != -1: # 将此代理ip保存到数据库中 self.proxy_pool.save(proxy) except Exception as e: logger.exception("爬虫{}出错,原因:{}".format(spider, e)) def run(self): """ 将各个爬虫加入到协程池中,并启动 :return: """ # 导入爬虫模块,并创建对象 spiders = self._import_spider_instance() # 将各个爬虫加入到协程池中 for spider in spiders: # 异步非阻塞 self.pool.apply_async(self._run_spider, args=(spider, )) # 让主线程等待异步任务完成 self.pool.join() @classmethod def start(cls): """ 开启爬虫服务 :return: """ # 创建并启动爬虫 spiders = cls() spiders.run() # 设置定时启动爬虫 schedule.every(SPIDER_INTERVAL).hours.do(spiders.run) while True: # 运行任务 schedule.run_pending() time.sleep(1)