最后来看progress_hooks这个参数,给这个参数的值是个函数列表:
ydl_opts = {
……
'progress_hooks': [my_hook],
# my_hook是钩子函数,传入函数的是一个视频信息的字典
……
}
函数my_hook()用作钩子函数,启动下载进程时被调用。下载进程启动后可以有三个状态:正在下载"downloading"、出错 "error"、 下载完毕"finished"。定义的钩子函数可以根据下载状态输出相应信息,比如my_hook()规定如果下载成功,则显示视频信息:
import youtube_dl
# 定义视频下载后的存放位置和视频链接
destPath = '/Users/PythonABC/Documents/tmp/'
# 音频文件存放的目标字串
videoPage = 'https://www.youtube.com/watch?v=FLhzB_DJQb4'
# 定义钩子函数
def my_hook(d):
if d['status'] == 'finished': # 如果视频下载完毕
print('\n下载完毕后再输出视频信息:')
for key, value in d.items():
print("{}: {}".format(key, value))
# 定义下载选项
ydl_opts = {
'outtmpl': destPath+'%(title)s.%(ext)s',
'format': 'best',
'progress_hooks': [my_hook], # my_hook是钩子函数
}
ydl = youtube_dl.YoutubeDL(ydl_opts) # 生成下载对象
ydl.download([videoPage]) # 下载视频
视频下载成功的提示之后还会出现:
图23.5 下载完毕后启动输出钩子函数my_hook()里指定的信息
因为下载进程中钩子函数不断被调用,视频下载成功满足if语句设定的条件,按照设定输出视频信息字典的健值和值。
如果生成下载对象ydl后,调用ydl的方法函数extract_info()抽取信息时,参数download设为false:
result = ydl.extract_info(
videoPage,
download=False, # 不下载只是抽取信息
)
因为只提取视频信息不下载视频,所以如果前面的代码改为:
……
def my_hook(d):
if d['status'] == 'finished': # 如果视频进程完成
print('\n下载完毕后再输出视频信息:')
for key, value in d.items():
print("{}: {}".format(key, value))
ydl_opts = { # 定义下载选项
'outtmpl': destPath+'%(title)s.%(ext)s',
'format': 'best',
'progress_hooks': [my_hook], # my_hook是钩子函数
}
ydl = youtube_dl.YoutubeDL(ydl_opts) # 生成下载对象
result = ydl.extract_info(
videoPage, # 视频链接
download=False, # 不下载只是抽取信息
)
if 'entries' in result:
downloadVideos = result['entries']
for video in downloadVideos:
print("标题:{}\n ".format(video['title']))
else:
downloadVideo = result
print('一枝独秀:{}'.format(downloadVideo['title']))
运行结果:
图23.6 下载进程没启动,参数'progress_hooks指定的钩子函数没运行
my_hook()没有被调用,因为下载进程根本没有被启动,跟下载进程关联的钩子函数自然没有机会被运行。