Wang's blog Wang's blog
首页
  • 前端文章

    • HTML教程
    • CSS
    • JavaScript
  • 前端框架

    • Vue
    • React
    • VuePress
    • Electron
  • 后端技术

    • Npm
    • Node
    • TypeScript
  • 编程规范

    • 规范
  • 我的笔记
  • Git
  • GitHub
  • VSCode
  • Mac工具
  • 数据库
  • Google
  • 服务器
  • Python爬虫
  • 前端教程
更多
收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Wang Mings

跟随大神,成为大神!
首页
  • 前端文章

    • HTML教程
    • CSS
    • JavaScript
  • 前端框架

    • Vue
    • React
    • VuePress
    • Electron
  • 后端技术

    • Npm
    • Node
    • TypeScript
  • 编程规范

    • 规范
  • 我的笔记
  • Git
  • GitHub
  • VSCode
  • Mac工具
  • 数据库
  • Google
  • 服务器
  • Python爬虫
  • 前端教程
更多
收藏
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Python爬虫

    • 爬虫的基础知识

    • 请求的发送方法

    • 数据提取方法

    • 高性能爬虫

    • selenium

    • 反爬以及解决方案

    • MONGODB数据库

    • scrapy框架

    • scrapy_redis

    • 爬虫的部署

    • 爬虫框架开发分析

    • 框架雏形实现

    • 框架功能完善

      • 日志模块使用
        • 框架完善 -- 日志模块的使用
          • 目标
          • 1 为什么要使用添加日志功能
          • 2 日志模块简单使用
          • 日志的等级
          • 捕获异常信息到日志
          • 日志的输出格式
          • datefmt参数说明:
          • 3 利用logger封装日志模块
          • 4 在框架中使用日志模块
          • 5 运行项目中的main.py
          • 小结
          • 本小结涉及修改的完整代码
      • 配置文件实现
      • 多请求实现
      • 多个解析函数实现
      • 多爬虫文件实现
      • 实现多个管道
      • 实现多个中间件
      • 实现动态模块导入
      • 实现请求去重
    • 框架功能升级

    • 项目实战

    • pywin32介绍

  • 前端教程

  • 教程
  • Python爬虫
  • 框架功能完善
wangmings
2022-07-19
目录

日志模块使用

# 框架完善 -- 日志模块的使用

# 目标
  1. 掌握logging模块的使用
  2. 掌握在框架中使用日志功能

# 1 为什么要使用添加日志功能

  1. 能够方便的对程序进行调试
  2. 能够记录程序的运行状态,包括错误

# 2 日志模块简单使用

# 日志的等级
import logging
# 日志的五个等级,等级依次递增
# 默认是WARNING等级
logging.DEBUG
logging.INFO
logging.WARNING
logging.ERROR
logging.CRITICAL
# 设置日志等级
logging.basicConfig(level=logging.INFO)
# 使用
logging.debug('DEBUG')
logging.info('INFO')
logging.warning('WARNING')
logging.error('ERROR')
logging.critical('CRITICAL') 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 捕获异常信息到日志

这里主要需要进行捕获异常才能记录下完整的异常信息

try:
    raise Exception("异常")
except Exception as e:
    logging.exception(e) 
1
2
3
4
# 日志的输出格式

对于日志的输出格式,我们能够进行自定义,包括输出的内容格式和时间格式

format格式说明:

%(name)s  Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s 用户输出的消息 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# datefmt参数说明:
%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 3 利用logger封装日志模块

在scrapy_plus目录下建立utils包 (utility:工具),专门放置工具类型模块,如日志模块log.py 下面的代码内容是固定的,在任何地方都可以使用下面的代码实习日志内容的输出

# scrapy_plus/utils/log.py
import sys
import logging

# 默认的配置
DEFAULT_LOG_LEVEL = logging.INFO    # 默认等级
DEFAULT_LOG_FMT = '%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s: %(message)s'   # 默认日志格式
DEFUALT_LOG_DATEFMT = '%Y-%m-%d %H:%M:%S'  # 默认时间格式
DEFAULT_LOG_FILENAME = 'log.log'    # 默认日志文件名称


class Logger(object):

    def __init__(self):
        # 1. 获取一个logger对象
        self._logger = logging.getLogger()
        # 2. 设置format对象
        self.formatter = logging.Formatter(fmt=DEFAULT_LOG_FMT,datefmt=DEFUALT_LOG_DATEFMT)
        # 3. 设置日志输出
        # 3.1 设置文件日志模式
        self._logger.addHandler(self._get_file_handler(DEFAULT_LOG_FILENAME))
        # 3.2 设置终端日志模式
        self._logger.addHandler(self._get_console_handler())
        # 4. 设置日志等级
        self._logger.setLevel(DEFAULT_LOG_LEVEL)

    def _get_file_handler(self, filename):
        '''返回一个文件日志handler'''
        # 1. 获取一个文件日志handler
        filehandler = logging.FileHandler(filename=filename,encoding="utf-8")
        # 2. 设置日志格式
        filehandler.setFormatter(self.formatter)
        # 3. 返回
        return filehandler

    def _get_console_handler(self):
        '''返回一个输出到终端日志handler'''
        # 1. 获取一个输出到终端日志handler
        console_handler = logging.StreamHandler(sys.stdout)
        # 2. 设置日志格式
        console_handler.setFormatter(self.formatter)
        # 3. 返回handler
        return console_handler

    @property
    def logger(self):
        return self._logger

# 初始化并配一个logger对象,达到单例的
# 使用时,直接导入logger就可以使用
logger = Logger().logger 
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
44
45
46
47
48
49
50
51

# 4 在框架中使用日志模块

使用参考

# scrapy_plus/core/engine.py
from datetime import datetime
from scrapy_plus.utils.log import logger    # 导入logger
......


class Engine(object):

    ......

    def start(self):
        '''启动整个引擎'''
        start = datetime.now()  # 起始时间
        logger.info("开始运行时间:%s" % start)  # 使用日志记录起始运行时间
        self._start_engine()
        stop = datetime.now()  # 结束时间
        logger.info("开始运行时间:%s" % stop)  # 使用日志记录结束运行时间
        logger.info("耗时:%.2f" % (stop - start).total_seconds())  # 使用日志记录运行耗时

...... 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 5 运行项目中的main.py

运行效果:

2018-07-03 11:29:20 engine.py [line:36] INFO: 开始运行时间:2018-07-03 11:29:20.445003
这是爬虫中间件:process_request方法
这是下载器中间件:process_request方法
这是下载器中间件:process_response方法
item:  <scrapy_plus.item.Item object at 0x7f9ea5ae80f0>
2018-07-03 11:29:20 engine.py [line:39] INFO: 开始运行时间:2018-07-03 11:29:20.490725
2018-07-03 11:29:20 engine.py [line:40] INFO: 耗时:0.05 
1
2
3
4
5
6
7

# 小结

  1. 掌握日志的使用方法
  2. 能够在框架中封装日志模块并且进行使用

# 本小结涉及修改的完整代码

scrapy_plus/core/engine.py

 '''引擎组件'''
from scrapy_plus.http.request import Request    # 导入Request对象

from .scheduler import Scheduler
from .downloader import Downloader
from .pipeline import Pipeline
from .spider import Spider

from scrapy_plus.middlewares.spider_middlewares import SpiderMiddleware
from scrapy_plus.middlewares.downloader_middlewares import DownloaderMiddleware

from datetime import datetime
from scrapy_plus.utils.log import logger    # 导入logger

class Engine(object):
    '''
    a. 对外提供整个的程序的入口
    b. 依次调用其他组件对外提供的接口,实现整个框架的运作(驱动)
    '''

    def __init__(self):
        self.spider = Spider()    # 接收爬虫对象
        self.scheduler = Scheduler()    # 初始化调度器对象
        self.downloader = Downloader()    # 初始化下载器对象
        self.pipeline = Pipeline()    # 初始化管道对象

        self.spider_mid = SpiderMiddleware()    # 初始化爬虫中间件对象
        self.downloader_mid = DownloaderMiddleware()    # 初始化下载器中间件对象

    def start(self):
        '''启动整个引擎'''
        start = datetime.now()  # 起始时间
        logger.info("开始运行时间:%s" % start)  # 使用日志记录起始运行时间
        self._start_engine()
        stop = datetime.now()  # 结束时间
        logger.info("开始运行时间:%s" % stop)  # 使用日志记录结束运行时间
        logger.info("耗时:%.2f" % (stop - start).total_seconds())  # 使用日志记录运行耗时

    def _start_engine(self):
        '''依次调用其他组件对外提供的接口,实现整个框架的运作(驱动)'''
        # 1. 爬虫模块发出初始请求
        start_request = self.spider.start_requests()

        # 此处新增
        # 利用爬虫中间件预处理请求对象
        start_request = self.spider_mid.process_request(start_request)

        # 2. 把初始请求添加给调度器
        self.scheduler.add_request(start_request)
        # 3. 从调度器获取请求对象,交给下载器发起请求,获取一个响应对象
        request = self.scheduler.get_request()

        # 此处新增
        # 利用下载器中间件预处理请求对象
        request = self.downloader_mid.process_request(request)

        # 4. 利用下载器发起请求
        response = self.downloader.get_response(request)

        # 此处新增
        # 利用下载器中间件预处理响应对象
        response = self.downloader_mid.process_response(response)

        # 5. 利用爬虫的解析响应的方法,处理响应,得到结果
        result = self.spider.parse(response)
        # 6. 判断结果对象
        # 6.1 如果是请求对象,那么就再交给调度器
        if isinstance(result, Request):

            # 此处新增
            # 利用爬虫中间件预处理请求对象
            result = self.spider_mid.process_request(result)

            self.scheduler.add_request(result)
        # 6.2 否则,就交给管道处理
        else:
            self.pipeline.process_item(result) 
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
编辑 (opens new window)
中间件
配置文件实现

← 中间件 配置文件实现→

最近更新
01
theme-vdoing-blog博客静态编译问题
09-16
02
搜索引擎
07-19
03
友情链接
07-19
更多文章>
Theme by Vdoing | Copyright © 2019-2022 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式