一款超好用的Python油管視頻下載工具
閱讀本文大概需要 3 分鐘。
在這里介紹一個工具,使用它我們可以非常方便地使用 Python 下載 Youtube 的視頻,叫做 pytube。
利用它我們可以實現(xiàn)如下功能:
支持 progresive 和 DASH 視頻流的下載 支持下載完整的播放列表 可以處理下載進行中和下載完成的回調 提供命令行直接執(zhí)行下載 支持下載字幕 支持將字幕輸出為 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 方法就可以執(zhí)行下載了。
下面我們來剖析一下具體是怎么回事。
首先我們來聲明一下 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 對象。
然后根據(jù)分辨率進行排序:
>>> 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 視頻和播放列表,還可以使用代碼靈活地控制,一舉兩得!
往期精彩文章:
廢棄fastjson!大型項目遷移Gson保姆級實戰(zhàn)


