pytube异常处理无法捕获直播流错误 抛出KeyError'streamingData'
问题根因
- 你使用的pytube 10.8.1版本存在已知缺陷:直播流的状态校验逻辑没有放在
YouTube()对象初始化阶段执行,会延迟到你首次访问yt.streams属性时才去解析视频流数据。同时该版本没有对返回数据中的streamingData字段做存在性校验,直播流本身不会返回这个字段,代码直接取值就会抛出Python原生KeyError,而KeyError不属于你捕获的pytube.exceptions下的自定义异常类,所以你写的几个异常捕获分支全部不生效。 - 你的异常捕获顺序存在错误:父类异常
PytubeError的捕获分支放在了LiveStreamError、VideoPrivate等子类异常的前面,就算触发了子类异常,也会优先被父类分支拦截,你写的细分异常提示逻辑永远不会执行。
修复方案
方案1(推荐):升级pytube到最新稳定版
最新版pytube已经修复了该缺陷:在YouTube()初始化阶段就会完成直播状态、私有状态、可用性校验,对应异常会正常抛出,同时补全了字段校验逻辑,不会直接抛出原生KeyError。升级命令:
pip install --upgrade pytube
方案2:如果必须保留10.8.1版本,修改代码逻辑
- 调整异常捕获顺序,所有子类异常放在父类
PytubeError之前 - 在
yt.streams相关的try块中补充KeyError的捕获分支,兼容版本缺陷 - 也可以提前判断
yt.is_live属性,提前过滤直播流,避免走到抛异常的逻辑
修改后的代码示例:
import pytube from pytube import YouTube mp4URL = "https://www.youtube.com/watch?v=21X5lGlDOfg" try: yt = YouTube(mp4URL) # 提前校验直播状态 if yt.is_live: print(f'Video {mp4URL} ist ein LiveStream, skipping. ') exit() # 细分异常放前面,父类异常放后面 except pytube.exceptions.LiveStreamError as e: print(f'Video {mp4URL} ist ein LiveStream, skipping. ',e) except pytube.exceptions.VideoPrivate as e: print(f'Video {mp4URL} ist ein privates Video, skipping. ',e) except pytube.exceptions.VideoUnavailable as e: print(f'Video {mp4URL} ist nicht verfügbar, skipping. ',e) except pytube.exceptions.HTMLParseError as e: print(e) except pytube.exceptions.PytubeError as e: print(e) else: print(f'Downloading video: {mp4URL}') try: stream = yt.streams.filter(mime_type='video/mp4',progressive=True,file_extension='mp4').order_by('resolution').desc().first() except KeyError: print(f'Video {mp4URL} 无可用流数据,大概率为直播流,skipping. ') # 同样调整异常顺序 except pytube.exceptions.LiveStreamError as e: print(f'Video {mp4URL} ist ein LiveStream, skipping. ',e) except pytube.exceptions.VideoPrivate as e: print(f'Video {mp4URL} ist ein privates Video, skipping. ',e) except pytube.exceptions.VideoUnavailable as e: print(f'Video {mp4URL} ist nicht verfügbar, skipping. ',e) except pytube.exceptions.HTMLParseError as e: print(e) except pytube.exceptions.PytubeError as e: print(e) else: if stream: stream.download() else: print(f'Video {mp4URL} 无符合条件的mp4流')
内容的提问来源于stack exchange,提问作者Martin Hormann
相关产品推荐
相关产品推荐

