1, 跑起来

下载 youtube-dl, 配合 launch.json,

# 本文中 himala 是代指,具体见文末的 github repo
"configurations": [
{
"name": "audio",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/youtube_dl",
"console": "integratedTerminal",
"args": ["-F", "http://www.himala.com/61425525/sound/47740352/"]
}
] 复制代码

然后,直接调用 main.py

通过 main.py 文件中,将

if __package__ is None and not hasattr(sys, 'frozen'):
import os.path
path = os.path.realpath(os.path.abspath(__file__))
sys.path.insert(0, os.path.dirname(os.path.dirname(path))) 复制代码

替换为

import os.path
path = os.path.realpath(os.path.abspath(__file__))
sys.path.insert(0, os.path.dirname(os.path.dirname(path)))
复制代码

2, 操作纲要

2.1 , 程序入口, 拿命令行的参数,做事情

__main__.py 文件中,

if __name__ == '__main__':
youtube_dl.main()
复制代码

__init__.py 文件中,走

def main(argv=None):
try:
_real_main(argv)
except DownloadError:
sys.exit(1)
# ...
复制代码

__init__.py 文件中,接着走

def _real_main(argv=None):
# 里面做了一个参数配置
#...
try:
if opts.load_info_filename is not None:
retcode = ydl.download_with_info_file(expand_path(opts.load_info_filename))
else:
retcode = ydl.download(all_urls)
except MaxDownloadsReached:
#...
复制代码

2.2 , YoutubeDL.py 文件中, 拿 url 去下载音视频

class YoutubeDL(object):

   def download(self, url_list):
# ...
for url in url_list:
try:
# It also downloads the videos
res = self.extract_info(
url, force_generic_extractor=self.params.get('force_generic_extractor', False))
except UnavailableVideoError:
# ... 复制代码

此函数中,不但抽出相关信息,还下载网页、音视频

所有的事情,都得到了解决

def extract_info(self, url, download=True, ie_key=None, extra_info={},
process=True, force_generic_extractor=False): if not ie_key and force_generic_extractor:
ie_key = 'Generic' if ie_key:
ies = [self.get_info_extractor(ie_key)]
else:
ies = self._ies for ie in ies:
if not ie.suitable(url):
continue
ie = self.get_info_extractor(ie.ie_key())
# ...
try:
ie_result = ie.extract(url)
# ...
复制代码

上面代码中的 ie, Info Extract

youtube-dl 可以处理很多网站的信息,每一个网站都有对应的 Info Extract 文件

youtube-dl,音视频,都用 video 代指

3,找出 ie

youtube-dl 是怎样,给定一个 url, 找出对应的 IE 的

通过正则,做匹配

youtube-dl 通过正则,实现站点支持的扩展性

3.1 , 上文代码中 self._ies, 的初始化

3.1.1 self._ies 添加

YoutubeDL.py 文件中,

self._ies, 初始化的入口

class YoutubeDL(object):
def __init__(self, params=None, auto_init=True):
# ...
if auto_init:
self.print_debug_header()
self.add_default_info_extractors()
# ...
复制代码

gen_extractor_classes 里面的信息,

添加给 self._ies

    def add_default_info_extractors(self):
"""
Add the InfoExtractors returned by gen_extractors to the end of the list
"""
for ie in gen_extractor_classes():
self.add_info_extractor(ie) def add_info_extractor(self, ie):
"""Add an InfoExtractor object to the end of the list."""
self._ies.append(ie)
# ...
复制代码
3.1.2 self._ies 添加的内容

__init__.py 文件中,

_ALL_CLASSES 添加了 extractor 文件夹下 extractors.py 文件中,引用到的,所有以 IE 结尾的类


#...
except ImportError:
_LAZY_LOADER = False
from .extractors import *
_ALL_CLASSES = [
klass
for name, klass in globals().items()
if name.endswith('IE') and name != 'GenericIE'
]
_ALL_CLASSES.append(GenericIE) def gen_extractor_classes():
return _ALL_CLASSES
复制代码

_ALL_CLASSES, 这个列表的顺序挺重要的,先通过正则匹配到的,

是用到的 IE

3.1.3 , 添加网站

新支持一个网站,建立对应的 IE 文件

extractors.py 文件中,如下添加引用

from .youtube import (
YoutubeIE,
YoutubeChannelIE,
# ...
}
复制代码

3.2, 找出对应的 IE

上文提高的, YoutubeDL.py 文件中,

def extract_info(self, url, download=True, ie_key=None, extra_info={},
process=True, force_generic_extractor=False): # ...
for ie in ies:
if not ie.suitable(url):
continue
ie = self.get_info_extractor(ie.ie_key())
# ... 复制代码

每个 ie 都有一个类方法 def suitable(cls, url):

每个网站的 ie 继承自

common.py 文件中的 class InfoExtractor(object)

class InfoExtractor(object):

    @classmethod
def suitable(cls, url): if '_VALID_URL_RE' not in cls.__dict__:
cls._VALID_URL_RE = re.compile(cls._VALID_URL)
return cls._VALID_URL_RE.match(url) is not None
复制代码

如果该网站的 ie 没实现自己的 suitable,

就用 InfoExtractor 类的 suitable

每个网站的 IE

class XimalayaIE(XimalayaBaseIE):
# 本文中 himala 是代指,具体见文末的 github repo
IE_NAME = 'himala'
IE_DESC = 'himala 网站'
_VALID_URL = r'https?://(?:www\.|m\.)?himala\.com/(?P<uid>[0-9]+)/sound/(?P<id>[0-9]+)'
复制代码

InfoExtractor 类,通过 __dict__ 获取,我们配置的 _VALID_URL 属性,

正则一下,识别出来

4,找出网页信息

上文代码, YoutubeDL.py 文件中,进入 ie , 做事情

def extract_info(self, url, download=True, ie_key=None, extra_info={},
process=True, force_generic_extractor=False): # ...
try:
ie_result = ie.extract(url)
# ...
复制代码

先进入 common.py 文件中,InfoExtractor

    def extract(self, url):
"""Extracts URL information and returns it in list of dicts."""
try:
for _ in range(2):
try:
self.initialize()
ie_result = self._real_extract(url)
# ...
复制代码

再进入实际做事情的类 , himala.py 文件中

下载网页,正则抽取信息

# 本文中 himala 是代指,具体见文末的 github repo
class HimalaIE(InfoExtractor):
def _real_extract(self, url):
#...
webpage = self._download_webpage(url, audio_id,
note='Download sound page for %s' % audio_id,
errnote='Unable to get sound page')
# ...
if is_m:
audio_description = self._html_search_regex(r'(?s)<section\s+class=["\']content[^>]+>(.+?)</section>',
webpage, 'audio_description', fatal=False)
else:
audio_description = self._html_search_regex(r'(?s)<div\s+class=["\']rich_intro[^>]*>(.+?</article>)',
webpage, 'audio_description', fatal=False)
# ... 复制代码

5,应用

Himala 网站中,一个主播的作品很多,

没有该主播内部的作品搜索功能

通过简单扩展 youtube-dl ,可以实现找出

该主播有多少期 fallout 节目,及对应在哪一页

代码很简单,见

github repo

作者:邓轻舟
链接:https://juejin.im/post/6889989103958360077
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

youtube-dl 源码看看,例子是下载网页的更多相关文章

  1. hadoop2.6.0汇总:新增功能最新编译 32位、64位安装、源码包、API下载及部署文档

    相关内容: hadoop2.5.2汇总:新增功能最新编译 32位.64位安装.源码包.API.eclipse插件下载Hadoop2.5 Eclipse插件制作.连接集群视频.及hadoop-eclip ...

  2. Android4.4系统源码百度网盘下载

    众所周知.Android如今非常火,肯定也有非常多android开发人员像我一样想研究android系统的源码.可是假设依照Google官方站点http://source.android.com/so ...

  3. Android源码的编译和下载【转】

    本文转载自:http://blog.csdn.net/banketree/article/details/9089827 网上介绍下载.编译Android方法一坨,读万卷书不如行万里路,以下是笔者亲身 ...

  4. Linux下编译Qt源码,一定要下载tar.gz版本,否则会报权限不足

    首先下载qt-everywhere-opensource-src-4.8.1源码,下载地址: ftp://ftp.qt-project.org/qt/source/ 在Linux下编译一定要下载qt- ...

  5. 查看android源码,windows环境下载源码

    查看源码 参考: http://blog.csdn.net/janronehoo/article/details/8560304 步骤: 添加chrome插件 Android SDK Search 进 ...

  6. Spring源码的编译、下载和阅读

    原文出处: 分享牛 想对spring框架进行深入的学习一下,看看源代码,提升和沉淀下自己,工欲善其事必先利其器,还是先搭建环境吧. 环境搭建 sping源码之前是svn管理,现在已经迁移到了githu ...

  7. Android源码4.4.4_r1下载和编译

    系统:ubuntu 16.04.2 TLS 1.源码下载: sudo apt-get install curl curl https://storage.googleapis.com/git-repo ...

  8. iOS开发者福利之精品源码汇总!免费下载

    汇总一些看着不错的源码,有需要的朋友过来下载吧!{:4_102:} 1.用swift制作的色彩炫丽的进度条-KDCircularProgressKDCircularProgress是使用swift制作 ...

  9. 80个Python经典资料(教程+源码+工具)汇总——下载目录 ...

    原文转自:http://bbs.51cto.com/thread-935214-1.html 大家好,51CTO下载中心根据资料的热度和好评度收集了80个Python资料,分享给Python开发的同学 ...

随机推荐

  1. DX12龙书 00 - 环境配置:通过 Visual Studio 2019 运行示例项目

    0x00 安装 Visual Studio 2019 安装 Visual Studio 2019 以及相关组件. 注:安装组件时带的 Windows 10 SDK 可以在 Individual com ...

  2. Python+Appium自动化测试(13)-toast定位

    一,前言 在app自动化测试的过程中经常会遇到需要对toast进行定位,最常见的就是定位toast或者获取toast的文案进行断言,如下图,通过定位"登录成功"的toast就可以断 ...

  3. Eclipse4.5 Mars版本安装activiti插件 亲测可用

    Eclipse4.5 Mars版本安装activiti插件 亲测可用 学习使用activiti 在线安装一直,国内的网络真心的是 很苦 啊:在茫茫网络上面找到了很多插件的离线包 终于找到一个可以使用的 ...

  4. 用flannel实现跨主机container通信

    最近在看kubernetes,看到了网络部分,这部分是集群设计的难点,也是我比较感兴趣的部分.书上提到不同node的container之间通信主要使用flannel,openvswitch等技术,这些 ...

  5. 关于ptype_all和pypte_base中的pt_prev的说明[转]

    不知道原帖,我是从这里看到了,解决了迷惑我很久的疑问,抄过来. 看见noble_shi兄弟"关于net_rx_action函数的若干问题"贴中关于pt_prev的问题, 本来想在论 ...

  6. 多测师讲解_ 高级自动化测试selenium_001基本学习

    高级自动化测试python+selenium教程手册 --高级讲师肖sir 第 1 章webdriver 环境搭建好了,我们正式学习 selenium 的 webdriver 框架,它不像 QTP 之 ...

  7. MVC-WebApi配置 Swagger(Web Api可视化文档)

    一.从创建MVC WebApi开始 第一步创建MVC WebApi就创建好了,接下来就进入正题,上干货 ================================================ ...

  8. jmeter_01_常用快捷键

    jmeter常用快捷键 * 快捷键 功能 备注 Ctrl + C 复制 可复制组件 Ctrl + V 粘贴 可粘贴组件 Ctrl + Shift + C 复制粘贴当前组件到下一行 Ctrl + R 运 ...

  9. spring boot:用spring security加强druid的安全(druid 1.1.22 / spring boot 2.3.3)

    一,druid的安全保障有哪些环节要注意? 1,druid ui的访问要有ip地址限制 2,用户必须要有相应的权限才能访问druid 3,关闭重置功能 说明:stat-view-servlet.url ...

  10. spring boot:在项目中引入第三方外部jar包集成为本地jar包(spring boot 2.3.2)

    一,为什么要集成外部jar包? 不是所有的第三方库都会上传到mvnrepository, 这时我们如果想集成它的第三方库,则需要直接在项目中集成它们的jar包, 在操作上还是很简单的, 这里用luos ...