日志记录¶
注意
scrapy.log
以及其函数已被弃用,建议使用 Python 标准库中的 logging
进行显式调用。继续阅读以了解新的日志系统。
Scrapy 使用 logging
进行事件日志记录。我们将提供一些简单的示例来帮助您入门,但对于更高级的用例,强烈建议您仔细阅读其文档。
日志记录开箱即用,并且可以通过 日志设置 中列出的 Scrapy 设置进行一定程度的配置。
Scrapy 调用 scrapy.utils.log.configure_logging()
来设置一些合理的默认值并在运行命令时处理 日志设置 中的设置,因此如果从脚本中运行 Scrapy,建议您手动调用它,如 从脚本运行 Scrapy 中所述。
日志级别¶
Python 内置的 logging 定义了 5 个不同的级别来指示给定日志消息的严重程度。以下是标准级别,按严重程度降序排列:
logging.CRITICAL
- 用于严重错误(最高严重程度)logging.ERROR
- 用于常规错误logging.WARNING
- 用于警告消息logging.INFO
- 用于信息消息logging.DEBUG
- 用于调试消息(最低严重程度)
如何记录消息¶
以下是一个使用 logging.WARNING
级别记录消息的快速示例:
import logging
logging.warning("This is a warning")
有用于在任何标准 5 个级别上发出日志消息的快捷方式,还有一个通用的 logging.log
方法,它将给定级别作为参数。如果需要,最后一个示例可以改写为:
import logging
logging.log(logging.WARNING, "This is a warning")
最重要的是,您可以创建不同的“日志记录器”来封装消息。(例如,一种常见做法是为每个模块创建不同的日志记录器。)这些日志记录器可以独立配置,并且允许分层构造。
前面的示例在幕后使用了根日志记录器,它是一个顶级日志记录器,所有消息都传播到该日志记录器(除非另有指定)。使用 logging
助手仅仅是显式获取根日志记录器的快捷方式,因此这也是最后一段代码的等价物:
import logging
logger = logging.getLogger()
logger.warning("This is a warning")
您可以通过使用 logging.getLogger
函数获取其名称来使用不同的日志记录器:
import logging
logger = logging.getLogger("mycustomlogger")
logger.warning("This is a warning")
最后,您可以通过使用 __name__
变量(其中填充了当前模块的路径)来确保为正在处理的任何模块拥有一个自定义日志记录器:
import logging
logger = logging.getLogger(__name__)
logger.warning("This is a warning")
从爬虫记录日志¶
Scrapy 在每个 Spider 实例中提供了一个 logger
,可以像这样访问和使用它:
import scrapy
class MySpider(scrapy.Spider):
name = "myspider"
start_urls = ["https://scrapy.net.cn"]
def parse(self, response):
self.logger.info("Parse function called on %s", response.url)
该日志记录器是使用 Spider 的名称创建的,但您可以使用任何您想要的自定义 Python 日志记录器。例如:
import logging
import scrapy
logger = logging.getLogger("mycustomlogger")
class MySpider(scrapy.Spider):
name = "myspider"
start_urls = ["https://scrapy.net.cn"]
def parse(self, response):
logger.info("Parse function called on %s", response.url)
日志配置¶
日志记录器本身不管理如何显示通过它们发送的消息。为此,可以将不同的“处理程序”附加到任何日志记录器实例,它们会将这些消息重定向到适当的目标,例如标准输出、文件、电子邮件等。
默认情况下,Scrapy 基于以下设置设置和配置根日志记录器的处理程序。
日志设置¶
这些设置可用于配置日志记录:
前几个设置定义了日志消息的目标。如果设置了 LOG_FILE
,则通过根日志记录器发送的消息将重定向到名为 LOG_FILE
的文件,编码为 LOG_ENCODING
。如果未设置并且 LOG_ENABLED
为 True
,则日志消息将显示在标准错误上。如果设置了 LOG_FILE
并且 LOG_FILE_APPEND
为 False
,则文件将被覆盖(丢弃以前运行的输出,如果有)。最后,如果 LOG_ENABLED
为 False
,则不会有任何可见的日志输出。
LOG_LEVEL
确定要显示的最低严重程度级别,严重程度较低的消息将被过滤掉。它涵盖了 日志级别 中列出的所有可能级别。
LOG_FORMAT
和 LOG_DATEFORMAT
指定用作所有消息布局的格式字符串。这些字符串可以包含 logging 的 logrecord 属性文档 和 datetime 的 strftime 和 strptime 指令 中列出的任何占位符。
如果设置了 LOG_SHORT_NAMES
,则日志将不会显示打印日志的 Scrapy 组件。默认情况下它未设置,因此日志包含负责该日志输出的 Scrapy 组件。
命令行选项¶
有一些可用于所有命令的命令行参数,您可以使用它们来覆盖一些关于日志记录的 Scrapy 设置。
--logfile FILE
覆盖
LOG_FILE
--loglevel/-L LEVEL
覆盖
LOG_LEVEL
--nolog
将
LOG_ENABLED
设置为False
另请参阅
logging.handlers
模块关于可用处理程序的更多文档
自定义日志格式¶
可以通过扩展 LogFormatter
类并使 LOG_FORMATTER
指向您的新类来为不同的操作设置自定义日志格式。
- class scrapy.logformatter.LogFormatter[source]¶
用于为不同操作生成日志消息的类。
所有方法都必须返回一个字典,其中列出参数
level
、msg
和args
,这些参数将在调用logging.log
时用于构建日志消息。方法输出的字典键
level
是该操作的日志级别,您可以使用来自python logging 库的级别:logging.DEBUG
、logging.INFO
、logging.WARNING
、logging.ERROR
和logging.CRITICAL
。msg
应该是一个可以包含不同格式占位符的字符串。这个字符串,使用提供的args
进行格式化,将成为该操作的详细日志消息。args
应该是一个元组或字典,包含msg
的格式占位符。最终的日志消息计算为msg % args
。
如果用户想要自定义每个操作的日志记录方式或完全省略日志记录,则可以定义自己的
LogFormatter
类。为了省略某个操作的日志记录,该方法必须返回None
。以下是如何创建一个自定义日志格式化程序的示例,以便在从管道中删除项目时降低日志消息的严重性级别
class PoliteLogFormatter(logformatter.LogFormatter): def dropped(self, item, exception, response, spider): return { 'level': logging.INFO, # lowering the level from logging.WARNING 'msg': "Dropped: %(exception)s" + os.linesep + "%(item)s", 'args': { 'exception': exception, 'item': item, } }
- crawled(request: Request, response: Response, spider: Spider) LogFormatterResult [source]¶
当爬虫找到一个网页时记录一条消息。
- download_error(failure: Failure, request: Request, spider: Spider, errmsg: str | None = None) LogFormatterResult [source]¶
记录来自蜘蛛的下载错误消息(通常来自引擎)。
版本 2.0 中的新功能。
- dropped(item: Any, exception: BaseException, response: Response | None, spider: Spider) LogFormatterResult [source]¶
当项目在通过项目管道时被删除时记录一条消息。
- item_error(item: Any, exception: BaseException, response: Response | None, spider: Spider) LogFormatterResult [source]¶
当项目在通过项目管道时导致错误时记录一条消息。
版本 2.0 中的新功能。
高级自定义¶
因为 Scrapy 使用 stdlib logging 模块,所以您可以使用 stdlib logging 的所有功能来自定义日志记录。
例如,假设您正在抓取一个返回许多 HTTP 404 和 500 响应的网站,并且您想隐藏所有类似的消息
2016-12-16 22:00:06 [scrapy.spidermiddlewares.httperror] INFO: Ignoring
response <500 https://quotes.toscrape.com/page/1-34/>: HTTP status code
is not handled or not allowed
首先要注意的是日志记录器名称 - 它在方括号中:[scrapy.spidermiddlewares.httperror]
。如果您只得到[scrapy]
,则LOG_SHORT_NAMES
可能设置为 True;将其设置为 False 并重新运行爬取。
接下来,我们可以看到消息的级别是 INFO。要隐藏它,我们应该将scrapy.spidermiddlewares.httperror
的日志级别设置为高于 INFO;INFO 之后的下一个级别是 WARNING。这可以通过例如在 spider 的__init__
方法中完成。
import logging
import scrapy
class MySpider(scrapy.Spider):
# ...
def __init__(self, *args, **kwargs):
logger = logging.getLogger("scrapy.spidermiddlewares.httperror")
logger.setLevel(logging.WARNING)
super().__init__(*args, **kwargs)
如果你再次运行这个 spider,那么来自scrapy.spidermiddlewares.httperror
logger 的 INFO 消息就会消失了。
你也可以通过LogRecord
数据过滤日志记录。例如,你可以使用子字符串或正则表达式根据消息内容过滤日志记录。创建一个logging.Filter
子类,并为其配备一个正则表达式模式来过滤掉不需要的消息。
import logging
import re
class ContentFilter(logging.Filter):
def filter(self, record):
match = re.search(r"\d{3} [Ee]rror, retrying", record.message)
if match:
return False
项目级别的过滤器可以附加到 Scrapy 创建的根处理程序上,这是一种方便的方式来过滤项目不同部分(中间件、spider 等)中的所有 logger。
import logging
import scrapy
class MySpider(scrapy.Spider):
# ...
def __init__(self, *args, **kwargs):
for handler in logging.root.handlers:
handler.addFilter(ContentFilter())
或者,您可以选择一个特定的 logger 并隐藏它,而不会影响其他 logger。
import logging
import scrapy
class MySpider(scrapy.Spider):
# ...
def __init__(self, *args, **kwargs):
logger = logging.getLogger("my_logger")
logger.addFilter(ContentFilter())
scrapy.utils.log 模块¶
- scrapy.utils.log.configure_logging(settings: Settings | dict[Union[bool, float, int, str, NoneType], Any] | None = None, install_root_handler: bool = True) None [source]¶
初始化 Scrapy 的日志默认值。
- 参数:
此函数执行以下操作:
通过 Python 标准日志记录路由警告和 Twisted 日志记录
分别为 Scrapy 和 Twisted logger 分配 DEBUG 和 ERROR 级别
如果 LOG_STDOUT 设置为 True,则将标准输出路由到日志
当
install_root_handler
为 True(默认值)时,此函数还会根据给定的设置创建根 logger 的处理程序(请参阅日志记录设置)。您可以使用settings
参数覆盖默认选项。当settings
为空或为 None 时,将使用默认值。configure_logging
在使用 Scrapy 命令或CrawlerProcess
时会自动调用,但在使用CrawlerRunner
运行自定义脚本时需要显式调用。在这种情况下,不需要使用它,但建议使用。运行自定义脚本时的另一个选项是手动配置日志记录。为此,您可以使用
logging.basicConfig()
设置一个基本的根处理程序。请注意,
CrawlerProcess
会自动调用configure_logging
,因此建议仅将logging.basicConfig()
与CrawlerRunner
一起使用。这是一个关于如何将
INFO
或更高级别的消息重定向到文件的示例。import logging logging.basicConfig( filename="log.txt", format="%(levelname)s: %(message)s", level=logging.INFO )
有关以这种方式使用 Scrapy 的更多详细信息,请参阅从脚本运行 Scrapy。