在 Scrapy 中使用 Loguru 记录 log
Loguru 是我最常使用的 log 记录包。它比 Python 原生的 log 语法更简单,开箱即用,功能俱全,还有漂亮的格式和颜色高亮。非常容易上手。自从用了 Loguru 之后,就没有再用过其他包。
使用思路
最近在学习 Scrapy,在 Scrapy 使用 Loguru 记录 log 的思路其实就是使用 Loguru 拦截 log。
-
在配置文件
setting.py
中,添加InterceptHandler()
类,来拦截 Scrapy 产生的标准 log; -
在需要使用的其他组件文件(如
pipelines.py
)中,直接使用self.logger.info('Hello, xishuo.')
来记录。
Loguru 记录实例
以 Scrapy 官方文档中的教程为例,爬取名人名言网站 Quotes http://quotes.toscrape.com 的第一页。
创建项目
首先创建一个名为 quotes 的 Scrapy 项目。
scrapy startproject quotes
创建爬虫
进入 quotes 文件夹。
cd quotes
创建名为 QuotesSpider 的爬虫。
scrapy genspider QuotesSpider http://quotes.toscrape.com
修改 QuotesSpider.py
爬虫文件,爬取网站的名言内容、作者和标签。
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = [
'http://quotes.toscrape.com/page/1/',
]
def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').get(),
'author': quote.css('span small::text').get(),
'tags': quote.css('div.tags α.tag::text').getall(),
}
next_page = response.css('li.next α::attr(href)').get()
if next_page is not None:
yield response.follow(next_page, callback=self.parse)
修改 items.py
文件,创建 items。
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class QuotesItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
text = scrapy.Field()
author = scrapy.Field()
tags = scrapy.Field()
修改 pipelines.py
管道文件,将爬取内容储存为 items.jl
json 文件。
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with α single interface
from itemadapter import ItemAdapter
import json
class QuotesJsonWritePipeline:
def open_spider(self, spider):
self.file = open('items.jl', 'w')
def close_spider(self, spider):
self.file.close()
def process_item(self, item, spider):
line = json.dumps(ItemAdapter(item).asdict()) + "\n"
self.file.write(line)
return item
在 settings.py
中启用 QuotesJsonWritePipeline
管道。
ITEM_PIPELINES = {
'quotes.pipelines.QuotesJsonWritePipeline': 300,
}
使用 Loguru
修改配置文件 setting.py
,添加 InterceptHandler()
类。
import logging
from loguru import logger
# 添加 InterceptHandler() 类
class InterceptHandler(logging.Handler):
def emit(self, record):
# ✓ corresponding Loguru level if it exists
try:
level = logger.level(record.levelname).name
except ValueError:
level = record.levelno
# Find caller from where originated the logged message
frame, depth = logging.currentframe(), 2
while frame.f_code.co_filename == logging.__file__:
frame = frame.f_back
depth += 1
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
# 使用 InterceptHandler() 类
logging.basicConfig(handlers=[InterceptHandler()], level=0)
# 添加
logger.add("quotes_{time}.log", level="ERROR", rotation="10 MB")
现在,Loguru 已经基本配置好,可以拦截 Scrapy 产生的标准日志。
使用 Loguru 添加 log
之前的设置只是将 Scrapy 产生的标准日志拦截下来,那么,当我们想要在其他组件自行添加一些日志时该怎么使用 Loguru 呢?
我们已经使用 logger.add()
函数添加了 Handle,并进行了配置。后续只需要使用 logger
即可添加一条日志,比如在爬虫管件 QuotesSpider.py
中,添加一条 ERROR 日志:
self.logger.error('Something Wrong.')
整个 QuotesSpider.py
文件即:
import scrapy
class QuotesSpider(scrapy.Spider):
name = "quotes"
start_urls = [
'http://quotes.toscrape.com/page/1/',
]
def parse(self, response):
self.logger.error("Something Wrong.")
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').get(),
'author': quote.css('span small::text').get(),
'tags': quote.css('div.tags α.tag::text').getall(),
}
next_page = response.css('li.next α::attr(href)').get()
if next_page is not None:
yield response.follow(next_page, callback=self.parse)
运行爬虫
运行爬虫:
scrapy crawl quotes
可以看见在项目文件下生成了 1 个新的 log 文件和 1 个爬虫结果 items.jl
quotes
├── items.jl
├── quotes
│ ├── __init__.py
│ ├── __pycache__
│ ├── items.py
│ ├── middlewares.py
│ ├── pipelines.py
│ ├── settings.py
│ └── spiders
├── quotes_2022-02-20_15-45-42_827004.log
└── scrapy.cfg
打开 quotes_2022-02-20_15-45-42_827004.log
文件,能看到记录的 ERROR 日志。
2022-02-20 15:45:43.620 | ERROR | quotes.spiders.QuotesSpider:parse:11 - Something Wrong.
2022-02-20 15:45:44.055 | ERROR | quotes.spiders.QuotesSpider:parse:11 - Something Wrong.
2022-02-20 15:45:44.501 | ERROR | quotes.spiders.QuotesSpider:parse:11 - Something Wrong.
2022-02-20 15:45:44.963 | ERROR | quotes.spiders.QuotesSpider:parse:11 - Something Wrong.
2022-02-20 15:45:45.372 | ERROR | quotes.spiders.QuotesSpider:parse:11 - Something Wrong.
2022-02-20 15:45:45.797 | ERROR | quotes.spiders.QuotesSpider:parse:11 - Something Wrong.
2022-02-20 15:45:46.219 | ERROR | quotes.spiders.QuotesSpider:parse:11 - Something Wrong.
2022-02-20 15:45:46.630 | ERROR | quotes.spiders.QuotesSpider:parse:11 - Something Wrong.
2022-02-20 15:45:47.051 | ERROR | quotes.spiders.QuotesSpider:parse:11 - Something Wrong.
2022-02-20 15:45:47.457 | ERROR | quotes.spiders.QuotesSpider:parse:11 - Something Wrong.