Dies ist eine Python-API, mit der Sie das Transkript/Untertitel für ein bestimmtes YouTube-Video abrufen können. Sie funktioniert auch mit automatisch generierten Untertiteln, unterstützt die Übersetzung von Untertiteln und benötigt keinen headless Browser, wie es andere Selenium-basierte Lösungen erfordern!
Die Wartung dieses Projekts wird durch alle Mitwirkenden und Sponsoren ermöglicht. Wenn Sie dieses Projekt sponsern und Ihr Avatar oder Firmenlogo unten erscheinen lassen möchten, klicken Sie hier. 💖
Es wird empfohlen, dieses Modul mit pip zu installieren:
pip install youtube-transcript-api
Sie können dieses Modul entweder in eine bestehende Anwendung integrieren oder es einfach über die CLI verwenden.
Der einfachste Weg, ein Transkript für ein bestimmtes Video zu erhalten, ist die Ausführung von:
from youtube_transcript_api import YouTubeTranscriptApi
ytt_api = YouTubeTranscriptApi()
ytt_api.fetch(video_id)
Hinweis: Standardmäßig wird versucht, auf das englische Transkript des Videos zuzugreifen. Wenn Ihr Video eine andere Sprache hat oder Sie ein Transkript in einer anderen Sprache abrufen möchten, lesen Sie bitte den folgenden Abschnitt.
Hinweis: Geben Sie die Video-ID ein, NICHT die Video-URL. Für ein Video mit der URL
https://www.youtube.com/watch?v=12345
lautet die ID12345
.
Dies gibt ein FetchedTranscript
-Objekt zurück, das ungefähr so aussieht:
FetchedTranscript(
snippets=[
FetchedTranscriptSnippet(
text="Hey there",
start=0.0,
duration=1.54,
),
FetchedTranscriptSnippet(
text="how are you",
start=1.54,
duration=4.16,
),
# ...
],
video_id="12345",
language="English",
language_code="en",
is_generated=False,
)
Dieses Objekt implementiert die meisten Schnittstellen einer List
:
ytt_api = YouTubeTranscriptApi()
fetched_transcript = ytt_api.fetch(video_id)
# is iterable
for snippet in fetched_transcript:
print(snippet.text)
# indexable
last_snippet = fetched_transcript[-1]
# provides a length
snippet_count = len(fetched_transcript)
Wenn Sie die Rohdaten des Transkripts bevorzugen, können Sie fetched_transcript.to_raw_data()
aufrufen, was eine Liste von Dictionaries zurückgibt:
[
{
'text': 'Hey there',
'start': 0.0,
'duration': 1.54
},
{
'text': 'how are you',
'start': 1.54
'duration': 4.16
},
# ...
]
Sie können den languages
-Parameter hinzufügen, wenn Sie sicherstellen möchten, dass die Transkripte in Ihrer gewünschten Sprache abgerufen werden (standardmäßig Englisch).
YouTubeTranscriptApi().fetch(video_id, languages=['de', 'en'])
Es handelt sich um eine Liste von Sprachcodes in absteigender Priorität. In diesem Beispiel wird zuerst versucht, das deutsche Transkript ('de'
) abzurufen, und falls dies fehlschlägt, das englische Transkript ('en'
). Wenn Sie herausfinden möchten, welche Sprachen verfügbar sind, sehen Sie sich list()
an.
Wenn Sie nur eine Sprache möchten, müssen Sie das languages
-Argument dennoch als Liste formatieren:
YouTubeTranscriptApi().fetch(video_id, languages=['de'])
Sie können auch preserve_formatting=True
hinzufügen, wenn Sie HTML-Formatierungselemente wie <i>
(kursiv) und <b>
(fett) beibehalten möchten.
YouTubeTranscriptApi().fetch(video_ids, languages=['de', 'en'], preserve_formatting=True)
Wenn Sie alle Transkripte auflisten möchten, die für ein bestimmtes Video verfügbar sind, können Sie folgendes aufrufen:
ytt_api = YouTubeTranscriptApi()
transcript_list = ytt_api.list(video_id)
Dies gibt ein TranscriptList
-Objekt zurück, das iterierbar ist und Methoden bereitstellt, um die Liste der Transkripte nach bestimmten Sprachen und Typen zu filtern, wie z.B.:
transcript = transcript_list.find_transcript(['de', 'en'])
Standardmäßig wählt dieses Modul immer manuell erstellte Transkripte vor automatisch generierten aus, wenn ein Transkript in der gewünschten Sprache sowohl manuell erstellt als auch generiert verfügbar ist. Die TranscriptList
ermöglicht es Ihnen, dieses Standardverhalten zu umgehen, indem Sie nach bestimmten Transkripttypen suchen:
# filter for manually created transcripts
transcript = transcript_list.find_manually_created_transcript(['de', 'en'])
# or automatically generated ones
transcript = transcript_list.find_generated_transcript(['de', 'en'])
Die Methoden find_generated_transcript
, find_manually_created_transcript
, find_transcript
geben Transcript
-Objekte zurück. Diese enthalten Metadaten zum Transkript:
print(
transcript.video_id,
transcript.language,
transcript.language_code,
# whether it has been manually created or generated by YouTube
transcript.is_generated,
# whether this transcript can be translated or not
transcript.is_translatable,
# a list of languages the transcript can be translated to
transcript.translation_languages,
)
und bieten die Methode, mit der Sie die eigentlichen Transkriptdaten abrufen können:
transcript.fetch()
Dies gibt ein FetchedTranscript
-Objekt zurück, genau wie YouTubeTranscriptApi().fetch()
.
YouTube bietet eine Funktion, mit der Sie Untertitel automatisch übersetzen können. Dieses Modul ermöglicht ebenfalls den Zugriff auf diese Funktion. Dazu bieten Transcript
-Objekte eine translate()
-Methode, die ein neues übersetztes Transcript
-Objekt zurückgibt:
transcript = transcript_list.find_transcript(['en'])
translated_transcript = transcript.translate('de')
print(translated_transcript.fetch())
from youtube_transcript_api import YouTubeTranscriptApi
ytt_api = YouTubeTranscriptApi()
# retrieve the available transcripts
transcript_list = ytt_api.list('video_id')
# iterate over all available transcripts
for transcript in transcript_list:
# the Transcript object provides metadata properties
print(
transcript.video_id,
transcript.language,
transcript.language_code,
# whether it has been manually created or generated by YouTube
transcript.is_generated,
# whether this transcript can be translated or not
transcript.is_translatable,
# a list of languages the transcript can be translated to
transcript.translation_languages,
)
# fetch the actual transcript data
print(transcript.fetch())
# translating the transcript will return another transcript object
print(transcript.translate('en').fetch())
# you can also directly filter for the language you are looking for, using the transcript list
transcript = transcript_list.find_transcript(['de', 'en'])
# or just filter for manually created transcripts
transcript = transcript_list.find_manually_created_transcript(['de', 'en'])
# or automatically generated ones
transcript = transcript_list.find_generated_transcript(['de', 'en'])
RequestBlocked
oder IpBlocked
Exception)Leider hat YouTube damit begonnen, die meisten IPs zu sperren, die bekannten Cloud-Anbietern (wie AWS, Google Cloud Platform, Azure usw.) gehören. Das bedeutet, dass Sie höchstwahrscheinlich auf RequestBlocked
- oder IpBlocked
-Exceptions stoßen werden, wenn Sie Ihren Code in einer Cloud-Lösung bereitstellen. Dasselbe kann mit der IP Ihrer selbst gehosteten Lösung passieren, wenn Sie zu viele Anfragen stellen. Sie können diese IP-Sperren mit Proxies umgehen. Da YouTube jedoch statische Proxies nach längerer Nutzung sperrt, sind rotierende Residential Proxies die zuverlässigste Option.
Es gibt verschiedene Anbieter, die rotierende Residential Proxies anbieten, aber nach Tests verschiedener Angebote habe ich Webshare als den zuverlässigsten Anbieter identifiziert und daher in dieses Modul integriert, um die Einrichtung so einfach wie möglich zu gestalten.
Sobald Sie ein Webshare-Konto erstellt und ein "Residential"-Proxy-Paket gekauft haben, das zu Ihrer Arbeitslast passt (stellen Sie sicher, NICHT "Proxy Server" oder "Static Residential" zu kaufen!), öffnen Sie die Webshare Proxy-Einstellungen, um Ihren "Proxy-Benutzernamen" und Ihr "Proxy-Passwort" abzurufen. Mit diesen Informationen können Sie die YouTubeTranscriptApi
wie folgt initialisieren:
from youtube_transcript_api import YouTubeTranscriptApi
from youtube_transcript_api.proxies import WebshareProxyConfig
ytt_api = YouTubeTranscriptApi(
proxy_config=WebshareProxyConfig(
proxy_username="<proxy-username>",
proxy_password="<proxy-password>",
)
)
# all requests done by ytt_api will now be proxied through Webshare
ytt_api.fetch(video_id)
Die Verwendung von WebshareProxyConfig
verwendet standardmäßig rotierende Residential Proxies und erfordert keine weitere Konfiguration.
Beachten Sie, dass hier Referral-Links verwendet werden und alle Käufe über diese Links dieses Open-Source-Projekt unterstützen, was sehr geschätzt wird! 💖😊🙏💖
Sie sind jedoch natürlich frei, Ihre eigene Proxy-Lösung mit der GenericProxyConfig
-Klasse zu integrieren, wenn Sie einen anderen Anbieter bevorzugen oder Ihre eigene Lösung implementieren möchten, wie im folgenden Abschnitt beschrieben.
Alternativ zur Verwendung von Webshare können Sie jeden generischen HTTP/HTTPS/SOCKS-Proxy mit der GenericProxyConfig
-Klasse einrichten:
from youtube_transcript_api import YouTubeTranscriptApi
from youtube_transcript_api.proxies import GenericProxyConfig
ytt_api = YouTubeTranscriptApi(
proxy_config=GenericProxyConfig(
http_url="http://user:[email protected]:port",
https_url="https://user:[email protected]:port",
)
)
# all requests done by ytt_api will now be proxied using the defined proxy URLs
ytt_api.fetch(video_id)
Beachten Sie, dass die Verwendung eines Proxys nicht garantiert, dass Sie nicht gesperrt werden, da YouTube jederzeit die IP Ihres Proxys sperren kann! Daher sollten Sie immer eine Lösung wählen, die durch einen Pool von Proxy-Adressen rotiert, wenn Sie die Zuverlässigkeit maximieren möchten.
Bei der Initialisierung eines YouTubeTranscriptApi
-Objekts wird eine requests.Session
erstellt, die für alle HTTP(S)-Anfragen verwendet wird. Dies ermöglicht das Zwischenspeichern von Cookies beim Abrufen mehrerer Anfragen. Sie können jedoch optional ein requests.Session
-Objekt an den Konstruktor übergeben, wenn Sie Cookies manuell zwischen verschiedenen Instanzen von YouTubeTranscriptApi
teilen, Standards überschreiben, benutzerdefinierte Header festlegen, SSL-Zertifikate angeben usw. möchten.
from requests import Session
http_client = Session()
# set custom header
http_client.headers.update({"Accept-Encoding": "gzip, deflate"})
# set path to CA_BUNDLE file
http_client.verify = "/path/to/certfile"
ytt_api = YouTubeTranscriptApi(http_client=http_client)
ytt_api.fetch(video_id)
# share same Session between two instances of YouTubeTranscriptApi
ytt_api_2 = YouTubeTranscriptApi(http_client=http_client)
# now shares cookies with ytt_api
ytt_api_2.fetch(video_id)
Einige Videos sind altersbeschränkt, sodass dieses Modul ohne eine Art von Authentifizierung nicht auf diese Videos zugreifen kann. Leider haben einige kürzliche Änderungen an der YouTube-API die aktuelle Implementierung der cookie-basierten Authentifizierung unterbrochen, sodass diese Funktion derzeit nicht verfügbar ist.
Formatierer sind als zusätzliche Verarbeitungsschicht für das Transkript gedacht, das Sie ihm übergeben. Das Ziel ist es, ein FetchedTranscript
-Objekt in einen konsistenten String eines bestimmten "Formats" umzuwandeln. Wie z.B. einfacher Text (.txt
) oder sogar Formate, die eine definierte Spezifikation haben, wie JSON (.json
), WebVTT (.vtt
), SRT (.srt
), kommagetrenntes Format (.csv
) usw.
Das formatters
-Submodul bietet einige grundlegende Formatierer, die wie sie sind verwendet oder nach Ihren Bedürfnissen erweitert werden können:
Hier ist, wie Sie aus dem formatters
-Modul importieren können.
# the base class to inherit from when creating your own formatter.
from youtube_transcript_api.formatters import Formatter
# some provided subclasses, each outputs a different string format.
from youtube_transcript_api.formatters import JSONFormatter
from youtube_transcript_api.formatters import TextFormatter
from youtube_transcript_api.formatters import WebVTTFormatter
from youtube_transcript_api.formatters import SRTFormatter
Angenommen, wir möchten ein Transkript abrufen und in einer JSON-Datei speichern. Das würde ungefähr so aussehen:
# your_custom_script.py
from youtube_transcript_api import YouTubeTranscriptApi
from youtube_transcript_api.formatters import JSONFormatter
ytt_api = YouTubeTranscriptApi()
transcript = ytt_api.fetch(video_id)
formatter = JSONFormatter()
# .format_transcript(transcript) turns the transcript into a JSON string.
json_formatted = formatter.format_transcript(transcript)
# Now we can write it out to a file.
with open('your_filename.json', 'w', encoding='utf-8') as json_file:
json_file.write(json_formatted)
# Now should have a new JSON file that you can easily read back into Python.
Übergeben zusätzlicher Keyword-Argumente
Da JSONFormatter json.dumps()
nutzt, können Sie auch Keyword-Argumente an .format_transcript(transcript)
weitergeben, wie z.B. indent=2
, um Ihre Dateiausgabe übersichtlicher zu gestalten.
json_formatted = JSONFormatter().format_transcript(transcript, indent=2)
Sie können Ihre eigene Formatierer-Klasse implementieren. Erben Sie einfach von der Formatter
-Basisklasse und stellen Sie sicher, dass Sie die Methoden format_transcript(self, transcript: FetchedTranscript, **kwargs) -> str
und format_transcripts(self, transcripts: List[FetchedTranscript], **kwargs) -> str
implementieren, die letztendlich einen String zurückgeben sollten, wenn sie auf Ihrer Formatierer-Instanz aufgerufen werden.
class MyCustomFormatter(Formatter):
def format_transcript(self, transcript: FetchedTranscript, **kwargs) -> str:
# Do your custom work in here, but return a string.
return 'your processed output data as a string.'
def format_transcripts(self, transcripts: List[FetchedTranscript], **kwargs) -> str:
# Do your custom work in here to format a list of transcripts, but return a string.
return 'your processed output data as a string.'
Führen Sie das CLI-Skript mit den Video-IDs als Parameter aus, und die Ergebnisse werden auf der Kommandozeile ausgegeben:
youtube_transcript_api <first_video_id> <second_video_id> ...
Die CLI gibt Ihnen auch die Möglichkeit, eine Liste bevorzugter Sprachen anzugeben:
youtube_transcript_api <first_video_id> <second_video_id> ... --languages de en
Sie können auch angeben, ob Sie automatisch generierte oder manuell erstellte Untertitel ausschließen möchten:
youtube_transcript_api <first_video_id> <second_video_id> ... --languages de en --exclude-generated
youtube_transcript_api <first_video_id> <second_video_id> ... --languages de en --exclude-manually-created
Wenn Sie die Ergebnisse lieber in eine Datei schreiben oder in eine andere Anwendung pipen möchten, können Sie die Ergebnisse auch als JSON ausgeben:
youtube_transcript_api <first_video_id> <second_video_id> ... --languages de en --format json > transcripts.json
Das Übersetzen von Transkripten mit der CLI ist ebenfalls möglich:
youtube_transcript_api <first_video_id> <second_video_id> ... --languages en --translate de
Wenn Sie nicht sicher sind, welche Sprachen für ein bestimmtes Video verfügbar sind, können Sie folgendes aufrufen, um alle verfügbaren Transkripte aufzulisten:
youtube_transcript_api --list-transcripts <first_video_id>
Wenn eine Video-ID mit einem Bindestrich beginnt, müssen Sie den Bindestrich mit \
maskieren, um zu verhindern, dass die CLI ihn fälschlicherweise als Argumentnamen interpretiert. Um beispielsweise das Transkript für das Video mit der ID -abc123
abzurufen, führen Sie aus:
youtube_transcript_api "\-abc123"
Wenn Sie auf RequestBlocked
- oder IpBlocked
-Fehler stoßen, weil YouTube Ihre IP sperrt, können Sie dies mit Residential Proxies umgehen, wie in Umgehung von IP-Sperren erklärt. Um Webshare "Residential" Proxies über die CLI zu verwenden, müssen Sie ein Webshare-Konto erstellen und ein "Residential"-Proxy-Paket kaufen, das zu Ihrer Arbeitslast passt (stellen Sie sicher, NICHT "Proxy Server" oder "Static Residential" zu kaufen!). Dann können Sie den "Proxy-Benutzernamen" und das "Proxy-Passwort", die Sie in Ihren Webshare Proxy-Einstellungen finden, verwenden, um den folgenden Befehl auszuführen:
youtube_transcript_api <first_video_id> <second_video_id> --webshare-proxy-username "username" --webshare-proxy-password "password"
Wenn Sie lieber eine andere Proxy-Lösung verwenden möchten, können Sie einen generischen HTTP/HTTPS-Proxy mit folgendem Befehl einrichten:
youtube_transcript_api <first_video_id> <second_video_id> --http-proxy http://user:pass@domain:port --https-proxy https://user:pass@domain:port
Um sich mit Cookies über die CLI zu authentifizieren, wie in Cookie-Authentifizierung erklärt, führen Sie aus:
youtube_transcript_api <first_video_id> <second_video_id> --cookies /path/to/your/cookies.txt
Dieser Code verwendet einen undokumentierten Teil der YouTube-API, der vom YouTube-Webclient aufgerufen wird. Es gibt also keine Garantie, dass er nicht morgen aufhört zu funktionieren, wenn sie die Funktionsweise ändern. Ich werde jedoch mein Bestes tun, um die Funktionalität so schnell wie möglich wiederherzustellen, falls dies passiert. Wenn es also nicht mehr funktioniert, lassen Sie es mich wissen!
Um das Projekt lokal einzurichten, führen Sie folgendes aus (erfordert die Installation von poetry):
poetry install --with test,dev
Es gibt poe-Aufgaben, um Tests, Coverage, den Linter und den Formatter auszuführen (Sie müssen alle bestehen, damit der Build erfolgreich ist):
poe test
poe coverage
poe format
poe lint
Wenn Sie nur sicherstellen möchten, dass Ihr Code alle notwendigen Prüfungen besteht, um einen erfolgreichen Build zu erhalten, können Sie einfach ausführen:
poe precommit
Wenn dieses Projekt Ihnen Freude bereitet, indem es Ihre Entwicklungszeit verkürzt, können Sie mir Freude bereiten, indem Sie mir einen Kaffee spendieren oder Sponsor dieses Projekts werden :)