如何为Scrapy内置日志器设置与用户爬虫不同的日志级别?
解决Scrapy内置日志器冗长问题的正确方案
我之前也碰到过Scrapy内置日志太啰嗦的问题,试了好几种方法才找到稳定生效的方案,给你整理了三个靠谱的实现方式:
方法一:通过Scrapy配置文件(settings.py)直接设置
这是最稳妥的方式,因为Scrapy启动时会优先读取配置文件的日志设置,不会被后续的初始化流程覆盖。
在你的settings.py里添加以下配置:
# settings.py LOG_LEVEL = 'INFO' # 将用户自己编写的爬虫日志级别设为INFO,减少冗余输出 # 针对指定的Scrapy内置日志器单独设置DEBUG级别,保留调试信息 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'loggers': { 'scrapy.utils.log': { 'level': 'DEBUG', 'handlers': ['console'], }, 'scrapy.crawler': { 'level': 'DEBUG', 'handlers': ['console'], }, 'scrapy.middleware': { 'level': 'DEBUG', 'handlers': ['console'], }, 'scrapy.core.engine': { 'level': 'DEBUG', 'handlers': ['console'], }, 'scrapy.extensions.logstats': { 'level': 'DEBUG', 'handlers': ['console'], }, 'scrapy.extensions.telnet': { 'level': 'DEBUG', 'handlers': ['console'], }, 'scrapy.core.scraper': { 'level': 'DEBUG', 'handlers': ['console'], }, 'scrapy.statscollectors': { 'level': 'DEBUG', 'handlers': ['console'], }, }, 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'formatter': 'scrapy', }, }, 'formatters': { 'scrapy': { 'format': '%(asctime)s [%(name)s] %(levelname)s: %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S', }, }, }
这里的LOG_LEVEL控制你自己在爬虫里用logging.info()输出的内容级别为INFO,而LOGGING字典则单独把那些内置组件的日志级别设为DEBUG,完美兼顾了精简日志和保留调试信息的需求。
方法二:在爬虫启动前动态配置日志
如果不想修改settings.py,可以在启动爬虫的脚本里提前配置日志,一定要注意:必须在初始化CrawlerProcess之前执行配置,否则Scrapy的默认日志配置会覆盖你的设置。
示例代码:
import logging from scrapy.crawler import CrawlerProcess from scrapy.utils.project import get_project_settings def setup_custom_logging(): # 设置根日志器(用户爬虫日志)级别为INFO root_logger = logging.getLogger() root_logger.setLevel(logging.INFO) # 逐个设置Scrapy内置日志器的级别为DEBUG scrapy_loggers = [ 'scrapy.utils.log', 'scrapy.crawler', 'scrapy.middleware', 'scrapy.core.engine', 'scrapy.extensions.logstats', 'scrapy.extensions.telnet', 'scrapy.core.scraper', 'scrapy.statscollectors' ] for logger_name in scrapy_loggers: logger = logging.getLogger(logger_name) logger.setLevel(logging.DEBUG) # 避免日志重复输出,给每个日志器单独添加处理器并关闭传播 if not logger.handlers: handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s [%(name)s] %(levelname)s: %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) logger.propagate = False if __name__ == "__main__": # 先配置日志,再启动爬虫进程 setup_custom_logging() process = CrawlerProcess(get_project_settings()) # 替换成你的爬虫类 process.crawl(YourSpider) process.start()
你之前的辅助函数有时不生效,大概率是因为调用时机太晚——比如在爬虫的parse方法里才设置,这时候Scrapy已经完成了日志系统的初始化,你的设置会被覆盖。
方法三:在爬虫类的__init__方法中设置
如果只想针对某个特定爬虫调整日志级别,可以在爬虫类的__init__方法里设置,这样不会影响项目里的其他爬虫。
示例代码:
import logging import scrapy class YourSpider(scrapy.Spider): name = 'your_spider' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 设置用户爬虫日志级别为INFO logging.getLogger().setLevel(logging.INFO) # 配置Scrapy内置日志器为DEBUG级别 scrapy_loggers = [ 'scrapy.utils.log', 'scrapy.crawler', 'scrapy.middleware', 'scrapy.core.engine', 'scrapy.extensions.logstats', 'scrapy.extensions.telnet', 'scrapy.core.scraper', 'scrapy.statscollectors' ] for logger_name in scrapy_loggers: logger = logging.getLogger(logger_name) logger.setLevel(logging.DEBUG)
关键注意点
- 时机优先:Scrapy启动时会自动初始化日志系统,你的配置必须早于这个流程才能生效,所以优先用
settings.py或者启动脚本开头配置。 - 避免重复输出:设置
logger.propagate = False可以防止日志同时被根日志器和子日志器处理,造成重复打印。 - 验证生效情况:可以在爬虫里加一句
logging.info("这是用户爬虫的INFO日志"),同时观察Scrapy内置组件的日志(比如引擎启动日志)是否为DEBUG级别,以此验证配置是否生效。
内容的提问来源于stack exchange,提问作者scrapy_user
相关产品推荐
相关产品推荐

