5
votes

Pytube ne fonctionne que périodiquement (KeyError: 'assets')

Cinq fois sur dix, Pytube m'enverra cette erreur en essayant d'exécuter mon petit script de test.

Voici le script:

Traceback (most recent call last):
  File "youtube.py", line 6, in <module>
    yt = YouTube('https://www.youtube.com/watch?v=3NCyD3XoJgM')
  File "C:\Users\test\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\pytube\__main__.py", line 91, in __init__
    self.prefetch()
  File "C:\Users\test\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\pytube\__main__.py", line 183, in prefetch
    self.js_url = extract.js_url(self.watch_html)
  File "C:\Users\test\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\pytube\extract.py", line 143, in js_url
    base_js = get_ytplayer_config(html)["assets"]["js"]
KeyError: 'assets'

Voici ce que j'obtiens:

import pytube
import urllib.request


from pytube import YouTube
yt = YouTube('https://www.youtube.com/watch?v=3NCyD3XoJgM')

print('Youtube video title is: ' + yt.title + '! Downloading now!')

Je suis très confus. J'ai tenté de réinstaller Python plus pytube mais je n'arrive pas à résoudre ce problème. Il est de plus en plus déroutant que le script fonctionne la moitié du temps, mais pas l'autre moitié.


0 commentaires

10 Réponses :


-1
votes

Essayez de remplacer la ligne 143

    try:
        base_js = get_ytplayer_config(html)["assets"]["js"]
    except Exception:
        pass

avec

    base_js = get_ytplayer_config(html)["assets"]["js"]


1 commentaires

Comment initialisez-vous la variable base_js?



5
votes

J'ai le même problème, mais je vous garantis que la première réponse ne résout rien, cachez simplement le problème jusqu'à ce qu'il réapparaisse. J'ai étudié cette portée du fichier "extract.py" et j'ai trouvé une erreur. Cette étendue recherche un extrait de "chaîne" dans le code source de la page Youtube où se trouve la vidéo, via une recherche dans le dictionnaire, par exemple:

def js_url(html: str) -> str:
"""Get the base JavaScript url.

Construct the base JavaScript url, which contains 
the decipher
"transforms".

:param str html:
    The html contents of the watch page.
"""
base_js = html[html.find('js') + 4:html.find('.js') 
+ 4]
return "https://youtube.com" + base_js

L'erreur:

base_js = get_ytplayer_config(html)["assets"]["js"]
KeyError: 'assets'

Il est donné parce que cet extrait de code source ne prend pas en charge une recherche en tant que dicionario, donc erreur de clé 'KeyError', car 'assets' n'est pas une clé valide et le code source n'est pas un dictionnaire. J'ai donc fait ce script, qui je crois remplacer cet original, mais dans le mien, en particulier, sont apparus d'autres erreurs.

#Example ---------------
Vars = {
    'name':'luis'
    'age':'27'
}
print(Vars['name'])

result: 'luis'

#Extract.py Code -------

def js_url(html: str) -> str:
"""Get the base JavaScript url.

Construct the base JavaScript url, which contains 
the decipher
"transforms".

:param str html:
    The html contents of the watch page.
"""
base_js = get_ytplayer_config(html)["assets"]["js"]
return "https://youtube.com" + base_js

Le script ci-dessus recherche ce que la fonction veut sous forme de chaîne et non de dictionnaire.

J'espère avoir contribué à une solution future plus complète :)


0 commentaires

2
votes

Si vous utilisez le package pytube ou pytube3 , je vous recommande de le désinstaller et d'installer pytubeX . Pas besoin de modifier les importations. J'ai trouvé que cela fonctionne de manière beaucoup plus fiable.

Edit: à partir des commentaires, si aucun de ceux-ci ne fonctionne, essayez pytube4

Edit: pytube est à nouveau maintenu!


5 commentaires

pytubeX réussit là où pytube3 a échoué. Mais pytube4 semble encore mieux fonctionner que pytubeX ...


@ Jean-PierreSchnyder Y a-t-il une grande différence entre pytube4 et PytubeX? Les deux ont la même description et les mêmes slogans.


@ Jean-PierreSchnyder et theboy oui, ils ont même la même page github


@KetZoomer J'adorerais une fois le problème résolu. Pytube4 et X reviennent tous les deux avec la même erreur, même si je pense que cela peut avoir à voir avec la vidéo ayant des caractères spéciaux.


On dirait que pytube est à nouveau entretenu !!!



1
votes

C'est un problème avec les fichiers de la bibliothèque pytube. Vous pouvez résoudre ce problème en modifiant manuellement le fichier "extract.py" dans le dossier pytube. Copiez et collez plutôt ceci dans le fichier:https://github.com/nficano/pytube/blob/master/pytube/extract.py


0 commentaires

9
votes

Pour l'instant fixé à 100% avec ceci:

https://github.com/nficano/pytube/pull/767#issuecomment-716184994

Si quelqu'un d'autre obtient cette erreur ou ce problème, exécutez cette commande dans un terminal ou cmd: python -m pip install git+https://github.com/nficano/pytube

Une mise à jour de pytubeX qui n'a pas encore été publiée avec l'installation de pip. Le lien GitHub est le développeur actuel expliquant la situation.


0 commentaires

1
votes

Fixé

La base de code extract.py est maintenant mise à jour si vous obtenez toujours l'erreur après avoir exécuté cette commande dans un terminal ou cmd: python -m pip install git + https: //github.com/nficano/pytube est parce que ce n'est pas le cas a mis à jour votre fichier pytube / extract.py.

Le correctif est de copier tout le code de la base de code et de le remplacer dans votre fichier extract.py. J'espère que cela fonctionnera.


0 commentaires

5
votes

Ajoutez cette fonction à extract.py

def js_url(html: str) -> str:
    """Get the base JavaScript url.

    Construct the base JavaScript url, which contains the decipher
    "transforms".

    :param str html:
        The html contents of the watch page.
    """
    base_js = get_ytplayer_js(html)
    return "https://youtube.com" + base_js

et changez la fonction "js_url" dans extract.py de:

def js_url(html: str) -> str:
    """Get the base JavaScript url.

    Construct the base JavaScript url, which contains the decipher
    "transforms".

    :param str html:
        The html contents of the watch page.
    """
    base_js = get_ytplayer_config(html)["assets"]["js"]
    return "https://youtube.com" + base_js

à:

def get_ytplayer_js(html: str) -> Any:
    """Get the YouTube player base JavaScript path.

    :param str html
    The html contents of the watch page.
    :rtype: str
    :returns:
    Path to YouTube's base.js file.
    """
    js_url_patterns = [
        r"\"jsUrl\":\"([^\"]*)\"",
    ]
    for pattern in js_url_patterns:
        regex = re.compile(pattern)
        function_match = regex.search(html)
        if function_match:
            logger.debug("finished regex search, matched: %s", pattern)
            yt_player_js = function_match.group(1)
            return yt_player_js

    raise RegexMatchError(
       caller="get_ytplayer_js", pattern="js_url_patterns"
    )


1 commentaires

Je suppose que cela ne fonctionne pas dans pytube3 mais cela fonctionne dans pytubex



0
votes

Afin d'éviter ce problème de pytube, vous pouvez utiliser youtube_dl à la place. Voici un code qui a été testé sur Windows et sur une tablette Android (avec l'application Pydroid3). Le but est de télécharger la piste audio des vidéos référencées dans une playlist publique.

import os, re
import youtube_dl
from pytube import Playlist

YOUTUBE_STREAM_AUDIO = '140'
if os.name == 'posix':
    targetAudioDir = '/storage/emulated/0/Download/Audiobooks/test_youtube_dl'
    ydl_opts = {
    'outtmpl': targetAudioDir + '/%(title)s.mp3',
    'format': 'bestaudio/best',
    'quiet': False
    }
else:
    targetAudioDir = 'D:\\Users\\Jean-Pierre\\Downloads\\Audiobooks\\test_youtube_dl'
    ydl_opts = {
    'outtmpl': targetAudioDir + '\\%(title)s.%(ext)s',
    'format': 'bestaudio/best',
    'postprocessors': [{
                        'key': 'FFmpegExtractAudio',
                        'preferredcodec': 'mp3',
                        'preferredquality': '128',
                    }],
    'quiet': False
    }

playlistUrl = 'https://www.youtube.com/playlist?list=PLzwWSJNcZTMSFWGrRGKOypqN29MlyuQvn'
playlistObject = Playlist(playlistUrl)
playlistObject._video_regex = re.compile(r"\"url\":\"(/watch\?v=[\w-]*)")
    
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    for videoUrl in playlistObject.video_urls:
        meta = ydl.extract_info(videoUrl, download=False)
        videoTitle = meta['title']
        print('Video title: ' + videoTitle)
        ydl.download([videoUrl])


0 commentaires

5
votes

Il semble que le module Pytube soit mis à jour.

Cela fonctionne bien pour le paquet pytube

par exemple, essayez pip install pytube désinstaller les variantes de pytube


0 commentaires

3
votes

J'ai eu le même problème et la mise à jour de pytube vers la dernière version disponible actuellement le problème a disparu.

pip install --upgrade pytube

ou

pip install pytube==10.0.0


0 commentaires