You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django开发中如何捕获调用YouTube API时触发的各类异常

异常捕获失效的核心原因

你当前的捕获逻辑抓不到报错,基本逃不出这几个情况:

  • 捕获范围太窄:只拦截了某一类特定异常(比如仅捕获了requests库的网络错误),但Google官方YouTube API客户端抛出的自定义异常、数据解析异常、参数校验异常都没覆盖
  • 作用域不对:如果「Error 1」位置的代码跑在Celery异步任务、子线程里,写在主线程/调用方外层的try-except根本无法捕获子执行流抛出的异常
  • 异常类未正确导入:google-api-python-client抛出的HTTP错误属于googleapiclient.errors下的自定义类型,没提前导入的话无法精准捕获
  • 漏处理跨模块异常:比如网络超时触发的TimeoutError、API配额耗尽返回的403、参数非法返回的400、私有视频触发的404等异常散落在不同模块,窄范围捕获必然漏判
可直接落地的实现方案

第一步:先枚举全量异常类型

先临时加全量捕获,跑一遍所有会触发报错的场景,把所有出现的异常类型摸清楚,避免漏判:

import traceback
try:
    # 这里放「Error 1」位置对应的完整业务代码:初始化API客户端、构造请求、拉取视频、解析响应的全流程
    pass
except BaseException as e:
    # 以下为临时调试代码,上线前删除
    print(f"异常类型:{type(e).__name__},异常详情:{str(e)}")
    print(traceback.format_exc())
    raise

注意:BaseException仅用于临时调试抓全量异常,正式代码禁止直接用它做兜底拦截,否则会把键盘中断、进程退出这类系统级异常拦住,导致服务假死。

第二步:分层精准捕获异常,返回自定义提示

先导入所有需要用到的异常类:

# 网络请求类异常
from requests.exceptions import RequestException, Timeout, ConnectionError
# Google YouTube API 官方客户端抛出的异常
from googleapiclient.errors import HttpError
# 数据解析、校验类异常
from json import JSONDecodeError
from django.core.exceptions import ValidationError

替换原「Error 1」位置的异常处理逻辑,按异常粒度分别返回对应提示:

def crawl_youtube_videos(preset_filter):
    try:
        # 初始化YouTube客户端、构造请求参数、发起API调用的核心逻辑
        youtube = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY)
        api_resp = youtube.search().list(
            part="id,snippet",
            maxResults=preset_filter["max_count"],
            q=preset_filter["keyword"],
            relevanceLanguage=preset_filter.get("lang", "zh"),
            # 其余你预设的筛选参数
        ).execute()
        # 解析响应、入库、返回结果的逻辑
        return format_video_data(api_resp)

    except HttpError as e:
        # 处理YouTube API返回的官方HTTP错误
        err_content = e.content.decode("utf-8")
        if e.resp.status == 403:
            if "quotaExceeded" in err_content:
                tip = "YouTube API当日调用配额已耗尽,请24小时后再试"
            elif "accessNotConfigured" in err_content:
                tip = "YouTube API权限未开启,请检查后端接口配置"
            else:
                tip = "当前请求无权限访问YouTube资源"
        elif e.resp.status == 400:
            tip = "预设筛选参数不合法,请检查规则配置"
        elif e.resp.status == 404:
            tip = "查询的频道/视频资源不存在或已被删除"
        else:
            tip = f"YouTube接口请求失败,错误码:{e.resp.status}"
        print(f"Error 1: API请求错误 - {err_content}")
        # Django视图直接返回统一结构给Vue前端
        return JsonResponse({"code": 5001, "msg": tip})

    except Timeout:
        print("Error 1: 请求YouTube API超时")
        return JsonResponse({"code": 5002, "msg": "连接YouTube服务超时,请检查网络后重试"})

    except ConnectionError:
        print("Error 1: 无法连接YouTube服务")
        return JsonResponse({"code": 5003, "msg": "无法连接YouTube服务,请检查服务器网络配置"})

    except (JSONDecodeError, ValidationError, KeyError, TypeError) as e:
        print(f"Error 1: 数据处理失败 - {str(e)}")
        return JsonResponse({"code": 5004, "msg": "视频数据解析异常,请稍后重试"})

    except RequestException as e:
        print(f"Error 1: 网络请求异常 - {str(e)}")
        return JsonResponse({"code": 5005, "msg": "网络请求异常,请稍后重试"})

    except Exception as e:
        # 最后兜底所有未预判的业务异常
        print(f"Error 1: 未预期异常 - {str(e)}\n{traceback.format_exc()}")
        # 生产环境不要返回原始异常信息,避免泄露敏感配置
        return JsonResponse({"code": 5000, "msg": "服务出现未知错误,请联系管理员"})

第三步:补全特殊场景处理

  • 如果爬取逻辑跑在Celery异步任务、子线程中,上述try-except必须写在任务执行函数/子线程入口函数的最外层,写在调用任务的外层代码中无法捕获异常
  • 前后端交互要统一响应结构,不要让Django抛出默认的500错误页,Vue端直接读取响应中的msg字段展示给用户即可
  • 日志打印不要只输出「Error 1」,要带上异常栈、触发的筛选规则ID、请求参数,方便后续补全漏处理的异常类型
避坑提醒
  • 不要写裸except:做拦截,会拦截所有系统级异常,引发不可预期的服务问题
  • 不要把原始异常栈、API密钥这类敏感信息随接口返回给前端,详细错误仅存在服务端日志即可
  • 如果你用的是第三方封装的YouTube爬取库,提前查阅对应文档确认其抛出的异常类型,补充到捕获列表中

内容的提问来源于stack exchange,提问作者Revathi Narayankutty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 20:12:17