Last translated: 12 Jun 2025

Translation Not Available Yet

This repository's README hasn't been translated yet. Once translated, it will be easier to read and understand in your native language (中文).

After translating, add the links to README so others can view it directly.

✨ YouTube Transcript API ✨

Donate Build Status Coverage Status MIT license Current Version Supported Python Versions

Это Python API, которое позволяет получать транскрипты/субтитры для заданного видео на YouTube. Оно также работает с автоматически сгенерированными субтитрами, поддерживает перевод субтитров и не требует использования headless-браузера, в отличие от решений на основе Selenium!

Поддержка этого проекта стала возможной благодаря всем участникам и спонсорам. Если вы хотите спонсировать этот проект и разместить свой аватар или логотип компании ниже, нажмите здесь. 💖

SearchAPI        supadata        Dumpling AI

Установка

Рекомендуется установить этот модуль с помощью pip:

pip install youtube-transcript-api

Вы можете интегрировать этот модуль в существующее приложение или просто использовать его через CLI.

API

Самый простой способ получить транскрипт для заданного видео — выполнить:

from youtube_transcript_api import YouTubeTranscriptApi

ytt_api = YouTubeTranscriptApi()
ytt_api.fetch(video_id)

Примечание: По умолчанию будет предпринята попытка получить английский транскрипт видео. Если у вашего видео другой язык или вы хотите получить транскрипт на другом языке, прочитайте раздел ниже.

Примечание: Передавайте ID видео, а не URL. Для видео с URL https://www.youtube.com/watch?v=12345 ID — это 12345.

Это вернет объект FetchedTranscript, который выглядит примерно так:

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,
)

Этот объект реализует большинство интерфейсов 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)

Если вы предпочитаете работать с сырыми данными транскрипта, вы можете вызвать fetched_transcript.to_raw_data(), который вернет список словарей:

[
    {
        'text': 'Hey there',
        'start': 0.0,
        'duration': 1.54
    },
    {
        'text': 'how are you',
        'start': 1.54
        'duration': 4.16
    },
    # ...
]

Получение разных языков

Вы можете добавить параметр languages, если хотите убедиться, что транскрипты будут получены на нужном вам языке (по умолчанию — английский).

YouTubeTranscriptApi().fetch(video_id, languages=['de', 'en'])

Это список кодов языков в порядке убывания приоритета. В этом примере сначала будет предпринята попытка получить немецкий транскрипт ('de'), а затем английский ('en'), если первая попытка не удастся. Если вы хотите узнать, какие языки доступны, ознакомьтесь с list().

Если вам нужен только один язык, параметр languages все равно должен быть оформлен как список:

YouTubeTranscriptApi().fetch(video_id, languages=['de'])

Сохранение форматирования

Вы также можете добавить preserve_formatting=True, если хотите сохранить элементы HTML-форматирования, такие как <i> (курсив) и <b> (жирный шрифт).

YouTubeTranscriptApi().fetch(video_ids, languages=['de', 'en'], preserve_formatting=True)

Список доступных транскриптов

Если вы хотите получить список всех доступных транскриптов для заданного видео, вы можете вызвать:

ytt_api = YouTubeTranscriptApi()
transcript_list = ytt_api.list(video_id)

Это вернет объект TranscriptList, который является итерируемым и предоставляет методы для фильтрации списка транскриптов по определенным языкам и типам, например:

transcript = transcript_list.find_transcript(['de', 'en'])

По умолчанию этот модуль всегда выбирает ручные транскрипты вместо автоматически созданных, если транскрипт на запрашиваемом языке доступен в обоих вариантах. TranscriptList позволяет обойти это поведение по умолчанию, выполнив поиск по определенным типам транскриптов:

# 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'])

Методы find_generated_transcript, find_manually_created_transcript, find_transcript возвращают объекты Transcript. Они содержат метаданные о транскрипте:

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,
)

и предоставляют метод, который позволяет получить фактические данные транскрипта:

transcript.fetch()

Это возвращает объект FetchedTranscript, так же как и YouTubeTranscriptApi().fetch().

Перевод транскрипта

YouTube имеет функцию автоматического перевода субтитров. Этот модуль также позволяет получить доступ к этой функции. Для этого объекты Transcript предоставляют метод translate(), который возвращает новый переведенный объект Transcript:

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'])

Обход блокировок IP (RequestBlocked или IpBlocked исключение)

К сожалению, YouTube начал блокировать большинство IP-адресов, которые принадлежат облачным провайдерам (таким как AWS, Google Cloud Platform, Azure и т. д.), что означает, что вы, скорее всего, столкнетесь с исключениями ReuquestBlocked или IpBlocked при развертывании кода в облачных решениях. То же самое может произойти с IP-адресом вашего самодельного решения, если вы делаете слишком много запросов. Вы можете обойти эти блокировки с помощью прокси. Однако, поскольку YouTube блокирует статические прокси после длительного использования, наиболее надежным вариантом являются ротируемые резидентные прокси.

Существуют разные провайдеры, предлагающие ротируемые резидентные прокси, но после тестирования различных вариантов я обнаружил, что Webshare является наиболее надежным и интегрировал его в этот модуль, чтобы упростить настройку.

Использование Webshare

После создания аккаунта Webshare и покупки пакета "Residential" прокси, подходящего для вашей нагрузки (убедитесь, что НЕ покупаете "Proxy Server" или "Static Residential"!), откройте настройки прокси Webshare, чтобы получить "Proxy Username" и "Proxy Password". Используя эту информацию, вы можете инициализировать YouTubeTranscriptApi следующим образом:

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)

Использование WebshareProxyConfig по умолчанию предполагает использование ротируемых резидентных прокси и не требует дополнительной настройки.

Обратите внимание, что здесь используются реферальные ссылки, и любые покупки, сделанные по этим ссылкам, поддержат этот Open Source проект, что очень ценится! 💖😊🙏💖

Однако вы, конечно, можете интегрировать собственное решение с прокси, используя класс GenericProxyConfig, если предпочитаете другого провайдера или хотите реализовать собственное решение, как описано в следующем разделе.

Использование других решений с прокси

В качестве альтернативы Webshare вы можете настроить любой HTTP/HTTPS/SOCKS прокси с помощью класса GenericProxyConfig:

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)

Учтите, что использование прокси не гарантирует, что вас не заблокируют, так как YouTube может заблокировать IP-адрес вашего прокси! Поэтому, если вы хотите максимизировать надежность, следует выбирать решение, которое ротирует пул адресов прокси.

Переопределение настроек запроса по умолчанию

При инициализации объекта YouTubeTranscriptApi создается requests.Session, который будет использоваться для всех HTTP(S) запросов. Это позволяет кэшировать куки при получении нескольких запросов. Однако вы можете передать объект requests.Session в конструктор, если хотите вручную разделить куки между разными экземплярами YouTubeTranscriptApi, переопределить настройки по умолчанию, установить пользовательские заголовки, указать SSL-сертификаты и т. д.

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)

Аутентификация с помощью куки

Некоторые видео имеют возрастные ограничения, поэтому этот модуль не сможет получить доступ к ним без какой-либо аутентификации. К сожалению, недавние изменения в API YouTube нарушили текущую реализацию аутентификации на основе куки, поэтому эта функция сейчас недоступна.

Использование форматтеров

Форматтеры предназначены для дополнительной обработки транскрипта, который вы им передаете. Цель — преобразовать объект FetchedTranscript в строку заданного "формата". Например, простой текст (.txt) или форматы с определенной спецификацией, такие как JSON (.json), WebVTT (.vtt), SRT (.srt), CSV (.csv) и т. д.

Подмодуль formatters предоставляет несколько базовых форматтеров, которые можно использовать как есть или расширить под свои нужды:

  • JSONFormatter
  • PrettyPrintFormatter
  • TextFormatter
  • WebVTTFormatter
  • SRTFormatter

Вот как можно импортировать из модуля formatters:

# 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

Пример форматтера

Допустим, мы хотим получить транскрипт и сохранить его в JSON-файл. Это будет выглядеть примерно так:

# 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.

Передача дополнительных аргументов

Поскольку JSONFormatter использует json.dumps(), вы также можете передать дополнительные аргументы в .format_transcript(transcript), например, сделать вывод файла более читаемым, передав аргумент indent=2.

json_formatted = JSONFormatter().format_transcript(transcript, indent=2)

Пример пользовательского форматтера

Вы можете реализовать собственный класс форматтера. Просто унаследуйтесь от базового класса Formatter и убедитесь, что реализовали методы format_transcript(self, transcript: FetchedTranscript, **kwargs) -> str и format_transcripts(self, transcripts: List[FetchedTranscript], **kwargs) -> str, которые в конечном итоге должны возвращать строку при вызове на экземпляре вашего форматтера.

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.'

CLI

Выполните CLI-скрипт, используя ID видео в качестве параметров, и результаты будут выведены в командную строку:

youtube_transcript_api <first_video_id> <second_video_id> ...  

CLI также позволяет указать список предпочитаемых языков:

youtube_transcript_api <first_video_id> <second_video_id> ... --languages de en  

Вы также можете указать, хотите ли вы исключить автоматически сгенерированные или ручные субтитры:

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

Если вы предпочитаете записать результаты в файл или передать их в другое приложение, вы также можете вывести результаты в формате JSON:

youtube_transcript_api <first_video_id> <second_video_id> ... --languages de en --format json > transcripts.json

Перевод транскриптов через CLI также возможен:

youtube_transcript_api <first_video_id> <second_video_id> ... --languages en --translate de

Если вы не уверены, какие языки доступны для заданного видео, вы можете вызвать команду для списка всех доступных транскриптов:

youtube_transcript_api --list-transcripts <first_video_id>

Если ID видео начинается с дефиса, вам нужно экранировать его с помощью \, чтобы CLI не принял его за аргумент. Например, чтобы получить транскрипт для видео с ID -abc123, выполните:

youtube_transcript_api "\-abc123"

Обход блокировок IP через CLI

Если вы сталкиваетесь с ошибками ReqestBlocked или IpBlocked из-за блокировки вашего IP YouTube, вы можете обойти это с помощью резидентных прокси, как описано в Обход блокировок IP. Чтобы использовать резидентные прокси Webshare через CLI, вам нужно создать аккаунт Webshare и купить пакет "Residential" прокси, подходящий для вашей нагрузки (убедитесь, что НЕ покупаете "Proxy Server" или "Static Residential"!). Затем вы можете использовать "Proxy Username" и "Proxy Password" из настроек прокси Webshare, чтобы выполнить следующую команду:

youtube_transcript_api <first_video_id> <second_video_id> --webshare-proxy-username "username" --webshare-proxy-password "password"

Если вы предпочитаете другое решение с прокси, вы можете настроить общий HTTP/HTTPS прокси с помощью следующей команды:

youtube_transcript_api <first_video_id> <second_video_id> --http-proxy http://user:pass@domain:port --https-proxy https://user:pass@domain:port

Аутентификация с помощью куки через CLI

Для аутентификации с помощью куки через CLI, как описано в Аутентификация с помощью куки, выполните:

youtube_transcript_api <first_video_id> <second_video_id> --cookies /path/to/your/cookies.txt

Предупреждение

Этот код использует недокументированную часть YouTube API, которая вызывается веб-клиентом YouTube. Поэтому нет гарантии, что он не перестанет работать завтра, если YouTube изменит свою работу. Однако я приложу все усилия, чтобы как можно скорее восстановить работоспособность, если это произойдет. Так что если что-то перестанет работать, дайте мне знать!

Участие в разработке

Для локальной настройки проекта выполните следующее (требуется установленный poetry):

poetry install --with test,dev

Есть задачи poe для запуска тестов, покрытия, линтера и форматтера (вам нужно пройти все эти проверки для успешной сборки):

poe test
poe coverage
poe format
poe lint

Если вы просто хотите убедиться, что ваш код проходит все необходимые проверки для успешной сборки, вы можете просто выполнить:

poe precommit

Пожертвования

Если этот проект сэкономил ваше время разработки, вы можете сделать меня счастливым, угостив меня чашечкой кофе или став Спонсором этого проекта :)

Donate