# 3.8. 框架完善--实现动态模块导入
# 目标
- 掌握模块的动态导入的方法
- 完成对现有代码的重构
# 1. 目前代码存在的问题
通过前面的代码编写,我们已经能够完成大部分的任务,但是在main.py
中的代码非常臃肿,对应的我们可以再settings.py
配置哪些爬虫,管道,中间件需要开启,能够让整个代码的逻辑更加清晰
# 2. 模块动态导入的方法
利用
importlib.import_modle
能够传入模块的路径,即可即可实现根据模块的位置的字符串,导入该模块的功能在项目路径下新建
test.py
观察现象,插入如下代码观察现象
# 3. 在settings中设置SPIDER,MIDDLEWARES
利用在配置文件中设置需要启用的爬虫类、管道类、中间件类,如下:
# 项目中的settings.py ...... # 增加以下信息: # 启用的爬虫类 SPIDERS = [ 'spiders.baidu.BaiduSpider', 'spiders.douban.DoubanSpider' ] # 启用的管道类 PIPELINES = [ 'pipelines.BaiduPipeline', 'pipelines.DoubanPipeline' ] # 启用的爬虫中间件类 SPIDER_MIDDLEWARES = [] # 启用的下载器中间件类 DOWNLOADER_MIDDLEWARES = []
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22利用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 # 返回类对象 ......
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 4. 修改main.py
这样main.py就不用再导入并传入那么多对象了:
# project_dir/main.py
from scrapy_plus.core.engine import Engine # 导入引擎
if __name__ == '__main__':
engine = Engine() # 创建引擎对象
engine.start() # 启动引擎
1
2
3
4
5
6
2
3
4
5
6
# 小结
- 本小结重点
- 掌握
importlib.import_module
方法使用 - 完成代码的重构,实现通过配置文件导入模块
- 掌握