这是一个 Python API,可用来获取 YouTube 视频的字幕或文本记录,能处理自动生成的字幕,支持翻译字幕。和其他基于 Selenium 的解决方案不同,它不需要无头浏览器。
建议通过 pip 安装这个模块:
pip install youtube-transcript-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)
# 可迭代
for snippet in fetched_transcript:
print(snippet.text)
# 可索引
last_snippet = fetched_transcript[-1]
# 可获取长度
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'])
如果你想保留 HTML 格式元素,比如 <i>
(斜体)和 <b>
(粗体),也可以添加 preserve_formatting=True
。
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
允许你绕过这个默认行为,搜索特定的字幕类型:
# 过滤手动创建的字幕
transcript = transcript_list.find_manually_created_transcript(['de', 'en'])
# 或自动生成的字幕
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,
# 它是手动创建的还是由 YouTube 生成的
transcript.is_generated,
# 这个字幕是否可以翻译
transcript.is_translatable,
# 这个字幕可以翻译成的语言列表
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()
# 检索可用的字幕
transcript_list = ytt_api.list('video_id')
# 遍历所有可用的字幕
for transcript in transcript_list:
# Transcript 对象提供元数据属性
print(
transcript.video_id,
transcript.language,
transcript.language_code,
# 它是手动创建的还是由 YouTube 生成的
transcript.is_generated,
# 这个字幕是否可以翻译
transcript.is_translatable,
# 这个字幕可以翻译成的语言列表
transcript.translation_languages,
)
# 获取实际的字幕数据
print(transcript.fetch())
# 翻译字幕将返回另一个字幕对象
print(transcript.translate('en').fetch())
# 你也可以直接使用字幕列表过滤你要找的语言
transcript = transcript_list.find_transcript(['de', 'en'])
# 或只是过滤手动创建的字幕
transcript = transcript_list.find_manually_created_transcript(['de', 'en'])
# 或自动生成的字幕
transcript = transcript_list.find_generated_transcript(['de', 'en'])
RequestBlocked
或 IpBlocked
异常)不幸的是,YouTube 已经开始阻止大多数已知属于云提供商(如 AWS、Google Cloud Platform、Azure 等)的 IP,这意味着当你将代码部署到任何云解决方案时,很可能会遇到 ReuquestBlocked
或 IpBlocked
异常。如果你的自托管解决方案发出太多请求,其 IP 也可能遇到这种情况。你可以使用代理来解决这些 IP 封禁问题。然而,由于 YouTube 会在长时间使用后封禁静态代理,因此使用旋转住宅代理是可靠的选择。
有不同的提供商提供旋转住宅代理,但在测试了不同的产品后,我发现 Webshare 是可靠的,因此将其集成到这个模块中,使其设置起来容易。
一旦你创建了一个 Webshare 账户并购买了适合你工作负载的“住宅”代理包(确保不要购买“代理服务器”或“静态住宅”!),打开 Webshare 代理设置以检索你的“代理用户名”和“代理密码”。使用此信息,你可以按如下方式初始化 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>",
)
)
# ytt_api 完成的所有请求现在都将通过 Webshare 代理
ytt_api.fetch(video_id)
使用 WebshareProxyConfig
将默认使用旋转住宅代理,无需进一步配置。
除了使用 Webshare,你还可以使用 GenericProxyConfig
类设置任何通用的 HTTP/HTTPS/SOCKS 代理:
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",
)
)
# ytt_api 完成的所有请求现在都将使用定义的代理 URL 进行代理
ytt_api.fetch(video_id)
请注意,使用代理并不能保证你不会被阻止,因为 YouTube 总是可以阻止你代理的 IP!因此,如果你想最大化可靠性,你应该始终选择一个通过代理地址池轮换的解决方案。
初始化 YouTubeTranscriptApi
对象时,它将创建一个 requests.Session
,用于所有 HTTP(S) 请求。这允许在检索多个请求时缓存 cookie。但是,如果你想在不同的 YouTubeTranscriptApi
实例之间手动共享 cookie、覆盖默认值、设置自定义标头、指定 SSL 证书等,你可以选择将 requests.Session
对象传入其构造函数。
from requests import Session
http_client = Session()
# 设置自定义标头
http_client.headers.update({"Accept-Encoding": "gzip, deflate"})
# 设置 CA_BUNDLE 文件的路径
http_client.verify = "/path/to/certfile"
ytt_api = YouTubeTranscriptApi(http_client=http_client)
ytt_api.fetch(video_id)
# 在两个 YouTubeTranscriptApi 实例之间共享同一个 Session
ytt_api_2 = YouTubeTranscriptApi(http_client=http_client)
# 现在与 ytt_api 共享 cookie
ytt_api_2.fetch(video_id)
格式化工具旨在作为你传递给它的字幕的额外处理层,目的是将 FetchedTranscript
对象转换为给定“格式”的一致字符串,例如基本文本(.txt
),甚至是具有定义规范的格式,如 JSON(.json
)、WebVTT(.vtt
)、SRT(.srt
)、逗号分隔格式(.csv
)等。
formatters
子模块提供了一些基本的格式化工具,可以直接使用或根据需要进行扩展:
• JSONFormatter
• PrettyPrintFormatter
• TextFormatter
• WebVTTFormatter
• SRTFormatter
下面是如何从 formatters
模块导入:
# 创建自己的格式化工具时要继承的基类
from youtube_transcript_api.formatters import Formatter
# 一些提供的子类,每个子类输出不同的字符串格式
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) 将字幕转换为 JSON 字符串
json_formatted = formatter.format_transcript(transcript)
# 现在我们可以将其写入文件
with open('your_filename.json', 'w', encoding='utf-8') as json_file:
json_file.write(json_formatted)
# 现在应该有一个新的 JSON 文件,你可以轻松地读回 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:
# 在这里完成你的自定义工作,但要返回一个字符串
return 'your processed output data as a string.'
def format_transcripts(self, transcripts: List[FetchedTranscript], **kwargs) -> str:
# 在这里完成你的自定义工作以格式化字幕列表,但要返回一个字符串
return 'your processed output data as a string.'
使用视频 ID 作为参数执行 CLI 脚本,结果将打印到命令行:
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"
如果你遇到 ReqestBlocked
或 IpBlocked
错误,因为 YouTube 阻止了你的 IP,你可以按照“解决 IP 封禁问题”中解释的那样使用住宅代理来解决这个问题。要通过 CLI 使用 Webshare“住宅”代理,你必须创建一个 Webshare 账户并购买适合你工作负载的“住宅”代理包(确保不要购买“代理服务器”或“静态住宅”!)。然后你可以使用你在 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 按照“cookie 身份验证”中解释的那样使用 cookie 进行身份验证,请运行:
youtube_transcript_api <first_video_id> <second_video_id> --cookies /path/to/your/cookies.txt