youtube-dl 源码看看,例子是下载网页
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 源码看看,例子是下载网页的更多相关文章
- hadoop2.6.0汇总:新增功能最新编译 32位、64位安装、源码包、API下载及部署文档
		相关内容: hadoop2.5.2汇总:新增功能最新编译 32位.64位安装.源码包.API.eclipse插件下载Hadoop2.5 Eclipse插件制作.连接集群视频.及hadoop-eclip ... 
- Android4.4系统源码百度网盘下载
		众所周知.Android如今非常火,肯定也有非常多android开发人员像我一样想研究android系统的源码.可是假设依照Google官方站点http://source.android.com/so ... 
- Android源码的编译和下载【转】
		本文转载自:http://blog.csdn.net/banketree/article/details/9089827 网上介绍下载.编译Android方法一坨,读万卷书不如行万里路,以下是笔者亲身 ... 
- Linux下编译Qt源码,一定要下载tar.gz版本,否则会报权限不足
		首先下载qt-everywhere-opensource-src-4.8.1源码,下载地址: ftp://ftp.qt-project.org/qt/source/ 在Linux下编译一定要下载qt- ... 
- 查看android源码,windows环境下载源码
		查看源码 参考: http://blog.csdn.net/janronehoo/article/details/8560304 步骤: 添加chrome插件 Android SDK Search 进 ... 
- Spring源码的编译、下载和阅读
		原文出处: 分享牛 想对spring框架进行深入的学习一下,看看源代码,提升和沉淀下自己,工欲善其事必先利其器,还是先搭建环境吧. 环境搭建 sping源码之前是svn管理,现在已经迁移到了githu ... 
- Android源码4.4.4_r1下载和编译
		系统:ubuntu 16.04.2 TLS 1.源码下载: sudo apt-get install curl curl https://storage.googleapis.com/git-repo ... 
- iOS开发者福利之精品源码汇总!免费下载
		汇总一些看着不错的源码,有需要的朋友过来下载吧!{:4_102:} 1.用swift制作的色彩炫丽的进度条-KDCircularProgressKDCircularProgress是使用swift制作 ... 
- 80个Python经典资料(教程+源码+工具)汇总——下载目录 ...
		原文转自:http://bbs.51cto.com/thread-935214-1.html 大家好,51CTO下载中心根据资料的热度和好评度收集了80个Python资料,分享给Python开发的同学 ... 
随机推荐
- Java结构体系
- 多测师讲解接口测试 _HTTP常见的状态码归纳_高级讲师肖sir
			100 Continue 初始的请求已经接受,客户应当继续发送请求的其余部分 101 Switching Protocols 服务器将遵从客户的请求转换到另外一种协议 200 OK 一切正常,对 ... 
- 汕尾6397.7539(薇)xiaojie:汕尾哪里有xiaomei
			汕尾哪里有小姐服务大保健[微信:6397.7539倩儿小妹[汕尾叫小姐服务√o服务微信:6397.7539倩儿小妹[汕尾叫小姐服务][十微信:6397.7539倩儿小妹][汕尾叫小姐包夜服务][十微信 ... 
- Python3.7有什么新变化
			https://docs.python.org/zh-cn/3/whatsnew/3.7.html 
- spring-boot-route(十七)使用aop记录操作日志
			在上一章内容中--使用logback管理日志,我们详细讲述了如何将日志生成文件进行存储.但是在实际开发中,使用文件存储日志用来快速查询问题并不是最方便的,一个优秀系统除了日志文件还需要将操作日志进行持 ... 
- 编程代码 | C++/C输出阳历万年历—精美日历制作
			前言:本文章向大家介绍如何用C语言代码实现万年历使用实例.应用技巧.基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下. void输出万年历(int年, int月, int日 ... 
- centos8上redis5在生产环境的配置
			一,创建redis的数据和日志目录: [root@yjweb data]# mkdir /data/redis6379 [root@yjweb data]# mkdir /data/redis6379 ... 
- go创建http服务
			Go语言这种从零开始使用到解决问题的速度,在其他语言中是完全不可想象的.学过 C++ 的朋友都知道,一到两年大强度的理论学习和实战操练也只能学到这门语言的皮毛,以及知道一些基本的避免错误的方法. 那么 ... 
- spring注解@Transactional 和乐观锁,悲观锁并发生成有序编号问题
			需求:系统中有一个自增的合同编号,在满足并发情况下,生成的合同编号是自增的. 测试工具:Apache Jmeter 实现方法: 创建一个数据库表.编号最大值记录表 表结构类似 CREATE TAB ... 
- CSS实现鼠标移入弹出下拉框
			前言 最近比较沉迷CSS,所以我现在来做个鼠标的交互效果 HTML <ul> <li>测试</li> <li>测试</li> <li ... 
