python scrapy框架的日志文件问题
作者:小胖_@
这篇文章主要介绍了python scrapy框架的日志文件问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
scrapy框架中的常用日志配置
LOG_FILE
: 日志输出文件,如果为None,日志信息会打印在控制台;LOG_ENABLED
: 是否启用日志,默认True;LOG_ENCODING
: 日志编码,默认utf-8;LOG_LEVEL
: 日志等级,默认debug;LOG_FORMAT
: 日志格式;LOG_DATEFORMAT
: 日志日期格式;LOG_STDOUT
: 日志标椎输出,默认False,如果是True所有标椎输出都将写入日志中;LOG_SHORT_NAMES
: 短日志名,默认False,如果是True将不输出组件名。
日志级别
CRITICAT
— 严重错误ERROR
— 一般错误WARNING
— 警告信息INFO
— 一般信息DEBUG
— 调试信息
级别:
CRITICAT>ERROR>WARNING>INFO>DEBUG
logging模块常用format格式说明
%(levelno)s
: 打印日志级别的数值%(levelname)s
: 打印日志级别名称%(pathname)s
: 打印当前执行程序的路径,其实就是sys.argv[0]%(filename)s
: 打印当前执行程序名%(funcName)s
: 打印日志的当前函数%(lineno)d
: 打印日志的当前行号%(asctime)s
: 打印日志的时间%(thread)d
: 打印线程ID%(threadName)s
: 打印线程名称%(process)d
: 打印进程ID%(message)s
: 打印日志信息
日期格式
%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
当前时区的名称%%
%号本身
日志配置的常用形式(代码)
LOG_FILE = "日志文件名" LOG_LEVEL = "日志级别" # 显示日志级别以上的日志信息(包括自己) LOG_DATEFORMAT = "%Y-%m-%d %H:%M:%S" LOG_FORMAT = "%(asctime)s-%(levelname)s-%(filename)s-%(funcName)s-%(message)s-%(lineno)d"
scrapy中爬虫使用日志
在爬虫文件中使用日志:
1.导包 logging;
import logging
2.在自定义custom_settings中添加日志基本配置;
custom_settings = { "LOG_FILE": "a.log", "LOGLEVEL": "INFO" }
3.因为在scrapy框架中,爬虫文件直接self打点调用log(),将信息添加到日志文件中;
# logging.INFO 日志级别 self.log("准备采集导航条",logging.INFO)
4.在日志文件中添加日志错误信息,需要对错误信息进行转换,因为log()只能添加字符串日志信息。
基本代码实现
try: a = [] print(a[0]) except Exception as e: # self.log(str(e), logging.ERROR) self.log(f"{repr(e)},错误在{sys._getframe().f_code.co_filename}的{sys._getframe().f_lineno}行", logging.ERROR) # self.log(e.message, logging.ERROR) # self.log(traceback.print_exc(), logging.ERROR) # self.log(traceback.format_exc(), logging.ERROR)
scrapy 中管道使用文件
1.导包 logging;
import logging
2.配置日志中名字
log = logging.getLogger("a.log")
3.添加日志文件信息
log.info("日志存储信息") log.debug("日志存储信息") log.critical("日志存储信息") log.error("日志存储信息") log.warning("日志存储信息")
自定义日志工具类
第一个
- logger.py
#!_*_coding:utf-8_*_ import logging import os LOG_LEVEL = logging.INFO BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 自定义日志类型 LOG_TYPES = { 'transaction': 'transactions.log', 'access': 'access.log', } def log(log_type): """ from logger.logger import log log_obj = log('日志名称') log_obj.info("普通消息") log_obj.debug("调试消息") log_obj.warn("警告消息") log_obj.error("错误消息") log_obj.critical("hello world") """ log_dir = "%s/log" % (BASE_DIR) log_file = "%s/%s" % (log_dir, LOG_TYPES.get(log_type, log_type+".log")) os.makedirs(log_dir, exist_ok=True) # 创建日志对象 logger = logging.getLogger(log_type) logger.setLevel(LOG_LEVEL) # 创建一个handler,用于输出到控制台 ch = logging.StreamHandler() ch.setLevel(LOG_LEVEL) # 创建一个handler,用于写入日志文件 fh = logging.FileHandler(log_file, encoding="utf-8") fh.setLevel(LOG_LEVEL) # 定义handler的输出格式formatter """ 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 字符串形式的当前时间。默认格式是 “2018-07-08 16:49:45,896”。逗号后面的是毫秒 %(thread)d 线程ID。可能没有 %(threadName)s 线程名。可能没有 %(process)d 进程ID。可能没有 %(message)s用户输出的消息 """ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) fh.setFormatter(formatter) # 给logger添加handler logger.addHandler(ch) logger.addHandler(fh) return logger
- 使用方法
1.导包
from logger import log
2.调用
log_obj = log('日志文件名') log_obj.info("普通消息") log_obj.debug("调试消息") log_obj.warn("警告消息") log_obj.error("错误消息") log_obj.critical("严重错误信息")
第二个
logger.py
import logging from logging import StreamHandler, FileHandler, Formatter from logging.handlers import TimedRotatingFileHandler, RotatingFileHandler class Logger(object): # log = logging.getLogger(__name__) filename = "123.log" log_format = "%(asctime)s|%(levelname)s|%(filename)s|%(funcName)s|%(message)s|%(lineno)d" is_file = False is_time = False @classmethod def log_init(cls): log = logging.getLogger(__name__) handler1 = StreamHandler() # 输出 handler2 = FileHandler(cls.filename, encoding="gb2312") # 写入 log.setLevel(logging.DEBUG) handler1.setLevel(logging.DEBUG) handler2.setLevel(logging.DEBUG) format = Formatter(cls.log_format) handler1.setFormatter(format) handler2.setFormatter(format) if cls.is_time: # interval 是指等待多少个单位when的时间后,Logger会自动重建文件,当然,这个文件的创建取决于filename+suffix,若这个文件跟之前的文件有重名,则会自动覆盖掉以前的文件,所以有些情况suffix要定义的不能因为when而重复。 # backupCount 是保留日志个数。默认的0是不会自动删除掉日志。若设3,则在文件的创建过程中库会判断是否有超过这个3,若超过,则会从最先创建的开始删除。 filehandler = logging.handlers.TimedRotatingFileHandler("a" + cls.filename, when='S', interval=1, backupCount=3) # 设置后缀名称,跟strftime的格式一样 when设置的是S这个结尾必须是S.log filehandler.suffix = "%Y-%m-%d_%H-%M-%S.log" filehandler.setFormatter(format) log.addHandler(filehandler) if cls.is_file: # 写入文件,如果文件超过100个Bytes,仅保留5个文件。 handler = logging.handlers.RotatingFileHandler(cls.filename, maxBytes=100, backupCount=5) # 设置后缀名称,跟strftime的格式一样 handler.setFormatter(format) log.addHandler(handler) log.addHandler(handler1) log.addHandler(handler2) return log @classmethod def debug(cls, message): log = cls.log_init() log.debug(message) @classmethod def warning(cls, message): log = cls.log_init() log.warning(message) @classmethod def error(cls, message): log = cls.log_init() log.error(message) @classmethod def critical(cls, message): log = cls.log_init() log.critical(message) @classmethod def info(cls, message): log = cls.log_init() log.info(message)
- 使用方法
1.导包
from logger import Logger
2.调用
Logger.filename = "a.log" # 设置日志文件名,如果不设置,默认"123.log" Logger.log_format = "" # 设置日志文件显示格式 Logger.is_file = True # 设置基于文件大小日志存储,默认存储一个日志文件 Logger.is_time = True # 设置基于时间保存日志,默认不设置 Logger.info("普通消息") Logger.debug("调试消息") Logger.warn("警告消息") Logger.error("错误消息") Logger.critical("严重错误信息")
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。