每次我试图从PYTUBE下载官方视频时,它都会显示这个错误

2024-07-04 16:39:34 发布

您现在位置:Python中文网/ 问答频道 /正文

这是我每次尝试下载任何官方视频时都会遇到的错误,但使用某些在线下载应用程序时会下载相同的视频

  KeyError    Traceback (most recent call last)
~\anaconda3\lib\site-packages\pytube\extract.py in apply_descrambler(stream_data, key)
--> 297                 for format_item in formats
~\anaconda3\lib\site-packages\pytube\extract.py in <listcomp>(.0)
    296                 }
--> 297                 for format_item in formats
    298             ]
KeyError: 'url'

During handling of the above exception, another exception occurred:

KeyError      Traceback (most recent call last)
<ipython-input-1-796467b30bec> in <module>
      7 import cv2
      8 
----> 9 video = YouTube('https://www.youtube.com/watch?v=tDq3fNew1rU')
~\anaconda3\lib\site-packages\pytube\__main__.py in __init__(self, url, defer_prefetch_init, on_progress_callback, on_complete_callback, proxies)
     90         if not defer_prefetch_init:
     91             self.prefetch()
---> 92             self.descramble()
     94     def descramble(self) -> None:
~\anaconda3\lib\site-packages\pytube\__main__.py in descramble(self)
    130             if not self.age_restricted and fmt in self.vid_info:
    131                 apply_descrambler(self.vid_info, fmt)
--> 132             apply_descrambler(self.player_config_args, fmt)
    134             if not self.js:

~\anaconda3\lib\site-packages\pytube\extract.py in apply_descrambler(stream_data, key)
    299         except KeyError:
    300             cipher_url = [
--> 301                 parse_qs(formats[i]["cipher"]) for i, data in enumerate(formats)
    302             ]
    303             stream_data[key] = [
~\anaconda3\lib\site-packages\pytube\extract.py in <listcomp>(.0)
    299         except KeyError:
    300             cipher_url = [
--> 301                 parse_qs(formats[i]["cipher"]) for i, data in enumerate(formats)
    302             ]
    303             stream_data[key] = [

KeyError: 'cipher'

有人能帮我解决这个错误吗


Tags: inpyselfdatalibpackagessiteextract
2条回答
#TODO: Actually due to some sudden changes on youtube some changes have to made on this API too..
# ? just use this line before starting any pytube script:
# ! pytube.__main__.apply_descrambler = __pre__.apply_descrambler

# The below imports are required by the patch
import json
from urllib.parse import parse_qs, unquote

# This function is based off on the changes made in
# https://github.com/nficano/pytube/pull/643

    def apply_descrambler(stream_data, key):
        """Apply various in-place transforms to YouTube's media stream data.
        Creates a ``list`` of dictionaries by string splitting on commas, then
        taking each list item, parsing it as a query string, converting it to a
        ``dict`` and unquoting the value.
        :param dict stream_data:
            Dictionary containing query string encoded values.
        :param str key:
            Name of the key in dictionary.
        **Example**:
        >>> d = {'foo': 'bar=1&var=test,em=5&t=url%20encoded'}
        >>> apply_descrambler(d, 'foo')
        >>> print(d)
        {'foo': [{'bar': '1', 'var': 'test'}, {'em': '5', 't': 'url encoded'}]}
        """
        otf_type = "FORMAT_STREAM_TYPE_OTF"
    
        if key == "url_encoded_fmt_stream_map" and not stream_data.get(
            "url_encoded_fmt_stream_map"
        ):
            formats = json.loads(stream_data["player_response"])["streamingData"]["formats"]
            formats.extend(
                json.loads(stream_data["player_response"])["streamingData"][
                    "adaptiveFormats"
                ]
            )
            try:
                stream_data[key] = [
                    {
                        "url": format_item["url"],
                        "type": format_item["mimeType"],
                        "quality": format_item["quality"],
                        "itag": format_item["itag"],
                        "bitrate": format_item.get("bitrate"),
                        "is_otf": (format_item.get("type") == otf_type),
                    }
                    for format_item in formats
                ]
            except KeyError:
                cipher_url = []
                for data in formats:
                    cipher = data.get("cipher") or data["signatureCipher"]
                    cipher_url.append(parse_qs(cipher))
                stream_data[key] = [
                    {
                        "url": cipher_url[i]["url"][0],
                        "s": cipher_url[i]["s"][0],
                        "type": format_item["mimeType"],
                        "quality": format_item["quality"],
                        "itag": format_item["itag"],
                        "bitrate": format_item.get("bitrate"),
                        "is_otf": (format_item.get("type") == otf_type),
                    }
                    for i, format_item in enumerate(formats)
                ]
        else:
            stream_data[key] = [
                {k: unquote(v) for k, v in parse_qsl(i)}
                for i in stream_data[key].split(",")
            ]

这个文件是在一个问题中发布的(在PytubeGithub中),每次在主文件上导入它,然后pytube.__main__.apply_descrambler = __pre__.apply_descrambler 在你的文件上使用那一行

这会检测密码或密码签名,并进行一些必要的操作。。变化

我也有同样的问题。我通过以下方式解决了这个问题:

  1. 转到site-packages/pytub/extract.py安装pytube的地方
  2. 查找行:parse_qs(formats[i]["cipher"]) for i, data in enumerate(formats)
  3. ["cipher"]替换为["signatureCipher"]
  4. 完成了

资料来源here

相关问题 更多 >

    热门问题