一款超好用的Python油管视频下载工具

后端技术漫谈

共 18239字,需浏览 37分钟

 ·

2021-03-07 00:45

阅读本文大概需要 3 分钟。



在这里介绍一个工具,使用它我们可以非常方便地使用 Python 下载 Youtube 的视频,叫做 pytube。

利用它我们可以实现如下功能:

  • 支持 progresive 和 DASH 视频流的下载
  • 支持下载完整的播放列表
  • 可以处理下载进行中和下载完成的回调
  • 提供命令行直接执行下载
  • 支持下载字幕
  • 支持将字幕输出为 srt 格式
  • 获取视频缩略图

下面我们就来详细了解一下它的使用方法。

安装

首先看下安装过程,安装非常简单,只需要使用 pip3 安装即可,命令如下:

pip3 install pytube

或者直接源码安装也行:

pip3 install git+https://github.com/pytube/pytube

安装完成之后就可以使用 pytube 命令了。

使用

这里先介绍两个最常见的用法,那就是直接使用 pytube 命令,它可以用来下载单个 Yotube 视频或者视频列表。

比如这是一个视频 https://youtube.com/watch?v=2lAe1cqCOXo,截图如下:

我们可以直接使用命令下载:

pytube https://www.youtube.com/watch?v=2lAe1cqCOXo

很快视频就能被下载下来了:

Loading video...
YouTube Rewind 2019 For the Record  YouTubeRewind.mp4 | 83 MB
 ↳ |█████████                                   | 21.4%

同样地,pytube 还能下载播放列表,比如这是一个播放列表 https://www.youtube.com/playlist?list=PLS1QulWo1RIaJECMeUT4LFwJ-ghgoSH6n,截图如下:

使用 pytube 同样可以轻松下载:

pytube https://www.youtube.com/playlist?list=PLS1QulWo1RIaJECMeUT4LFwJ-ghgoSH6n

它可以解析播放列表,然后一个个下载下来:

Loading playlist...
Python Tutorial for Beginners 1 - Getting Started and Installing Python (For Absolute Beginners).mp4 | 63 MB
 ↳ |████████████████████████████████████████████| 100.0%
Python Tutorial for Beginners 2 - Numbers and Math in Python.mp4 | 11 MB
 ↳ |████████████████████████████████████████████| 100.0%
Python Tutorial for Beginners 3 - Variables and Inputs.mp4 | 15 MB
 ↳ |████████████████████████████████████████████| 100.0%
Python Tutorial for Beginners 4 - Built-in Modules and Functions.mp4 | 16 MB
 ↳ |████████████████████████████████████████████| 100.0%
Python Tutorial for Beginners 5 - Save and Run Python files py.mp4 | 37 MB
 ↳ |████████████████████████████████████████████| 100.0%
Python Tutorial for Beginners 6 - Strings.mp4 | 78 MB
 ↳ |███████████████████████████████████         | 79.6%

当然除了默认的命令配置,还可以支持查看 list,查看字幕,筛选语言等等,具体的命令如下:

usage: pytube [-h] [--version] [--itag ITAG] [-r RESOLUTION] [-l] [-v]
              [--logfile LOGFILE] [--build-playback-report] [-c CAPTION_CODE]
              [-lc] [-t TARGET] [-a [AUDIO]] [-f [FFMPEG]]
              [url]

Command line application to download youtube videos.

positional arguments:
  url                   The YouTube /watch or /playlist url

optional arguments:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  --itag ITAG           The itag for the desired stream
  -r RESOLUTION, --resolution RESOLUTION
                        The resolution for the desired stream
  -l, --list            The list option causes pytube cli to return a list of
                        streams available to download
  -v, --verbose         Verbosity level, use up to 4 to increase logging -vvvv
  --logfile LOGFILE     logging debug and error messages into a log file
  --build-playback-report
                        Save the html and js to disk
  -c CAPTION_CODE, --caption-code CAPTION_CODE
                        Download srt captions for given language code. Prints
                        available language codes if no argument given
  -lc, --list-captions  List available caption codes for a video
  -t TARGET, --target TARGET
                        The output directory for the downloaded stream.
                        Default is current working directory
  -a [AUDIO], --audio [AUDIO]
                        Download the audio for a given URL at the highest
                        bitrate availableDefaults to mp4 format if none is
                        specified
  -f [FFMPEG], --ffmpeg [FFMPEG]
                        Downloads the audio and video stream for resolution
                        providedIf no resolution is provided, downloads the
                        best resolutionRuns the command line program ffmpeg to
                        combine the audio and video

更多详细的说明可以参考官方文档:https://python-pytube.readthedocs.io/en/latest/user/cli.html

代码使用

当然除了这些,pytube 还支持以 Python 编程的方式来进行下载,同时提供了便捷的链式操作,比如这段代码:

>>> from pytube import YouTube
>>> YouTube('https://youtu.be/2lAe1cqCOXo').streams.first().download()
>>> yt = YouTube('http://youtube.com/watch?v=2lAe1cqCOXo')
>>> yt.streams
... .filter(progressive=True, file_extension='mp4')
... .order_by('resolution')
... .desc()
... .first()
... .download()

这里大家可以看到,要使用 pytube,只需要导入其中的 YouTube 这个类,然后传入 URL 声明 YouTube 对象就好了。接着我们可以直接调用其 streams 方法获取所有的视频源,然后可以通过 first 或者 filter 或者 order 等进行排序或筛选等处理,然后最后调用 download 方法就可以执行下载了。

下面我们来剖析一下具体是怎么回事。

首先我们来声明一下 YouTube 对象:

>>> from pytube import YouTube
>>> yt = YouTube('https://youtu.be/2lAe1cqCOXo')
>>> yt
<pytube.__main__.YouTube object at 0x7f88901e9890>

然后看看 streams 是什么:

>>> yt.streams
[<Stream: itag="18" mime_type="video/mp4" res="360p" fps="24fps" vcodec="avc1.42001E" acodec="mp4a.40.2" progressive="True" type="video">, <Stream: itag="22" mime_type="video/mp4" res="720p" fps="24fps" vcodec="avc1.64001F" acodec="mp4a.40.2" progressive="True" type="video">, <Stream: itag="137" mime_type="video/mp4" res="1080p" fps="24fps" vcodec="avc1.640028" progressive="False" type="video">, <Stream: itag="248" mime_type="video/webm" res="1080p" fps="24fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="399" mime_type="video/mp4" res="1080p" fps="24fps" vcodec="av01.0.08M.08" progressive="False" type="video">, <Stream: itag="136" mime_type="video/mp4" res="720p" fps="24fps" vcodec="avc1.4d401f" progressive="False" type="video">, <Stream: itag="247" mime_type="video/webm" res="720p" fps="24fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="398" mime_type="video/mp4" res="720p" fps="24fps" vcodec="av01.0.05M.08" progressive="False" type="video">, <Stream: itag="135" mime_type="video/mp4" res="480p" fps="24fps" vcodec="avc1.4d401e" progressive="False" type="video">, <Stream: itag="244" mime_type="video/webm" res="480p" fps="24fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="397" mime_type="video/mp4" res="480p" fps="24fps" vcodec="av01.0.04M.08" progressive="False" type="video">, <Stream: itag="134" mime_type="video/mp4" res="360p" fps="24fps" vcodec="avc1.4d401e" progressive="False" type="video">, <Stream: itag="243" mime_type="video/webm" res="360p" fps="24fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="396" mime_type="video/mp4" res="360p" fps="24fps" vcodec="av01.0.01M.08" progressive="False" type="video">, <Stream: itag="133" mime_type="video/mp4" res="240p" fps="24fps" vcodec="avc1.4d4015" progressive="False" type="video">, <Stream: itag="242" mime_type="video/webm" res="240p" fps="24fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="395" mime_type="video/mp4" res="240p" fps="24fps" vcodec="av01.0.00M.08" progressive="False" type="video">, <Stream: itag="160" mime_type="video/mp4" res="144p" fps="24fps" vcodec="avc1.4d400c" progressive="False" type="video">, <Stream: itag="278" mime_type="video/webm" res="144p" fps="24fps" vcodec="vp9" progressive="False" type="video">, <Stream: itag="394" mime_type="video/mp4" res="144p" fps="24fps" vcodec="av01.0.00M.08" progressive="False" type="video">, <Stream: itag="140" mime_type="audio/mp4" abr="128kbps" acodec="mp4a.40.2" progressive="False" type="audio">, <Stream: itag="249" mime_type="audio/webm" abr="50kbps" acodec="opus" progressive="False" type="audio">, <Stream: itag="250" mime_type="audio/webm" abr="70kbps" acodec="opus" progressive="False" type="audio">, <Stream: itag="251" mime_type="audio/webm" abr="160kbps" acodec="opus" progressive="False" type="audio">]
>> type(yt.streams)
<class 'pytube.query.StreamQuery'>

可以看到这里 streams 是一个 StreamQuery 对象,然后输出出来看起来像是一个列表,其中包含了一个个 stream 对象。

所以,StreamQuery 就是我们需要重点关注的对象了。

比如接下来我们使用 filter 或者 order_by 方法进行处理:

>>> type(yt.streams.filter(file_extension='mp4'))
<class 'pytube.query.StreamQuery'>

可以看到它依然还是一个 StreamQuery 对象。

然后根据分辨率进行排序:

>>> type(yt.streams.filter(file_extension='mp4').order_by('resolution'))
<class 'pytube.query.StreamQuery'>

还是一样,返回的还是 StreamQuery 对象。

这下明白为什么它可以进行链式操作了吧,因为每次 filter 或者 order_by 对象返回的依然还是 StreamQuery 对象,依然还是可以调用对应的方法的。

不过也不是每一个都是支持链式操作的,比如接下来我们对 StreamQuery 对象调用 first 方法:

>>> yt.streams.first()
<Stream: itag="18" mime_type="video/mp4" res="360p" fps="24fps" vcodec="avc1.42001E" acodec="mp4a.40.2" progressive="True" type="video">
>>> type(yt.streams.first())
<class 'pytube.streams.Stream'>

看到这里返回的就是单个 Stream 了。

对于 Stream 对象,我们最常用的就是 download 方法了。

yt.streams.first().download()

调用完毕之后,视频就会下载在运行目录中。

以上我们就介绍了利用命令行和代码进行视频下载的过程。

更多

当然这个库还有很多强大的功能,都在文档 https://python-pytube.readthedocs.io/en/latest/ 写得很清楚了,这里带大家稍微看下。

比如获取视频的属性:

>>> yt.title
YouTube Rewind 2019: For the Record | #YouTubeRewind

获取视频的缩略图:

>>> yt.thumbnail_url
'https://i.ytimg.com/vi/2lAe1cqCOXo/maxresdefault.jpg'

在初始化的时候设置处理方法或者设置代理:

>>> yt = YouTube(
  'http://youtube.com/watch?v=2lAe1cqCOXo',
  on_progress_callback=progress_func,
  on_complete_callback=complete_func,
  proxies=my_proxies
)

关于 filter 的一些用法,可以参考 https://python-pytube.readthedocs.io/en/latest/user/streams.html#filtering-streams,比如说过滤只保留有音频的流媒体:

>>> yt.streams.filter(only_audio=True)
[<Stream: itag="140" mime_type="audio/mp4" abr="128kbps" acodec="mp4a.40.2" progressive="False" type="audio">,
<Stream: itag="249" mime_type="audio/webm" abr="50kbps" acodec="opus" progressive="False" type="audio">,
<Stream: itag="250" mime_type="audio/webm" abr="70kbps" acodec="opus" progressive="False" type="audio">,
<Stream: itag="251" mime_type="audio/webm" abr="160kbps" acodec="opus" progressive="False" type="audio">]

保留 mp4 后缀的视频:

>>> yt.streams.filter(file_extension='mp4')
[<Stream: itag="18" mime_type="video/mp4" res="360p" fps="30fps" vcodec="avc1.42001E" acodec="mp4a.40.2" progressive="True" type="video">,
<Stream: itag="22" mime_type="video/mp4" res="720p" fps="30fps" vcodec="avc1.64001F" acodec="mp4a.40.2" progressive="True" type="video">,
<Stream: itag="137" mime_type="video/mp4" res="1080p" fps="30fps" vcodec="avc1.640028" progressive="False" type="video">,
...
<Stream: itag="394" mime_type="video/mp4" res="None" fps="30fps" vcodec="av01.0.00M.08" progressive="False" type="video">,
<Stream: itag="140" mime_type="audio/mp4" abr="128kbps" acodec="mp4a.40.2" progressive="False" type="audio">]

比如获取字幕:

>>> yt = YouTube('http://youtube.com/watch?v=2lAe1cqCOXo')
>>> yt.captions
{'ar': <Caption lang="Arabic" code="ar">, 'zh-HK': <Caption lang="Chinese (Hong Kong)" code="zh-HK">, 'zh-TW': <Caption lang="Chinese (Taiwan)" code="zh-TW">, ...

这里各国语言的字幕几乎都有。

另外还可以把字幕打印出来,比如输出 srt 格式:

>>> caption = yt.captions.get_by_language_code('en')
>>> print(caption.generate_srt_captions())
1
00:00:10,200 --> 00:00:11,140
K-pop!

2
00:00:13,400 --> 00:00:16,200
That is so awkward to watch.
...

对于播放列表的处理,比如新建 Playlist 对象,然后取出每一个视频的第一个视频流并下载:

>>> from pytube import Playlist
>>> p = Playlist('https://www.youtube.com/playlist?list=PLS1QulWo1RIaJECMeUT4LFwJ-ghgoSH6n')
>>> for video in p.videos:
>>>     video.streams.first().download()

另外还有一些异常处理机制:

>>> from pytube import Playlist, YouTube
>>> playlist_url = 'https://youtube.com/playlist?list=special_playlist_id'
>>> p = Playlist(playlist_url)
>>> for url in p.video_urls:
...     try:
...         yt = YouTube(url)
...     except VideoUnavailable:
...         print(f'Video {url} is unavaialable, skipping.')
...     else:
...         print(f'Downloading video: {url}')
...         yt.streams.first().download()

总之,使用这个库,我们不仅可以使用命令行方便地下载 Youtube 视频和播放列表,还可以使用代码灵活地控制,一举两得!

作者:崔庆才
排版:崔庆才


关注我,关注我,求关注,求关注~

往期精彩文章:


阔别2020  |  我的年度总结


深入理解Java线程池


Github Action 快速上手指南


一枚程序猿的MacBook M1使用体验


废弃fastjson!大型项目迁移Gson保姆级实战



好文和朋友一起看~
浏览 267
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报