爬虫进阶:框架功能完善-多爬虫实现之动态导入模块

未匹配的标注

动态导入模块

目前代码存在的问题

通过前面的代码编写,我们已经能够完成大部分的任务,但是在main.py 中的代码非常臃肿,对应的我们可以再settings.py 配置哪些爬虫,管道,中间件需要开启,能够让整个代码的逻辑更加清晰

模块动态导入的方法

  • 利用importlib.import_modle能够传入模块的路径,即可即可实现根据模块的位置的字符串,导入该模块的功能
  • 在项目路径下新建test.py观察现象,插入如下代码观察现象

在settings中设置SPIDER,MIDDLEWARES

利用在配置文件中设置需要启用的爬虫类、管道类、中间件类

利用importlib模块,在引擎中动态导入并实例化

  ....
  from scrapy_plus.conf.settings import SPIDERS, PIPELINES, \
      SPIDER_MIDDLEWARES,DOWNLOADER_MIDDLEWARES

  class Engine:
      '''完成对引擎模块的封装'''

      def __init__(self):
          '''
          实例化其他的组件,在引起中能够通过调用组件的方法实现功能
          '''
          self.spiders = self._auto_import_instances(SPIDERS,isspider=True)
          self.downloader = Downloader()
          self.scheduler = Scheduler()

          self.pipelines = self._auto_import_instances(PIPELINES)
          self.spider_mids = self._auto_import_instances(SPIDER_MIDDLEWARES)
          self.downloader_mids =self._auto_import_instances(DOWNLOADER_MIDDLEWARES)
          self.total_request_nums = 0
          self.total_response_nums = 0

      def _auto_import_instances(self,path=[],isspider=False):
          '''通过配置文件,动态导入类并实例化
          path: 表示配置文件中配置的导入类的路径
          isspider: 由于爬虫需要返回的是一个字典,因此对其做对应的判断和处理
          '''
          # 该方法不仅实例化动态导入爬虫,还有管道和中间件,而前者返回应是字典类型
          if isspider is True:
              instances = {}
          else:
              instances = []    # 存储对应类的实例对象

          for p in path:
              module_name = p.rsplit(".",1)[0]    # 取出模块名称
              cls_name = p.rsplit(".",1)[1]    # 取出类名称
              ret = importlib.import_module(module_name)    # 动态导入爬虫模块
              cls = getattr(ret, cls_name)    # 根据类名称获取类对象
              if isspider is True:
                  instances[cls.name] = cls()
              else:
                  instances.append(cls())    # 实例化类对象
          return instances    # 返回类对象
  ......

修改main.py

这样main.py就不用再导入并传入那么多对象了:

# project_dir/main.py
from scrapy_plus.core.engine import Engine    # 导入引擎

if __name__ == '__main__':
    engine = Engine()  # 创建引擎对象
    engine.start()    # 启动引擎

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~