iT邦幫忙

2022 iThome 鐵人賽

DAY 26
0
Software Development

學 Python 到底可以幹麻勒?系列 第 26

( Day 26 ) 下載 Youtube 影片 ( mp4、mp3、字幕 )

  • 分享至 

  • xImage
  •  

這篇文章會介紹使用 Python 的 pytube 第三方函式庫,輸入 Youtube 網址後就會自動下載為影片檔 mp4,單純下載為聲音檔 mp3,甚至可以進一步下載有字幕影片的字幕,儲存為 srt 或 txt,最後還會讀取 Youtube 清單內容,並將清單裡的所有影片下載為 mp4。。

原文參考:下載 Youtube 影片 ( mp4、mp3、字幕 )下載 Youtube 清單中所有影片

本篇使用的 Python 版本為 3.7.12,所有範例可使用 Google Colab 實作,不用安裝任何軟體 ( 參考:使用 Google Colab )

https://ithelp.ithome.com.tw/upload/images/20220926/20091306JFm0snHw2Q.jpg

安裝 pytube

輸入下列指令,安裝 pytube ( 根據個人環境使用 pip、pip3 )

!pip install pytube

讀取 Youtube 影片資訊

參考「pytube - YouTube Object」說明,使用 pytube 讀取 Youtube 網址後,就能取得關於該影片的各種資訊,下方的例子會取出標題、作者、作者頻道網址、影片縮圖網址、影片長度、觀看次數等資訊。

from pytube import YouTube
yt = YouTube('https://www.youtube.com/watch?v=R93ce4FZGbc')   # baby shark 的音樂
print(yt.title)           # 影片標題
print(yt.length)          # 影片長度 ( 秒 )
print(yt.author)          # 影片作者
print(yt.channel_url)     # 影片作者頻道網址
print(yt.thumbnail_url)   # 影片縮圖網址
print(yt.views)           # 影片觀看數

下載 Youtube 影片為 mp4

參考「pytube - StreamQuery Object」說明,可以使用 get_highest_resolution() 方法,下載最高畫質的影片

import os
os.chdir('/content/drive/MyDrive/Colab Notebooks')  # 使用 Colab 要換路徑使用

from pytube import YouTube
yt = YouTube('https://www.youtube.com/watch?v=R93ce4FZGbc')
print('download...')
yt.streams.filter().get_highest_resolution().download(filename='baby_shart.mp4')
# 下載最高畫質影片,如果沒有設定 filename,則以原本影片的 title 作為檔名
print('ok!')

如果要指定下載影片的畫質,可以透過 get_by_resolution() 方法,填入像是 720p、480p、360p、240p 等標準影像解析度格式,就能下載對應的畫質 ( 注意,畫質會必須取決於該影片實際大小是否支援 )

import os
os.chdir('/content/drive/MyDrive/Colab Notebooks')  # 使用 Colab 要換路徑使用

from pytube import YouTube
yt = YouTube('https://www.youtube.com/watch?v=R93ce4FZGbc')
print('download...')
yt.streams.filter().get_by_resolution('360p').download(filename='oxxostudio_360p.mp4')
# 下載 480p 的影片畫質
print('ok!')

如果想知道影片支援哪些畫質,可印出 streams.all() 來查看。

from pytube import YouTube
yt = YouTube('https://www.youtube.com/watch?v=R93ce4FZGbc')
print(yt.streams.all())

Python 教學 - 下載 Youtube 影片 ( mp4、mp3、字幕 )

透過宣告 yt 時的參數 on_progress_callback,可以回傳目前下載影片的進度 ( 可顯示下載進度 )。

from pytube import YouTube

def onProgress(stream, chunk, remains):
    total = stream.filesize                     # 取得完整尺寸
    percent = (total-remains) / total * 100     # 減去剩餘尺寸 ( 剩餘尺寸會抓取存取的檔案大小 )
    print(f'下載中… {percent:05.2f}', end='\r')  # 顯示進度,\r 表示不換行,在同一行更新

print('download...')
yt = YouTube('https://www.youtube.com/watch?v=R93ce4FZGbc', on_progress_callback=onProgress)
yt.streams.filter().get_highest_resolution().download(filename='oxxostudio.mp4')
# on_progress_callback 參數等於 onProgress 函式
print()
print('ok!')

下載 Youtube 影片為 mp3

使用 get_audio_only() 方法,能單獨取出 Youtube 的音軌儲存為 mp3 檔案 ( 預設為 mp4,存檔時改檔名為 mp3 就會變成 mp3 )。

import os
os.chdir('/content/drive/MyDrive/Colab Notebooks')  # 使用 Colab 要換路徑使用

from pytube import YouTube
yt = YouTube('https://www.youtube.com/watch?v=R93ce4FZGbc')
print('download...')
yt.streams.filter().get_audio_only().download(filename='oxxostudio.mp3')
# 儲存為 mp3
print('ok!')

下載 Youtube 影片字幕為 srt 或 txt

使用 yt.captions 方法,可以取得該 Youtube 影片全部的字幕 ( 如果是 auto 自動產生,字幕語系前方會出現 a. 標示 ),取得字幕後,透過 xml_captions 就能將指定語系的字幕轉換成 xml 檔案

由於 pytube 內建的 generate_srt_captions() 方法會發生 KeyError: 'start' 錯誤,因此直接使用 BeautifulSoup 套件讀取 xml 的內容,再透過數學計算和字串格式化的方法,轉換成字幕檔案格式,最後輸出成為 srt 或 txt。

參考:BeautifulSoupdivmod(x, y)字串格式化

import os
os.chdir('/content/drive/MyDrive/Colab Notebooks')  # 使用 Colab 要換路徑使用

from pytube import YouTube
from bs4 import BeautifulSoup

yt = YouTube('https://www.youtube.com/watch?v=R93ce4FZGbc')
print(yt.captions)                                 # 取得所有語系
caption = yt.captions.get_by_language_code('en')   # 取得英文語系
xml = caption.xml_captions                         # 將語系轉換成 xml
#print(xml)

def xml2srt(text):
    soup = BeautifulSoup(text)                     # 使用 BeautifulSoup 轉換 xml
    ps = soup.findAll('p')                         # 取出所有 p tag 內容

    output = ''                                    # 輸出的內容
    num = 0                                        # 每段字幕編號
    for i, p in enumerate(ps):
        try:
            a = p['a']                             # 如果是自動字幕,濾掉有 a 屬性的 p tag
        except:
            try:
                num = num + 1                      # 每段字幕編號加 1
                text = p.text                      # 取出每段文字
                t = int(p['t'])                    # 開始時間
                d = int(p['d'])                    # 持續時間

                h, tm = divmod(t,(60*60*1000))     # 轉換取得小時、剩下的毫秒數
                m, ts = divmod(tm,(60*1000))       # 轉換取得分鐘、剩下的毫秒數
                s, ms = divmod(ts,1000)            # 轉換取得秒數、毫秒

                t2 = t+d                           # 根據持續時間,計算結束時間
                if t2 > int(ps[i+1]['t']): t2 = int(ps[i+1]['t'])  # 如果時間算出來比下一段長,採用下一段的時間
                h2, tm = divmod(t2,(60*60*1000))   # 轉換取得小時、剩下的毫秒數
                m2, ts = divmod(tm,(60*1000))      # 轉換取得分鐘、剩下的毫秒數
                s2, ms2 = divmod(ts,1000)          # 轉換取得秒數、毫秒


                output = output + str(num) + '\n'  # 產生輸出的檔案,\n 表示換行
                output = output + f'{h:02d}:{m:02d}:{s:02d},{ms:03d} --> {h2:02d}:{m2:02d}:{s2:02d},{ms2:03d}' + '\n'
                output = output + text + '\n'
                output = output + '\n'
            except:
                pass

    return output

#print(xml2srt(xml))
with open('oxxostudio.srt','w') as f1:
    f1.write(xml2srt(xml))    # 儲存為 srt

print('ok!')

Python 教學 - 下載 Youtube 影片 ( mp4、mp3、字幕 )

讀取 Youtube 清單資訊

參考「pytube - Using Playlists」說明,使用 pytube 讀取 Youtube 清單網址後,就能將該影片清單的所有影片網址,輸出成為串列。

import os
os.chdir('/content/drive/MyDrive/Colab Notebooks')  # 使用 Colab 要換路徑使用

from pytube import Playlist
playlist = Playlist('https://www.youtube.com/watch?v=mOPRaLPh-YU&list=PL9ACDjBMkp9wViVmgpYweGkNqh62pHspF')
# 讀取影片清單
print(playlist.video_urls)   # 印出清單結果
'''
['https://www.youtube.com/watch?v=mOPRaLPh-YU',
 'https://www.youtube.com/watch?v=wARhTJH1fJI',
 'https://www.youtube.com/watch?v=WLjePGUCRqc']
'''

下載 Youtube 清單中所有影片為 mp4

讀取到影片清單中所有影片網址後,透過 for 迴圈,就能將所有影片下載為 mp4。

import os
os.chdir('/content/drive/MyDrive/Colab Notebooks')  # 使用 Colab 要換路徑使用

from pytube import Playlist, YouTube
playlist = Playlist('https://www.youtube.com/watch?v=mOPRaLPh-YU&list=PL9ACDjBMkp9wViVmgpYweGkNqh62pHspF')
print('download...')
for i in playlist.video_urls:
    print(i)
    yt = YouTube(i)                                           # 讀取影片
    yt.streams.filter().get_highest_resolution().download()   # 下載為最高畫質影片
print('ok!')

參考資料

更多 Python 教學

大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我已經寫了超過 400 篇 Python 的教學,有興趣可以參考下方連結呦~ ^_^


上一篇
( Day 25 ) 影片截圖、圖片轉影片
下一篇
( Day 27 ) 發送 LINE Notify 通知
系列文
學 Python 到底可以幹麻勒?41
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言