Python爬虫异常处理:保证程序稳定

2026-08-15 00:00:50 1703阅读 0评论

Python爬虫异常处理:让程序告别“一言不合就崩溃”

半夜挂着爬虫脚本去睡觉,满心以为早上能收获满满的数据,结果打开电脑一看,程序早在凌晨两点就因为一个小小的报错罢工了。这种“惊喜”想必每个写过爬虫的人都体会过。写爬虫不难,难的是让它像老黄牛一样稳定地跑完整个周期。今天我们就来聊聊,如何通过异常处理给Python爬虫穿上“防弹衣”。

网络请求阶段的“断网”危机

爬虫的第一步是发请求,这也是最容易翻车的地方。目标网站服务器打个盹,或者你的网络稍微抖一下,ConnectionErrorTimeout 就会直接让程序崩溃。

面对这种偶发的网络波动,死磕一次是不明智的。最实用的思路是引入重试机制。你可以手写一个带重试逻辑的装饰器,或者直接拥抱 tenacity 这个库。

from tenacity import retry, stop_after_attempt, wait_fixed

@retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
def fetch_data(url):
    response = requests.get(url, timeout=10)
    response.raise_for_status()
    return response.text

这里有个细节需要特别注意:一定要设置 timeout 参数。如果不设置,遇到服务器不响应也不拒绝的情况,你的程序会永远卡死在这个请求上,连重试的机会都没有。

解析阶段的“缺斤少两”

好不容易拿到了网页源码,到了用 BeautifulSoup 或 XPath 提取数据的环节,又容易栽跟头。有时候目标网站悄悄改了HTML结构,或者某个商品刚好缺货导致页面少了一块DOM节点,直接提取就会抛出 AttributeErrorIndexError

处理这类异常的核心原则是优雅降级与数据兜底。不要一报错就终止整个任务,而是捕获异常并赋予默认值。

try:
    price = soup.select_one('.price').text
except AttributeError:
    price = '未知'
    logging.warning(f"未找到价格节点,URL: {url}")

通过记录日志并赋默认值,既能保证程序继续运行,又能在事后排查时知道哪些数据是缺失的,不至于拿到一堆残缺不全的脏数据。

反爬机制下的“状态码”陷阱

当你请求频率稍微快了一点,或者IP被目标网站盯上,返回的往往不是200,而是 403(禁止访问)、429(请求过多)甚至 503。很多新手习惯用 raise_for_status() 一刀切,遇到非200状态码直接报错。

针对反爬状态码,我们需要分层处理。遇到 429 时,说明被限流了,这时候最聪明的做法是主动休眠,而不是盲目重试;遇到 403 或 503,可能是触发了风控,需要切换代理IP或更新请求头

if response.status_code == 429:
    time.sleep(random.uniform(10, 20))  # 遇到限流,随机休眠
elif response.status_code in [403, 503]:
    proxy = get_new_proxy()  # 切换代理

把状态码判断放在 raise_for_status() 之前,能让你的爬虫在面对反爬时游刃有余,而不是像个无头苍蝇一样乱撞。

数据入库时的“最后一公里”

数据辛辛苦苦抓下来了,存进数据库时也可能出岔子。比如数据库连接断开,或者遇到了重复数据导致 DuplicateKeyError

对于数据库连接异常,同样可以复用前面的重试机制。而对于数据重复问题,建议在SQL语句中使用 INSERT IGNOREON DUPLICATE KEY UPDATE,或者在MongoDB中使用 update_one 配合 upsert=True。在代码层面,捕获特定的数据库异常并打印警告,比直接让程序崩溃要体面得多,也能避免因为一条脏数据毁掉整批入库进度。

结语

写爬虫就像是在充满未知的水域里航行,异常处理就是你船底的压舱石。与其在程序崩溃后对着满屏的红字报错抓狂,不如在编写代码时就预判好各种可能出错的场景。把重试、兜底、日志记录这些防御性编程的习惯融入日常,你的爬虫程序才能真正实现“无人值守”,稳稳当当地把数据搬回你的硬盘里。

文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
验证码
评论列表 (暂无评论,1703人围观)

还没有评论,来说两句吧...

目录[+]