下载 Youtube 影片
这篇文章会介绍使用 Python 的 pytube 第三方函数库,输入 Youtube 网址后就会自动下载为影片档 mp4,单纯下载为声音档 mp3,甚至可以进一步下载有字幕影片的字幕,储存为 srt 或 txt。
快速导览:
本篇使用的 Python 版本为 3.7.12,所有范例可使用 Google Colab 实作,不用安装任何软件 ( 参考:使用 Google Colab )
安装 pytube
输入下列指令,安装 pytube ( 根据个人环境使用 pip、pip3 )
!pip install pytube
注意,原本 pytube 可以正常使用,但因为 Youtube API 更新安全性原则,所以原本程序码都需要加入下面这段 ssl,不然就会抛出错误消息:
import ssl
ssl._create_default_https_context = ssl._create_stdlib_context
读取 Youtube 影片信息
参考“pytube - YouTube Object”说明,使用 pytube 读取 Youtube 网址后,就能取得关于该影片的各种信息,下方的例子会取出标题、作者、作者频道网址、影片缩图网址、影片长度、观看次数等信息。
import ssl
ssl._create_default_https_context = ssl._create_stdlib_context
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 ssl
ssl._create_default_https_context = ssl._create_stdlib_context
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 ssl
ssl._create_default_https_context = ssl._create_stdlib_context
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())
透过宣告 yt 时的参数 on_progress_callback,可以回传目前下载影片的进度 ( 可显示下载进度 )。
import ssl
ssl._create_default_https_context = ssl._create_stdlib_context
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!')
如果有出现“pytube.exceptions.AgeRestrictedError:XXXXXXXXX is age restricted, and can't be accessed without logging in.”的错误情况,这可能是 pytube 的 bug 造成,参考“stackoverflow”的解决方法,在开头加上下面这段程序码就能解决。
from pytube.innertube import _default_clients
_default_clients["ANDROID_MUSIC"] = _default_clients["ANDROID_CREATOR"]
下载 Youtube 影片为 mp3
使用 get_audio_only() 方法,能单独取出 Youtube 的音轨储存为 mp3 文件 ( 默认为 mp4,存档时改档名为 mp3 就会变成 mp3 )。
import ssl
ssl._create_default_https_context = ssl._create_stdlib_context
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。
import ssl
ssl._create_default_https_context = ssl._create_stdlib_context
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!')
参考数据
微信扫码关注
抖音扫码关注