Python爬虫基础教程(10)Python标准库之logging模块:告别print!Python爬虫的‘后悔药’:logging模块,让你的bug无处遁形!

你的爬虫,需要一个“黑匣子”

想象一下这个场景:你精心编写的爬虫脚本,在本地跑得风生水起,感觉分分钟就能把整个互联网的数据都搬回家。于是你自信满满地把它扔到服务器上,设置好定时任务,安心睡觉。第二天一早,你满怀期待地打开电脑,却发现——数据量为零,脚本不知道在哪个深夜已经悄然崩溃,没留下任何线索。

此时的你,是不是很想穿越回过去,给那个只用 print(“跑到第XX页了…”) 的自己一个大嘴巴子?

“print流派”的三大致命伤:

  1. 信息转瞬即逝:控制台输出关掉就没了,服务器上你上哪儿看去?
  2. 泥沙俱下,真假难辨:有用的错误信息和没用的调试信息混在一起,找bug如同大海捞针。
  3. 性能与灵活性双输:上线后你得一处处去删print语句,万一漏了几个,还会影响程序性能。

而Python标准库里的 logging 模块,就是来解决这些痛点的。它就像飞机上的“黑匣子”,无论程序是平稳飞行还是意外坠毁,它都能忠实地记录下一切关键信息,让你事后可以精准复盘。

第一幕:开箱即用,5分钟上手logging

别怕,logging没那么复杂。咱们先来看看最简单、最“傻瓜式”的用法。

import logging

# 最最最基础的用法
logging.warning(“这是一条警告信息!”)
logging.error(“这是一条错误信息!”)

# 试着运行一下,你会看到:
# WARNING:root:这是一条警告信息!
# ERROR:root:这是一条错误信息!

发现了没?我们没有做任何配置,它就直接工作了。但为什么 logging.info(“这是一条普通信息”) 没有输出呢?

这就引出了logging的核心概念——日志级别

第二幕:理解日志的“音量旋钮”:级别(Level)

logging模块设定了5个标准级别,按严重性从低到高排列:

  • DEBUG:最唠叨的模式,记录一切细节,用于开发阶段调试。
  • INFO:正常运行时需要记录的信息,比如“成功连接到数据库”。
  • WARNING:表示一些不期望的事情发生了,但程序还在正常运行,比如“磁盘空间不足”。
  • ERROR:由于一个更严重的问题,某些功能已经没法正常使用了。
  • CRITICAL:最高级别,程序可能要挂了!

默认的“音量旋钮”拧在了 WARNING 位置。 所以,比WARNING级别“轻”的DEBUG和INFO信息,默认就被静音了。

你可以通过一行代码来调整这个“旋钮”:

import logging
logging.basicConfig(level=logging.DEBUG) # 把旋钮拧到最低,让所有信息都“响”起来

logging.debug(“这是最琐碎的调试信息”)
logging.info(“这是一条普通信息”)
logging.warning(“警告!”)

现在,所有级别的信息都会打印出来了。是不是感觉控制力强多了?

第三幕:打造你的专属日志:格式化和输出

默认的输出 WARNING:root:消息 有点丑,而且信息量不够(比如没有时间)。这时候,就该 basicConfig 方法大显身手了。

import logging

logging.basicConfig(
    level=logging.INFO,
    format=‘%(asctime)s - %(name)s - %(levelname)s - %(message)s’,
    datefmt=‘%Y-%m-%d %H:%M:%S’,
    filename=‘my_spider.log’, # 日志输出到文件,而不是控制台
    filemode=‘a’ # ‘a’是追加模式,‘w’是覆盖模式
)

logging.info(“程序启动啦!”)
# 此时控制台没东西了,但当前目录下会生成一个 my_spider.log 文件
# 里面的内容大概是:2023-10-27 14:35:01 - root - INFO - 程序启动啦!

参数解释:

  • format:这就是你的日志“美颜滤镜”。
    • % (asctime)s:人类可读的时间。
    • % (name)s:logger的名字(后面高级篇会讲,默认是‘root’)。
    • % (levelname)s:日志级别。
    • % (message)s:你输出的消息。
  • filename:指定日志文件路径,有了它,日志就不再是“一次性”的了。
  • filemode:和打开文件的模式一样,w 会覆盖,a 会追加。

到这一步,你已经能解决80%的日志需求了!但作为一个有追求的爬虫工程师,我们还得往深里探一探。

第四幕:高手进阶:Logger,Handler,Filter,Formatter

这才是logging模块的完全体!它采用了“组装式”设计,就像乐高。

  • Logger(记录器):就是你代码里打日志的那个接口。你可以创建多个logger,比如一个叫 ‘spider’ 专门记录爬虫逻辑,一个叫 ‘parser’ 专门记录解析逻辑。
  • Handler(处理器):决定日志该去哪里。是控制台(StreamHandler)?还是文件(FileHandler)?或者是通过网络发出去?你可以给一个logger添加多个handler。
  • Filter(过滤器):提供更精细的规则来决定哪些日志能通过。
  • Formatter(格式化器):和上面 basicConfig 里的format一样,决定日志的最终输出样式。

为什么要这么复杂? 灵活性!比如,你可以让 spider logger 的 DEBUG 级别信息写入文件(便于深度调试),同时只让 ERROR 级别信息发送邮件到你的邮箱(便于报警)。

下面我们来看一个完整示例。

终幕:实战!给爬虫装上“黑匣子”

我们来写一个简单的爬虫,并给它配上工业级的日志系统。

import logging
import requests
from bs4 import BeautifulSoup
import time

# 1. 创建一个专属的logger
logger = logging.getLogger(‘my_awesome_spider’)
logger.setLevel(logging.DEBUG) # logger本身捕获的最低级别

# 2. 创建Handler(我们创建两个:一个给文件,一个给控制台)
# 文件Handler,记录所有DEBUG及以上级别的日志
file_handler = logging.FileHandler(‘spider.log’, mode=‘a’, encoding=‘utf-8’)
file_handler.setLevel(logging.DEBUG)

# 控制台Handler,只记录INFO及以上级别的日志
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)

# 3. 创建Formatter,定义日志格式
formatter = logging.Formatter(
    ‘%(asctime)s - %(name)s - [%(levelname)s] - %(message)s’
)
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)

# 4. 将Handler添加到logger
logger.addHandler(file_handler)
logger.addHandler(console_handler)

def crawl_page(url):
    “”“爬取单个页面的函数”“”
    logger.info(f“开始爬取: {url}”)
    try:
        response = requests.get(url, timeout=5)
        response.raise_for_status() # 如果状态码不是200,会抛出HTTPError异常

        # 假装这里有一些复杂的解析逻辑
        soup = BeautifulSoup(response.text, ‘html.parser’)
        title = soup.title.string if soup.title else ‘No Title’
        logger.debug(f"页面标题获取成功: {title}") # 这种细节信息用DEBUG

        logger.info(f“爬取成功: {url}”)
        return response.text

    except requests.exceptions.RequestException as e:
        # 这里是爬虫最可能出错的地方!
        logger.error(f“爬取失败 {url},错误: {e}”, exc_info=True) # exc_info=True会打印完整的异常栈
        return None

def main():
    logger.info(“= = = 爬虫程序启动 = = =”)
    urls = [
        ‘https://httpbin.org/json’,
        ‘https://httpbin.org/status/404’, # 一个会返回404的URL
        ‘https://这是一个无效的网址.com/’,
    ]

    for i, url in enumerate(urls, 1):
        logger.info(f”正在处理第 {i} 个URL,共 {len(urls)} 个”)
        result = crawl_page(url)
        time.sleep(1) # 礼貌一点

    logger.info(“= = = 爬虫程序结束 = = =”)

if __name__ == ‘__main__’:
    main()

运行这个脚本,你会看到:

  • 控制台:清晰地显示着INFO及以上的关键流程信息。
  • spider.log 文件:记录了包括DEBUG信息在内的所有细节,特别是那个404错误和无效网址的 完整错误堆栈

现在,让我们模拟一下“后悔药”的场景:
假如你的爬虫在深夜因为一个连接超时异常崩溃了。第二天,你不再需要去猜测发生了什么。只需打开 spider.log,搜索 “ERROR”,你就能立刻看到:

2023-10-27 14:40:23 - my_awesome_spider - [ERROR] - 爬取失败 https://这是一个无效的网址.com/,错误: ... (后面是详细的异常信息)

问题瞬间定位!这就是logging的力量。

总结

老铁,看到这里,你已经成功从“print游击队”毕业,加入了“logging正规军”。记住,一个成熟的程序员,不是在写日志,就是在去写日志的路上。

总结一下核心心法:

  1. 告别print:从项目一开始就使用logging。
  2. 善用级别:用DEBUG调试,用INFO记录流程,用WARNING和ERROR记录问题。
  3. 输出到文件:这是日志发挥作用的前提。
  4. 信息明确:日志信息要能让人看懂,必要时带上上下文(比如URL、ID等)。
  5. 面向“甩锅”编程:清晰详细的日志,在排查与第三方API交互的问题时,是你最强的“甩锅”(哦不,是举证)利器。

现在,就打开你的爬虫项目,把里面乱七八糟的print语句,换成优雅强大的logging吧!让你的代码从此拥有一个可靠的“黑匣子”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值