Last Updated on 2021-05-07 by Clay
現代人的各種電子娛樂很大程度上都離不開 YouTube,不論是追劇、學習、聽音樂 …… 說 YouTube 是現代人最重要的網站也不為過。
有時候,我們會想要從 YouTube 上下載影片或是音樂。當然,這件事情本身很有可能觸犯智慧財產權,所以今天,我會紀錄如何透過 Python 中的 pytube 套件來做到『下載』這個動作,不過包含我本人在內,我們的範例程式僅限於教學與學術研究、絕非商業用途。
當然,下載後的影片也要於一定時間內刪除才行。
舉個非商業用途的下載例子:或許學校老師們會想要藉由 YouTube 影片向班上同學們授課,但是總難免會碰上網路訊號不好的時候,而在課堂上等待影片的播放難免浪費時間。
那麼,除了使用網路上各種 YouTube 下載網頁之外,或許也可以考慮使用 Python 來完成下載影片的工作。當然如果你是撰寫程式來下載,那麼你當然可以批量一口氣下載多部影片。
正如前述,本文介紹的是如何使用 Python 中著名的 pytube 套件。更詳細的資訊可以去開發者的 Github 看看: https://github.com/nficano/pytube
本篇心得教學分成兩階段:
- 下載影片檔
- (Optional)使用 moviepy 套件將 mp4 轉成 mp3
使用 pytube 下載 YouTube 的影片
首先,我們需要先安裝 pytube 套件:
pip3 install pytube
在我使用的現在,pytube 的最新版本是 9.5.3。但在我之前嘗試的時候,我是失敗的:我沒辦法順利地使用 9.5.2 的 pytube 下載 YouTube 網站上的影音檔。
(2021/05/07 更新)距離撰寫這篇文章已經過去了很長一段時間,為了因應 YouTube 網站的改版,pytube 套件自然也迭代了許多新的版本,本次文章更新最重要的便是修正了自定義的『下載進度條』相關的程式碼。目前 pytube 最新版本為 10.7.2。
在使用這個套件前,有個簡單的觀念要說明:YouTube 對於這種使用爬蟲技術來下載影片的方法一直都在換著花樣阻擋,必須要隨時更新我們使用的套件版本才行。
以下我們拿一個影片來示範: https://www.youtube.com/watch?v=JwBXgJeqeOs
以上這是個由日本 Falcom 公司所製作的遊戲《空之軌跡 3rd》當中的 op(開場曲),而這裡我們透過 pytube 套件來下載這部影片。
# -*- coding: utf-8 -*- from pytube import YouTube url = 'https://www.youtube.com/watch?v=JwBXgJeqeOs' YouTube(url).streams.first().download()
這樣稍等一會兒,我們就會看到影片存放在我們當前資料夾底下了。
(2021/05/07 更新)如果遇到以下報錯(比方說 MacOS):
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:847)>
則可以在程式開頭加上:
import ssl ssl._create_default_https_context = ssl._create_unverified_context
比較詳細的解釋紀錄在這篇:[已解決] urllib.error.URLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
進度條
但這時候我們一定會很疑惑,咦?沒有任何進度條出現欸?這樣如果需要一次下載較大的影片,不就不知道現在下載進度了嗎?
這倒不用擔心,在 pytube 的 YouTube
類別中,存在著 on_progress_callback
callback 參數,可以讓我們撰寫自己的進度條。
就像我這樣的配置:(已經不再適用)
# -*- coding: utf-8 -*- from pytube import YouTube def progress(stream, chunk, file_handle, bytes_remaining): contentSize = video.filesize size = contentSize - bytes_remaining print('\r' + '[Download progress]:[%s%s]%.2f%%;' % ( '█' * int(size*20/contentSize), ' '*(20-int(size*20/contentSize)), float(size/contentSize*100)), end='') url = 'https://www.youtube.com/watch?v=JwBXgJeqeOs' yt = YouTube(url, on_progress_callback=progress) video = yt.streams.first() video.download()
(2021/05/07 更新)目前自定義的進度條程式規格應如下:
# coding: utf-8 from pytube import YouTube def progress(chunk, file_handle, bytes_remaining): contentSize = video.filesize size = contentSize - bytes_remaining print('\r' + '[Download progress]:[%s%s]%.2f%%;' % ( '█' * int(size*20/contentSize), ' '*(20-int(size*20/contentSize)), float(size/contentSize*100)), end='') if __name__ == "__main__": # Init url = 'https://www.youtube.com/watch?v=JwBXgJeqeOs' yt = YouTube(url, on_progress_callback=progress) video = yt.streams.first() # file_size file_size = video.filesize # Download video.download()
Output:
使用 moviepy 轉換 MP4 成 MP3
將影片檔(mp4)轉成音訊檔(mp3)的程式跟套件有很多,在這裡我直接選擇了 moviepy 套件,因為其程式碼既短又清晰。
首先,我們同樣需要下載 moviepy 套件。
sudo pip3 install moviepy
下載好之後,我們來將剛才下載的檔案轉換成 test.mp3(名稱可以自己取)。
# -*- coding: utf-8 -*- from moviepy.editor import * video = VideoFileClip('Sora no Kiseki the 3rd Evolution [BGM RIP] - Cry for your Eternity.mp4') video.audio.write_audiofile('test.mp3')
Output:
MoviePy - Writing audio in test.mp3
MoviePy - Done.
這樣一來,我們的轉換就完成了。