youtube-dl 是一个通过命令行下载视频的工具,其不仅支持 youtube 网站的视频下载,还支持上百个不同的视频网站。用户可以在官方网站上下载 Windows(exe) 和 Linux(tar.gz) 的版本,之后解压并使用对应的命令即可。
对于部分需要使用 youtube-dl 进行开发并且调用其接口为其他功能服务的用户而言,可以在 Github 上找到源码并且进行二次开发,也可以直接调用其 python 接口。关于如何在命令行直接使用打包好的 youtube-dl 工具有许多的文档进行介绍,这篇文章主要是对 youtube-dl 提供的一些接口参数及其功能进行说明,如有错误或不严谨的地方欢迎批评指正。
Linux/Mac 用户可以直接用 pip 安装 youtube-dl 的最新版本:
sudo pip install youtube-dl
sudo -H pip install --upgrade youtube-dl
或 ( Homebrew )
brew install youtube-dl
注:youtube-dl 的库版本更新很快,一定要将 youtube-dl 升级到最新版本,因为其解析器很可能会随着版本更新发生变动,导致解析结果不正确或者程序崩溃 ( 在报错时可以试试更新能不能解决 ) 。
在下载 youtube-dl 源码后,可以看到 /docs/module_guide.rst 是一个简单的接口介绍文档,但只有最简单的三四个 api 的使用说明,本文会在这个的基础上加上作者在使用过程中自己用到的接口和参数。
初始化接口
在进行下载之前,youtube-dl 需要初始化一个可以看作是下载器的类,可以在初始化时指定之后使用的解析器、解析格式、是否需要使用代理等。
文档中只给出了使用 YoutubeDL() 进行初始化的方式,但这个函数还可以有一个字典形式的输入参数,如第2行所示。
>>> from youtube_dl import YoutubeDL
>>> opts = { 'outtmpl': u'%(id)s.%(ext)s' , 'ignoreerrors': True, 'proxy' : PROXY_URL}
>>> ydl = YoutubeDL(opts)
>>> ydl.add_default_info_extractors()
这个参数决定了在之后的下载过程中下载器将会遵循的某些规则,在源码中的 /youtube-dl/YoutubeDL.py 文件里有详细的注释说明,这里只将常用的几个参数列出来以供参考。
参数名称 | 参数类型 | 参数含义 |
---|---|---|
outtmpl | string | 下载视频文件的文件名格式 |
ignoreerrors | bool | 是否忽略下载过程中的错误(不忽略则遇到错误就程序停止) |
username | string | 用户名 (如果当前网站需要登录) |
password | string | 密码 (同用户名) |
nocheckcertificate | bool | 是否验证SSL证书 (对于某些网站有用) |
proxy | string | 指定代理 |
extract_flat | string | 如果指定 ‘in_playlist’, 则只下载播放列表而不尝试解析视频 |
其实这一部分的第四行代码,add_default_info_extractors 函数是指添加一个默认的提取器,但实际上这个提取器用户是可以自定义的,但作者暂时没有用到这个功能,所以这里不会细讲,但对于一些 youtube-dl 本身不支持的网站,根据其框架再编写一个新的提取器,应该可以适应大部分视频网站的需求。
提取视频信息与下载视频
在初始化完毕后,提取信息的接口调用就比较简单了。通过之前创建的下载器对象,调用 extract_info() 函数。
函数有两个参数,第一个是 url,如果是视频 url,会直接解析视频信息,而如果是播放列表类型的 url,则会先解析播放列表,再去解析播放列表中的每个视频 (这个过程中是不可打断的,一旦打断会从头开始)。
第二个参数是一个布尔值,True 代表同时解析视频详细信息和下载视频,False则不下载视频,只解析视频信息。
而这个函数的返回值是一个字典类型的数据,里面包含了视频相关的信息,比如清晰度、上传者、上传时间等等,要了解每一个参数的意义可以看这里。
>>> info = ydl.extract_info('http://www.youtube.com/watch?v=BaW_jenozKc', download=False)
[youtube] Setting language
[youtube] BaW_jenozKc: Downloading webpage
[youtube] BaW_jenozKc: Downloading video info webpage
[youtube] BaW_jenozKc: Extracting video information
>>> info['title']
'youtube-dl test video "\'/\\ä↭'
>>> info['height'], info['width']
(720, 1280)
提取播放列表信息
官方文档中给出的提取播放列表 (playlist) 的方法如下所示,只是将 extract_info 的第二个参数改为 False,但作者在实际开发过程中发现,这样的方式有很大的弊端。
在整个 extract_info 函数执行的过程中是不允许被打断的, youtube-dl 本身也没有实现断点续传功能,这就导致一旦 playlist 过长、视频太大,程序很可能就因为网络波动而导致前面的工作白费。
>>> playlist = ydl.extract_info('http://www.ted.com/playlists/13/open_source_open_world', download=False)
[TED] open_source_open_world: Downloading playlist webpage ...
>>> for video in playlist['entries']:
... print('Video #%d: %s' % (video['playlist_index'], video['title']))
Video #1: How Arduino is open-sourcing imagination
Video #2: The year open data went worldwide
Video #3: Massive-scale online collaboration
因此另一种方案就是先将 playlist 中的所有视频 url 提取出来 ( 只提取url不下载视频速度会很快 ),再逐个的去下载视频,并且配合数据库记录下载进度,能最大程度下规避网络波动带来的风险。其中的关键代码如下。
>>> playlist_ydl_opts = {'extract_flat':'in_playlist', 'ignoreerrors': True, 'nocheckcertificate':True}
>>> playlist_ydl = YoutubeDL(playlist_ydl_opts)
>>> playlist_ydl.add_default_info_extractors()
>>> playlist = playlist_ydl.extract_info(playlist_path, download = False)
>>> if playlist.has_key('entries') and playlist['entries'] != None:
>>> ......
本文为作者原创,转载请注明出处