├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── CHANGELOG.rst ├── LICENSE.txt ├── MANIFEST.in ├── Makefile ├── README.md ├── README.rst ├── contrib └── completion │ ├── _you-get │ ├── you-get-completion.bash │ └── you-get.fish ├── setup.cfg ├── setup.py ├── src └── you_get │ ├── __init__.py │ ├── __main__.py │ ├── cli_wrapper │ ├── __init__.py │ ├── downloader │ │ └── __init__.py │ ├── openssl │ │ └── __init__.py │ ├── player │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── dragonplayer.py │ │ ├── gnome_mplayer.py │ │ ├── mplayer.py │ │ ├── vlc.py │ │ └── wmp.py │ └── transcoder │ │ ├── __init__.py │ │ ├── ffmpeg.py │ │ ├── libav.py │ │ └── mencoder.py │ ├── common.py │ ├── extractor.py │ ├── extractors │ ├── __init__.py │ ├── acfun.py │ ├── alive.py │ ├── archive.py │ ├── baidu.py │ ├── bandcamp.py │ ├── baomihua.py │ ├── bigthink.py │ ├── bilibili.py │ ├── bokecc.py │ ├── cbs.py │ ├── ckplayer.py │ ├── cntv.py │ ├── dailymotion.py │ ├── dilidili.py │ ├── douban.py │ ├── douyutv.py │ ├── ehow.py │ ├── embed.py │ ├── facebook.py │ ├── fantasy.py │ ├── fc2video.py │ ├── flickr.py │ ├── freesound.py │ ├── funshion.py │ ├── google.py │ ├── heavymusic.py │ ├── huaban.py │ ├── huomaotv.py │ ├── icourses.py │ ├── ifeng.py │ ├── imgur.py │ ├── infoq.py │ ├── instagram.py │ ├── interest.py │ ├── iqilu.py │ ├── iqiyi.py │ ├── iwara.py │ ├── joy.py │ ├── khan.py │ ├── ku6.py │ ├── kugou.py │ ├── kuwo.py │ ├── le.py │ ├── lizhi.py │ ├── magisto.py │ ├── metacafe.py │ ├── mgtv.py │ ├── miaopai.py │ ├── miomio.py │ ├── mixcloud.py │ ├── mtv81.py │ ├── musicplayon.py │ ├── nanagogo.py │ ├── naver.py │ ├── netease.py │ ├── nicovideo.py │ ├── panda.py │ ├── pinterest.py │ ├── pixnet.py │ ├── pptv.py │ ├── qie.py │ ├── qie_video.py │ ├── qingting.py │ ├── qq.py │ ├── qq_egame.py │ ├── quanmin.py │ ├── showroom.py │ ├── sina.py │ ├── sohu.py │ ├── soundcloud.py │ ├── suntv.py │ ├── ted.py │ ├── theplatform.py │ ├── tucao.py │ ├── tudou.py │ ├── tumblr.py │ ├── twitter.py │ ├── ucas.py │ ├── universal.py │ ├── veoh.py │ ├── videomega.py │ ├── vidto.py │ ├── vimeo.py │ ├── vine.py │ ├── vk.py │ ├── w56.py │ ├── wanmen.py │ ├── xiami.py │ ├── ximalaya.py │ ├── yinyuetai.py │ ├── yixia.py │ ├── yizhibo.py │ ├── youku.py │ ├── youtube.py │ └── zhanqi.py │ ├── json_output.py │ ├── processor │ ├── __init__.py │ ├── ffmpeg.py │ ├── join_flv.py │ ├── join_mp4.py │ ├── join_ts.py │ └── rtmpdump.py │ ├── util │ ├── __init__.py │ ├── fs.py │ ├── git.py │ ├── log.py │ ├── strings.py │ └── term.py │ └── version.py ├── tests ├── __init__.py ├── test.py ├── test_common.py └── test_util.py ├── you-get ├── you-get.json └── you-get.plugin.zsh /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Please make sure these boxes are checked before submitting your issue – thank you! 2 | 3 | - [ ] You can actually watch the video in your browser or mobile application, but not download them with `you-get`. 4 | - [ ] Your `you-get` is up-to-date. 5 | - [ ] I have read and tried to do so. 6 | - [ ] The issue is not yet reported on or . If so, please add your comments under the existing issue. 7 | - [ ] The issue (or question) is really about `you-get`, not about some other code or project. 8 | 9 | Run the command with the `--debug` option, and paste the full output inside the fences: 10 | 11 | ``` 12 | [PASTE IN ME] 13 | ``` 14 | 15 | If there's anything else you would like to say (e.g. in case your issue is not about downloading a specific video; it might as well be a general discussion or proposal for a new feature), fill in the box below; otherwise, you may want to post an emoji or meme instead: 16 | 17 | > [WRITE SOMETHING] 18 | > [OR HAVE SOME :icecream:!] 19 | 20 | 汉语翻译最终日期:2016年02月26日 21 | 22 | 在提交前,请确保您已经检查了以下内容! 23 | 24 | - [ ] 你可以在浏览器或移动端中观看视频,但不能使用`you-get`下载. 25 | - [ ] 您的`you-get`为最新版. 26 | - [ ] 我已经阅读并按 中的指引进行了操作. 27 | - [ ] 您的问题没有在 , 报告,否则请在原有issue下报告. 28 | - [ ] 本问题确实关于`you-get`, 而不是其他项目. 29 | 30 | 请使用`--debug`运行,并将输出粘贴在下面: 31 | 32 | ``` 33 | [在这里粘贴完整日志] 34 | ``` 35 | 36 | 如果您有其他附言,例如问题只在某个视频发生,或者是一般性讨论或者提出新功能,请在下面添加;或者您可以卖个萌: 37 | 38 | > [您的内容] 39 | > [舔 :icecream:!] 40 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **(PLEASE DELETE ALL THESE AFTER READING)** 2 | 3 | Thank you for the pull request! `you-get` is a growing open source project, which would not have been possible without contributors like you. 4 | 5 | Here are some simple rules to follow, please recheck them before sending the pull request: 6 | 7 | - [ ] If you want to propose two or more unrelated patches, please open separate pull requests for them, instead of one; 8 | - [ ] All pull requests should be based upon the latest `develop` branch; 9 | - [ ] Name your branch (from which you will send the pull request) properly; use a meaningful name like `add-this-shining-feature` rather than just `develop`; 10 | - [ ] All commit messages, as well as comments in code, should be written in understandable English. 11 | 12 | As a contributor, you must be aware that 13 | 14 | - [ ] You agree to contribute your code to this project, under the terms of the MIT license, so that any person may freely use or redistribute them; of course, you will still reserve the copyright for your own authorship. 15 | - [ ] You may not contribute any code not authored by yourself, unless they are licensed under either public domain or the MIT license, literally. 16 | 17 | Not all pull requests can eventually be merged. I consider merged / unmerged patches as equally important for the community: as long as you think a patch would be helpful, someone else might find it helpful, too, therefore they could take your fork and benefit in some way. In any case, I would like to thank you in advance for taking your time to contribute to this project. 18 | 19 | Cheers, 20 | Mort 21 | 22 | **(PLEASE REPLACE ALL ABOVE WITH A DETAILED DESCRIPTION OF YOUR PULL REQUEST)** 23 | 24 | 25 | 汉语翻译最后日期:2016年02月26日 26 | 27 | **(阅读后请删除所有内容)** 28 | 29 | 感谢您的pull request! `you-get`是稳健成长的开源项目,感谢您的贡献. 30 | 31 | 以下简单检查项目望您复查: 32 | 33 | - [ ] 如果您预计提出两个或更多不相关补丁,请为每个使用不同的pull requests,而不是单一; 34 | - [ ] 所有的pull requests应基于最新的`develop`分支; 35 | - [ ] 您预计提出pull requests的分支应有有意义名称,例如`add-this-shining-feature`而不是`develop`; 36 | - [ ] 所有的提交信息与代码中注释应使用可理解的英语. 37 | 38 | 作为贡献者,您需要知悉 39 | 40 | - [ ] 您同意在MIT协议下贡献代码,以便任何人自由使用或分发;当然,你仍旧保留代码的著作权 41 | - [ ] 你不得贡献非自己编写的代码,除非其属于公有领域或使用MIT协议. 42 | 43 | 不是所有的pull requests都会被合并,然而我认为合并/不合并的补丁一样重要:如果您认为补丁重要,其他人也有可能这么认为,那么他们可以从你的fork中提取工作并获益。无论如何,感谢您费心对本项目贡献. 44 | 45 | 祝好, 46 | Mort 47 | 48 | **(请将本内容完整替换为PULL REQUEST的详细内容)** 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | # Misc 62 | _* 63 | *_ 64 | *.3gp 65 | *.asf 66 | *.download 67 | *.f4v 68 | *.flv 69 | *.gif 70 | *.html 71 | *.jpg 72 | *.lrc 73 | *.mkv 74 | *.mp3 75 | *.mp4 76 | *.mpg 77 | *.png 78 | *.srt 79 | *.ts 80 | *.webm 81 | *.xml 82 | /.env 83 | /.idea 84 | *.m4a 85 | *.DS_Store 86 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # https://travis-ci.org/soimort/you-get 2 | language: python 3 | python: 4 | - "3.2" 5 | - "3.3" 6 | - "3.4" 7 | - "3.5" 8 | - "3.6" 9 | - "nightly" 10 | - "pypy3" 11 | script: make test 12 | sudo: false 13 | notifications: 14 | webhooks: 15 | urls: 16 | - https://webhooks.gitter.im/e/43cd57826e88ed8f2152 17 | on_success: change # options: [always|never|change] default: always 18 | on_failure: always # options: [always|never|change] default: always 19 | on_start: never # options: [always|never|change] default: always 20 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | ============================================== 2 | This is a copy of the MIT license. 3 | ============================================== 4 | Copyright (C) 2012-2017 Mort Yao 5 | Copyright (C) 2012 Boyu Guo 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | this software and associated documentation files (the "Software"), to deal in 9 | the Software without restriction, including without limitation the rights to 10 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | of the Software, and to permit persons to whom the Software is furnished to do 12 | so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.rst 2 | include *.txt 3 | include Makefile 4 | include README.md 5 | include you-get 6 | include you-get.json 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SETUP = python3 setup.py 2 | 3 | .PHONY: default i test clean all html rst build sdist bdist bdist_egg bdist_wheel install release 4 | 5 | default: i 6 | 7 | i: 8 | @(cd src/; python3 -i -c 'import you_get; print("You-Get %s\n>>> import you_get" % you_get.version.__version__)') 9 | 10 | test: 11 | $(SETUP) test 12 | 13 | clean: 14 | zenity --question 15 | rm -fr build/ dist/ src/*.egg-info/ 16 | find . | grep __pycache__ | xargs rm -fr 17 | find . | grep .pyc | xargs rm -f 18 | 19 | all: build sdist bdist bdist_egg bdist_wheel 20 | 21 | html: 22 | pandoc README.md > README.html 23 | 24 | rst: 25 | pandoc -s -t rst README.md > README.rst 26 | 27 | build: 28 | $(SETUP) build 29 | 30 | sdist: 31 | $(SETUP) sdist 32 | 33 | bdist: 34 | $(SETUP) bdist 35 | 36 | bdist_egg: 37 | $(SETUP) bdist_egg 38 | 39 | bdist_wheel: 40 | $(SETUP) bdist_wheel 41 | 42 | install: 43 | $(SETUP) install --user --prefix= 44 | 45 | release: 46 | zenity --question 47 | $(SETUP) sdist bdist_wheel upload --sign 48 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | You-Get 2 | ======= 3 | 4 | |PyPI version| |Build Status| |Gitter| 5 | 6 | `You-Get `__ is a tiny command-line utility to 7 | download media contents (videos, audios, images) from the Web, in case 8 | there is no other handy way to do it. 9 | 10 | Here's how you use ``you-get`` to download a video from `this web 11 | page `__: 12 | 13 | .. code:: console 14 | 15 | $ you-get http://www.fsf.org/blogs/rms/20140407-geneva-tedx-talk-free-software-free-society 16 | Site: fsf.org 17 | Title: TEDxGE2014_Stallman05_LQ 18 | Type: WebM video (video/webm) 19 | Size: 27.12 MiB (28435804 Bytes) 20 | 21 | Downloading TEDxGE2014_Stallman05_LQ.webm ... 22 | 100.0% ( 27.1/27.1 MB) ├████████████████████████████████████████┤[1/1] 12 MB/s 23 | 24 | And here's why you might want to use it: 25 | 26 | - You enjoyed something on the Internet, and just want to download them 27 | for your own pleasure. 28 | - You watch your favorite videos online from your computer, but you are 29 | prohibited from saving them. You feel that you have no control over 30 | your own computer. (And it's not how an open Web is supposed to 31 | work.) 32 | - You want to get rid of any closed-source technology or proprietary 33 | JavaScript code, and disallow things like Flash running on your 34 | computer. 35 | - You are an adherent of hacker culture and free software. 36 | 37 | What ``you-get`` can do for you: 38 | 39 | - Download videos / audios from popular websites such as YouTube, 40 | Youku, Niconico, and a bunch more. (See the `full list of supported 41 | sites <#supported-sites>`__) 42 | - Stream an online video in your media player. No web browser, no more 43 | ads. 44 | - Download images (of interest) by scraping a web page. 45 | - Download arbitrary non-HTML contents, i.e., binary files. 46 | 47 | Interested? `Install it <#installation>`__ now and `get started by 48 | examples <#getting-started>`__. 49 | 50 | Are you a Python programmer? Then check out `the 51 | source `__ and fork it! 52 | 53 | .. |PyPI version| image:: https://badge.fury.io/py/you-get.png 54 | :target: http://badge.fury.io/py/you-get 55 | .. |Build Status| image:: https://api.travis-ci.org/soimort/you-get.png 56 | :target: https://travis-ci.org/soimort/you-get 57 | .. |Gitter| image:: https://badges.gitter.im/Join%20Chat.svg 58 | :target: https://gitter.im/soimort/you-get?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge 59 | -------------------------------------------------------------------------------- /contrib/completion/_you-get: -------------------------------------------------------------------------------- 1 | #compdef you-get 2 | 3 | # Zsh completion definition for soimort/you-get. 4 | 5 | setopt localoptions noshwordsplit noksharrays 6 | local -a args 7 | 8 | args=( 9 | '(- : *)'{-V,--version}'[print version and exit]' 10 | '(- : *)'{-h,--help}'[print help and exit]' 11 | '(-i --info)'{-i,--info}'[print extracted information]' 12 | '(-u --url)'{-u,--url}'[print extracted information with URLs]' 13 | '(--json)--json[print extracted URLs in JSON format]' 14 | '(-n --no-merge)'{-n,--no-merge}'[do not merge video parts]' 15 | '(--no-caption)--no-caption[do not download captions]' 16 | '(-f --force)'{-f,--force}'[force overwrite existing files]' 17 | '(-F --format)'{-F,--format}'[set video format to the specified stream id]:stream id' 18 | '(-O --output-filename)'{-O,--output-filename}'[set output filename]:filename:_files' 19 | '(-o --output-dir)'{-o,--output-dir}'[set output directory]:directory:_files -/' 20 | '(-p --player)'{-p,--player}'[stream extracted URL to the specified player]:player and options' 21 | '(-c --cookies)'{-c,--cookies}'[load cookies.txt or cookies.sqlite]:cookies file:_files' 22 | '(-x --http-proxy)'{-x,--http-proxy}'[use the specified HTTP proxy for downloading]:host\:port:' 23 | '(-y --extractor-proxy)'{-y,--extractor-proxy}'[use the specified HTTP proxy for extraction only]:host\:port' 24 | '(--no-proxy)--no-proxy[do not use a proxy]' 25 | '(-t --timeout)'{-t,--timeout}'[set socket timeout]:seconds' 26 | '(-d --debug)'{-d,--debug}'[show traceback and other debug info]' 27 | '*: :_guard "^-*" url' 28 | ) 29 | _arguments -S -s $args 30 | -------------------------------------------------------------------------------- /contrib/completion/you-get-completion.bash: -------------------------------------------------------------------------------- 1 | # Bash completion definition for you-get. 2 | 3 | _you-get () { 4 | COMPREPLY=() 5 | local IFS=$' \n' 6 | local cur=$2 prev=$3 7 | local -a opts_without_arg opts_with_arg 8 | opts_without_arg=( 9 | -V --version -h --help -i --info -u --url --json -n --no-merge 10 | --no-caption -f --force --no-proxy -d --debug 11 | ) 12 | opts_with_arg=( 13 | -F --format -O --output-filename -o --output-dir -p --player 14 | -c --cookies -x --http-proxy -y --extractor-proxy -t --timeout 15 | ) 16 | 17 | # Do not complete non option names 18 | [[ $cur == -* ]] || return 1 19 | 20 | # Do not complete when the previous arg is an option expecting an argument 21 | for opt in "${opts_with_arg[@]}"; do 22 | [[ $opt == $prev ]] && return 1 23 | done 24 | 25 | # Complete option names 26 | COMPREPLY=( $(compgen -W "${opts_without_arg[*]} ${opts_with_arg[*]}" \ 27 | -- "$cur") ) 28 | return 0 29 | } 30 | 31 | complete -F _you-get you-get 32 | -------------------------------------------------------------------------------- /contrib/completion/you-get.fish: -------------------------------------------------------------------------------- 1 | # Fish completion definition for you-get. 2 | 3 | complete -c you-get -s V -l version -d 'print version and exit' 4 | complete -c you-get -s h -l help -d 'print help and exit' 5 | complete -c you-get -s i -l info -d 'print extracted information' 6 | complete -c you-get -s u -l url -d 'print extracted information' 7 | complete -c you-get -l json -d 'print extracted URLs in JSON format' 8 | complete -c you-get -s n -l no-merge -d 'do not merge video parts' 9 | complete -c you-get -l no-caption -d 'do not download captions' 10 | complete -c you-get -s f -l force -d 'force overwrite existing files' 11 | complete -c you-get -s F -l format -x -d 'set video format to the specified stream id' 12 | complete -c you-get -s O -l output-filename -d 'set output filename' \ 13 | -x -a '(__fish_complete_path (commandline -ct) "output filename")' 14 | complete -c you-get -s o -l output-dir -d 'set output directory' \ 15 | -x -a '(__fish_complete_directories (commandline -ct) "output directory")' 16 | complete -c you-get -s p -l player -x -d 'stream extracted URL to the specified player' 17 | complete -c you-get -s c -l cookies -d 'load cookies.txt or cookies.sqlite' \ 18 | -x -a '(__fish_complete_path (commandline -ct) "cookies.txt or cookies.sqlite")' 19 | complete -c you-get -s x -l http-proxy -x -d 'use the specified HTTP proxy for downloading' 20 | complete -c you-get -s y -l extractor-proxy -x -d 'use the specified HTTP proxy for extraction only' 21 | complete -c you-get -l no-proxy -d 'do not use a proxy' 22 | complete -c you-get -s t -l timeout -x -d 'set socket timeout' 23 | complete -c you-get -s d -l debug -d 'show traceback and other debug info' 24 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [build] 2 | force = 0 3 | 4 | [global] 5 | verbose = 0 6 | 7 | [egg_info] 8 | tag_build = 9 | tag_date = 0 10 | tag_svn_revision = 0 11 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | PROJ_NAME = 'you-get' 4 | PACKAGE_NAME = 'you_get' 5 | 6 | PROJ_METADATA = '%s.json' % PROJ_NAME 7 | 8 | import os, json, imp 9 | here = os.path.abspath(os.path.dirname(__file__)) 10 | proj_info = json.loads(open(os.path.join(here, PROJ_METADATA), encoding='utf-8').read()) 11 | try: 12 | README = open(os.path.join(here, 'README.rst'), encoding='utf-8').read() 13 | except: 14 | README = "" 15 | CHANGELOG = open(os.path.join(here, 'CHANGELOG.rst'), encoding='utf-8').read() 16 | VERSION = imp.load_source('version', os.path.join(here, 'src/%s/version.py' % PACKAGE_NAME)).__version__ 17 | 18 | from setuptools import setup, find_packages 19 | setup( 20 | name = proj_info['name'], 21 | version = VERSION, 22 | 23 | author = proj_info['author'], 24 | author_email = proj_info['author_email'], 25 | url = proj_info['url'], 26 | license = proj_info['license'], 27 | 28 | description = proj_info['description'], 29 | keywords = proj_info['keywords'], 30 | 31 | long_description = README, 32 | 33 | packages = find_packages('src'), 34 | package_dir = {'' : 'src'}, 35 | 36 | test_suite = 'tests', 37 | 38 | platforms = 'any', 39 | zip_safe = True, 40 | include_package_data = True, 41 | 42 | classifiers = proj_info['classifiers'], 43 | 44 | entry_points = {'console_scripts': proj_info['console_scripts']} 45 | ) 46 | -------------------------------------------------------------------------------- /src/you_get/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # This file is Python 2 compliant. 3 | 4 | import sys 5 | 6 | if sys.version_info[0] == 3: 7 | #from .extractor import Extractor, VideoExtractor 8 | #from .util import log 9 | 10 | from .__main__ import * 11 | 12 | #from .common import * 13 | #from .version import * 14 | #from .cli_wrapper import * 15 | #from .extractor import * 16 | else: 17 | # Don't import anything. 18 | pass 19 | -------------------------------------------------------------------------------- /src/you_get/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import getopt 4 | import os 5 | import platform 6 | import sys 7 | from .version import script_name, __version__ 8 | from .util import git, log 9 | 10 | _options = [ 11 | 'help', 12 | 'version', 13 | 'gui', 14 | 'force', 15 | 'playlists', 16 | ] 17 | _short_options = 'hVgfl' 18 | 19 | _help = """Usage: {} [OPTION]... [URL]... 20 | TODO 21 | """.format(script_name) 22 | 23 | # TBD 24 | def main_dev(**kwargs): 25 | """Main entry point. 26 | you-get-dev 27 | """ 28 | 29 | # Get (branch, commit) if running from a git repo. 30 | head = git.get_head(kwargs['repo_path']) 31 | 32 | # Get options and arguments. 33 | try: 34 | opts, args = getopt.getopt(sys.argv[1:], _short_options, _options) 35 | except getopt.GetoptError as e: 36 | log.wtf(""" 37 | [Fatal] {}. 38 | Try '{} --help' for more options.""".format(e, script_name)) 39 | 40 | if not opts and not args: 41 | # Display help. 42 | print(_help) 43 | # Enter GUI mode. 44 | #from .gui import gui_main 45 | #gui_main() 46 | else: 47 | conf = {} 48 | for opt, arg in opts: 49 | if opt in ('-h', '--help'): 50 | # Display help. 51 | print(_help) 52 | 53 | elif opt in ('-V', '--version'): 54 | # Display version. 55 | log.println("you-get:", log.BOLD) 56 | log.println(" version: {}".format(__version__)) 57 | if head is not None: 58 | log.println(" branch: {}\n commit: {}".format(*head)) 59 | else: 60 | log.println(" branch: {}\n commit: {}".format("(stable)", "(tag v{})".format(__version__))) 61 | 62 | log.println(" platform: {}".format(platform.platform())) 63 | log.println(" python: {}".format(sys.version.split('\n')[0])) 64 | 65 | elif opt in ('-g', '--gui'): 66 | # Run using GUI. 67 | conf['gui'] = True 68 | 69 | elif opt in ('-f', '--force'): 70 | # Force download. 71 | conf['force'] = True 72 | 73 | elif opt in ('-l', '--playlist', '--playlists'): 74 | # Download playlist whenever possible. 75 | conf['playlist'] = True 76 | 77 | if args: 78 | if 'gui' in conf and conf['gui']: 79 | # Enter GUI mode. 80 | from .gui import gui_main 81 | gui_main(*args, **conf) 82 | else: 83 | # Enter console mode. 84 | from .console import console_main 85 | console_main(*args, **conf) 86 | 87 | def main(**kwargs): 88 | """Main entry point. 89 | you-get (legacy) 90 | """ 91 | from .common import main 92 | main(**kwargs) 93 | 94 | if __name__ == '__main__': 95 | main() 96 | -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosynirvana/you-get/cff5fb452953800ed6d47fb422c9d1a6ff4993cc/src/you_get/cli_wrapper/__init__.py -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/downloader/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosynirvana/you-get/cff5fb452953800ed6d47fb422c9d1a6ff4993cc/src/you_get/cli_wrapper/downloader/__init__.py -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/openssl/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosynirvana/you-get/cff5fb452953800ed6d47fb422c9d1a6ff4993cc/src/you_get/cli_wrapper/openssl/__init__.py -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/player/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from .mplayer import * 4 | -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/player/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' WIP 4 | def main(): 5 | script_main('you-get', any_download, any_download_playlist) 6 | 7 | if __name__ == "__main__": 8 | main() 9 | ''' 10 | -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/player/dragonplayer.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosynirvana/you-get/cff5fb452953800ed6d47fb422c9d1a6ff4993cc/src/you_get/cli_wrapper/player/dragonplayer.py -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/player/gnome_mplayer.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosynirvana/you-get/cff5fb452953800ed6d47fb422c9d1a6ff4993cc/src/you_get/cli_wrapper/player/gnome_mplayer.py -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/player/mplayer.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosynirvana/you-get/cff5fb452953800ed6d47fb422c9d1a6ff4993cc/src/you_get/cli_wrapper/player/mplayer.py -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/player/vlc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/player/wmp.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosynirvana/you-get/cff5fb452953800ed6d47fb422c9d1a6ff4993cc/src/you_get/cli_wrapper/player/wmp.py -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/transcoder/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosynirvana/you-get/cff5fb452953800ed6d47fb422c9d1a6ff4993cc/src/you_get/cli_wrapper/transcoder/__init__.py -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/transcoder/ffmpeg.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosynirvana/you-get/cff5fb452953800ed6d47fb422c9d1a6ff4993cc/src/you_get/cli_wrapper/transcoder/ffmpeg.py -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/transcoder/libav.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosynirvana/you-get/cff5fb452953800ed6d47fb422c9d1a6ff4993cc/src/you_get/cli_wrapper/transcoder/libav.py -------------------------------------------------------------------------------- /src/you_get/cli_wrapper/transcoder/mencoder.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rosynirvana/you-get/cff5fb452953800ed6d47fb422c9d1a6ff4993cc/src/you_get/cli_wrapper/transcoder/mencoder.py -------------------------------------------------------------------------------- /src/you_get/extractors/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from .acfun import * 4 | from .alive import * 5 | from .archive import * 6 | from .baidu import * 7 | from .bandcamp import * 8 | from .bigthink import * 9 | from .bilibili import * 10 | from .bokecc import * 11 | from .cbs import * 12 | from .ckplayer import * 13 | from .cntv import * 14 | from .dailymotion import * 15 | from .dilidili import * 16 | from .douban import * 17 | from .douyutv import * 18 | from .ehow import * 19 | from .facebook import * 20 | from .fantasy import * 21 | from .fc2video import * 22 | from .flickr import * 23 | from .freesound import * 24 | from .funshion import * 25 | from .google import * 26 | from .heavymusic import * 27 | from .huaban import * 28 | from .icourses import * 29 | from .ifeng import * 30 | from .imgur import * 31 | from .infoq import * 32 | from .instagram import * 33 | from .interest import * 34 | from .iqilu import * 35 | from .iqiyi import * 36 | from .joy import * 37 | from .ku6 import * 38 | from .kugou import * 39 | from .kuwo import * 40 | from .le import * 41 | from .lizhi import * 42 | from .magisto import * 43 | from .metacafe import * 44 | from .mgtv import * 45 | from .miaopai import * 46 | from .miomio import * 47 | from .mixcloud import * 48 | from .mtv81 import * 49 | from .musicplayon import * 50 | from .nanagogo import * 51 | from .naver import * 52 | from .netease import * 53 | from .nicovideo import * 54 | from .panda import * 55 | from .pinterest import * 56 | from .pixnet import * 57 | from .pptv import * 58 | from .qie import * 59 | from .qingting import * 60 | from .qq import * 61 | from .showroom import * 62 | from .sina import * 63 | from .sohu import * 64 | from .soundcloud import * 65 | from .suntv import * 66 | from .theplatform import * 67 | from .tucao import * 68 | from .tudou import * 69 | from .tumblr import * 70 | from .twitter import * 71 | from .ucas import * 72 | from .veoh import * 73 | from .videomega import * 74 | from .vimeo import * 75 | from .vine import * 76 | from .vk import * 77 | from .w56 import * 78 | from .wanmen import * 79 | from .xiami import * 80 | from .yinyuetai import * 81 | from .yixia import * 82 | from .youku import * 83 | from .youtube import * 84 | from .ted import * 85 | from .khan import * 86 | from .zhanqi import * 87 | -------------------------------------------------------------------------------- /src/you_get/extractors/acfun.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __all__ = ['acfun_download'] 4 | 5 | from ..common import * 6 | 7 | from .le import letvcloud_download_by_vu 8 | from .qq import qq_download_by_vid 9 | from .sina import sina_download_by_vid 10 | from .tudou import tudou_download_by_iid 11 | from .youku import youku_download_by_vid 12 | 13 | import json 14 | import re 15 | import base64 16 | import time 17 | 18 | def get_srt_json(id): 19 | url = 'http://danmu.aixifan.com/V2/%s' % id 20 | return get_content(url) 21 | 22 | def youku_acfun_proxy(vid, sign, ref): 23 | endpoint = 'http://player.acfun.cn/flash_data?vid={}&ct=85&ev=3&sign={}&time={}' 24 | url = endpoint.format(vid, sign, str(int(time.time() * 1000))) 25 | json_data = json.loads(get_content(url, headers=dict(referer=ref)))['data'] 26 | enc_text = base64.b64decode(json_data) 27 | dec_text = rc4(b'8bdc7e1a', enc_text).decode('utf8') 28 | youku_json = json.loads(dec_text) 29 | 30 | yk_streams = {} 31 | for stream in youku_json['stream']: 32 | tp = stream['stream_type'] 33 | yk_streams[tp] = [], stream['total_size'] 34 | if stream.get('segs'): 35 | for seg in stream['segs']: 36 | yk_streams[tp][0].append(seg['url']) 37 | else: 38 | yk_streams[tp] = stream['m3u8'], stream['total_size'] 39 | 40 | return yk_streams 41 | 42 | def acfun_download_by_vid(vid, title, output_dir='.', merge=True, info_only=False, **kwargs): 43 | """str, str, str, bool, bool ->None 44 | 45 | Download Acfun video by vid. 46 | 47 | Call Acfun API, decide which site to use, and pass the job to its 48 | extractor. 49 | """ 50 | 51 | #first call the main parasing API 52 | info = json.loads(get_content('http://www.acfun.tv/video/getVideo.aspx?id=' + vid)) 53 | 54 | sourceType = info['sourceType'] 55 | 56 | #decide sourceId to know which extractor to use 57 | if 'sourceId' in info: sourceId = info['sourceId'] 58 | # danmakuId = info['danmakuId'] 59 | 60 | #call extractor decided by sourceId 61 | if sourceType == 'sina': 62 | sina_download_by_vid(sourceId, title, output_dir=output_dir, merge=merge, info_only=info_only) 63 | elif sourceType == 'youku': 64 | youku_download_by_vid(sourceId, title=title, output_dir=output_dir, merge=merge, info_only=info_only, **kwargs) 65 | elif sourceType == 'tudou': 66 | tudou_download_by_iid(sourceId, title, output_dir=output_dir, merge=merge, info_only=info_only) 67 | elif sourceType == 'qq': 68 | qq_download_by_vid(sourceId, title, output_dir=output_dir, merge=merge, info_only=info_only) 69 | elif sourceType == 'letv': 70 | letvcloud_download_by_vu(sourceId, '2d8c027396', title, output_dir=output_dir, merge=merge, info_only=info_only) 71 | elif sourceType == 'zhuzhan': 72 | #As in Jul.28.2016, Acfun is using embsig to anti hotlink so we need to pass this 73 | #In Mar. 2017 there is a dedicated ``acfun_proxy'' in youku cloud player 74 | #old code removed 75 | url = 'http://www.acfun.cn/v/ac' + vid 76 | yk_streams = youku_acfun_proxy(info['sourceId'], info['encode'], url) 77 | seq = ['mp4hd3', 'mp4hd2', 'mp4hd', 'flvhd'] 78 | for t in seq: 79 | if yk_streams.get(t): 80 | preferred = yk_streams[t] 81 | break 82 | #total_size in the json could be incorrect(F.I. 0) 83 | size = 0 84 | for url in preferred[0]: 85 | _, _, seg_size = url_info(url) 86 | size += seg_size 87 | #fallback to flvhd is not quite possible 88 | print_info(site_info, title, 'mp4', size) 89 | if not info_only: 90 | download_urls(preferred[0], title, 'mp4', size, output_dir=output_dir, merge=merge) 91 | else: 92 | raise NotImplementedError(sourceType) 93 | 94 | if not info_only and not dry_run: 95 | if not kwargs['caption']: 96 | print('Skipping danmaku.') 97 | return 98 | try: 99 | title = get_filename(title) 100 | print('Downloading %s ...\n' % (title + '.cmt.json')) 101 | cmt = get_srt_json(vid) 102 | with open(os.path.join(output_dir, title + '.cmt.json'), 'w', encoding='utf-8') as x: 103 | x.write(cmt) 104 | except: 105 | pass 106 | 107 | def acfun_download(url, output_dir='.', merge=True, info_only=False, **kwargs): 108 | assert re.match(r'http://[^\.]*\.*acfun\.[^\.]+/\D/\D\D(\d+)', url) 109 | html = get_content(url) 110 | 111 | title = r1(r'data-title="([^"]+)"', html) 112 | title = unescape_html(title) 113 | title = escape_file_path(title) 114 | assert title 115 | if match1(url, r'_(\d+)$'): # current P 116 | title = title + " " + r1(r'active">([^<]*)', html) 117 | 118 | vid = r1('data-vid="(\d+)"', html) 119 | up = r1('data-name="([^"]+)"', html) 120 | title = title + ' - ' + up 121 | acfun_download_by_vid(vid, title, 122 | output_dir=output_dir, 123 | merge=merge, 124 | info_only=info_only, 125 | **kwargs) 126 | 127 | site_info = "AcFun.tv" 128 | download = acfun_download 129 | download_playlist = playlist_not_supported('acfun') 130 | -------------------------------------------------------------------------------- /src/you_get/extractors/alive.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __all__ = ['alive_download'] 4 | 5 | from ..common import * 6 | 7 | def alive_download(url, output_dir = '.', merge = True, info_only = False, **kwargs): 8 | html = get_html(url) 9 | 10 | title = r1(r'(.*)', html) 27 | assert title 28 | id = r1(r'flvid\s*=\s*(\d+)', html) 29 | assert id 30 | baomihua_download_by_id(id, title, output_dir=output_dir, merge=merge, info_only=info_only) 31 | 32 | site_info = "baomihua.com" 33 | download = baomihua_download 34 | download_playlist = playlist_not_supported('baomihua') 35 | -------------------------------------------------------------------------------- /src/you_get/extractors/bigthink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from ..common import * 4 | from ..extractor import VideoExtractor 5 | 6 | import json 7 | 8 | class Bigthink(VideoExtractor): 9 | name = "Bigthink" 10 | 11 | stream_types = [ #this is just a sample. Will make it in prepare() 12 | # {'id': '1080'}, 13 | # {'id': '720'}, 14 | # {'id': '360'}, 15 | # {'id': '288'}, 16 | # {'id': '190'}, 17 | # {'id': '180'}, 18 | 19 | ] 20 | 21 | @staticmethod 22 | def get_streams_by_id(account_number, video_id): 23 | """ 24 | int, int->list 25 | 26 | Get the height of the videos. 27 | 28 | Since brightcove is using 3 kinds of links: rtmp, http and https, 29 | we will be using the HTTPS one to make it secure. 30 | 31 | If somehow akamaihd.net is blocked by the Great Fucking Wall, 32 | change the "startswith https" to http. 33 | """ 34 | endpoint = 'https://edge.api.brightcove.com/playback/v1/accounts/{account_number}/videos/{video_id}'.format(account_number = account_number, video_id = video_id) 35 | fake_header_id = fake_headers 36 | #is this somehow related to the time? Magic.... 37 | fake_header_id['Accept'] ='application/json;pk=BCpkADawqM1cc6wmJQC2tvoXZt4mrB7bFfi6zGt9QnOzprPZcGLE9OMGJwspQwKfuFYuCjAAJ53JdjI8zGFx1ll4rxhYJ255AXH1BQ10rnm34weknpfG-sippyQ' 38 | 39 | html = get_content(endpoint, headers= fake_header_id) 40 | html_json = json.loads(html) 41 | 42 | link_list = [] 43 | 44 | for i in html_json['sources']: 45 | if 'src' in i: #to avoid KeyError 46 | if i['src'].startswith('https'): 47 | link_list.append((str(i['height']), i['src'])) 48 | 49 | return link_list 50 | 51 | def prepare(self, **kwargs): 52 | 53 | html = get_content(self.url) 54 | 55 | self.title = match1(html, r'None 19 | 20 | Keyword arguments: 21 | self: self 22 | vid: The video ID for BokeCC cloud, something like 23 | FE3BB999594978049C33DC5901307461 24 | 25 | Calls the prepare() to download the video. 26 | 27 | If no title is provided, this method shall try to find a proper title 28 | with the information providin within the 29 | returned content of the API.""" 30 | 31 | assert vid 32 | 33 | self.prepare(vid = vid, title = title, **kwargs) 34 | 35 | self.extract(**kwargs) 36 | 37 | self.download(output_dir = output_dir, 38 | merge = merge, 39 | info_only = info_only, **kwargs) 40 | 41 | def prepare(self, vid = '', title = None, **kwargs): 42 | assert vid 43 | 44 | api_url = self.API_ENDPOINT + \ 45 | 'servlet/playinfo?vid={vid}&m=0'.format(vid = vid) #return XML 46 | 47 | html = get_content(api_url) 48 | self.tree = ET.ElementTree(ET.fromstring(html)) 49 | 50 | if self.tree.find('result').text != '1': 51 | log.wtf('API result says failed!') 52 | raise 53 | 54 | if title is None: 55 | self.title = '_'.join([i.text for i in self.tree.iterfind('video/videomarks/videomark/markdesc')]) 56 | else: 57 | self.title = title 58 | 59 | if not title: 60 | self.title = vid 61 | 62 | for i in self.tree.iterfind('video/quality'): 63 | quality = i.attrib ['value'] 64 | url = i[0].attrib['playurl'] 65 | self.stream_types.append({'id': quality, 66 | 'video_profile': i.attrib ['desp']}) 67 | self.streams[quality] = {'url': url, 68 | 'video_profile': i.attrib ['desp']} 69 | self.streams_sorted = [dict([('id', stream_type['id'])] + list(self.streams[stream_type['id']].items())) for stream_type in self.__class__.stream_types if stream_type['id'] in self.streams] 70 | 71 | 72 | def extract(self, **kwargs): 73 | for i in self.streams: 74 | s = self.streams[i] 75 | _, s['container'], s['size'] = url_info(s['url']) 76 | s['src'] = [s['url']] 77 | if 'stream_id' in kwargs and kwargs['stream_id']: 78 | # Extract the stream 79 | stream_id = kwargs['stream_id'] 80 | 81 | if stream_id not in self.streams: 82 | log.e('[Error] Invalid video format.') 83 | log.e('Run \'-i\' command with no specific video format to view all available formats.') 84 | exit(2) 85 | else: 86 | # Extract stream with the best quality 87 | stream_id = self.streams_sorted[0]['id'] 88 | _, s['container'], s['size'] = url_info(s['url']) 89 | s['src'] = [s['url']] 90 | 91 | site = BokeCC() 92 | 93 | # I don't know how to call the player directly so I just put it here 94 | # just in case anyone touchs it -- Beining@Aug.24.2016 95 | #download = site.download_by_url 96 | #download_playlist = site.download_by_url 97 | 98 | bokecc_download_by_id = site.download_by_id 99 | -------------------------------------------------------------------------------- /src/you_get/extractors/cbs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __all__ = ['cbs_download'] 4 | 5 | from ..common import * 6 | 7 | from .theplatform import theplatform_download_by_pid 8 | 9 | def cbs_download(url, output_dir='.', merge=True, info_only=False, **kwargs): 10 | """Downloads CBS videos by URL. 11 | """ 12 | 13 | html = get_content(url) 14 | pid = match1(html, r'video\.settings\.pid\s*=\s*\'([^\']+)\'') 15 | title = match1(html, r'video\.settings\.title\s*=\s*\"([^\"]+)\"') 16 | 17 | theplatform_download_by_pid(pid, title, output_dir=output_dir, merge=merge, info_only=info_only) 18 | 19 | site_info = "CBS.com" 20 | download = cbs_download 21 | download_playlist = playlist_not_supported('cbs') 22 | -------------------------------------------------------------------------------- /src/you_get/extractors/ckplayer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #coding:utf-8 3 | # Author: Beining -- 4 | # Purpose: A general extractor for CKPlayer 5 | # Created: 03/15/2016 6 | 7 | __all__ = ['ckplayer_download'] 8 | 9 | from xml.etree import cElementTree as ET 10 | from copy import copy 11 | from ..common import * 12 | #---------------------------------------------------------------------- 13 | def ckplayer_get_info_by_xml(ckinfo): 14 | """str->dict 15 | Information for CKPlayer API content.""" 16 | e = ET.XML(ckinfo) 17 | video_dict = {'title': '', 18 | #'duration': 0, 19 | 'links': [], 20 | 'size': 0, 21 | 'flashvars': '',} 22 | dictified = dictify(e)['ckplayer'] 23 | if 'info' in dictified: 24 | if '_text' in dictified['info'][0]['title'][0]: #title 25 | video_dict['title'] = dictified['info'][0]['title'][0]['_text'].strip() 26 | 27 | #if dictify(e)['ckplayer']['info'][0]['title'][0]['_text'].strip(): #duration 28 | #video_dict['title'] = dictify(e)['ckplayer']['info'][0]['title'][0]['_text'].strip() 29 | 30 | if '_text' in dictified['video'][0]['size'][0]: #size exists for 1 piece 31 | video_dict['size'] = sum([int(i['size'][0]['_text']) for i in dictified['video']]) 32 | 33 | if '_text' in dictified['video'][0]['file'][0]: #link exist 34 | video_dict['links'] = [i['file'][0]['_text'].strip() for i in dictified['video']] 35 | 36 | if '_text' in dictified['flashvars'][0]: 37 | video_dict['flashvars'] = dictified['flashvars'][0]['_text'].strip() 38 | 39 | return video_dict 40 | 41 | #---------------------------------------------------------------------- 42 | #helper 43 | #https://stackoverflow.com/questions/2148119/how-to-convert-an-xml-string-to-a-dictionary-in-python 44 | def dictify(r,root=True): 45 | if root: 46 | return {r.tag : dictify(r, False)} 47 | d=copy(r.attrib) 48 | if r.text: 49 | d["_text"]=r.text 50 | for x in r.findall("./*"): 51 | if x.tag not in d: 52 | d[x.tag]=[] 53 | d[x.tag].append(dictify(x,False)) 54 | return d 55 | 56 | #---------------------------------------------------------------------- 57 | def ckplayer_download_by_xml(ckinfo, output_dir = '.', merge = False, info_only = False, **kwargs): 58 | #Info XML 59 | video_info = ckplayer_get_info_by_xml(ckinfo) 60 | 61 | try: 62 | title = kwargs['title'] 63 | except: 64 | title = '' 65 | type_ = '' 66 | size = 0 67 | 68 | if len(video_info['links']) > 0: #has link 69 | type_, _ext, size = url_info(video_info['links'][0]) #use 1st to determine type, ext 70 | 71 | if 'size' in video_info: 72 | size = int(video_info['size']) 73 | else: 74 | for i in video_info['links'][1:]: #save 1st one 75 | size += url_info(i)[2] 76 | 77 | print_info(site_info, title, type_, size) 78 | if not info_only: 79 | download_urls(video_info['links'], title, _ext, size, output_dir=output_dir, merge=merge) 80 | 81 | #---------------------------------------------------------------------- 82 | def ckplayer_download(url, output_dir = '.', merge = False, info_only = False, is_xml = True, **kwargs): 83 | if is_xml: #URL is XML URL 84 | try: 85 | title = kwargs['title'] 86 | except: 87 | title = '' 88 | try: 89 | headers = kwargs['headers'] #headers provided 90 | ckinfo = get_content(url, headers = headers) 91 | except NameError: 92 | ckinfo = get_content(url) 93 | 94 | ckplayer_download_by_xml(ckinfo, output_dir, merge, 95 | info_only, title = title) 96 | 97 | site_info = "CKPlayer General" 98 | download = ckplayer_download 99 | download_playlist = playlist_not_supported('ckplayer') 100 | -------------------------------------------------------------------------------- /src/you_get/extractors/cntv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import json 4 | import re 5 | 6 | from ..common import get_content, r1, match1, playlist_not_supported 7 | from ..extractor import VideoExtractor 8 | 9 | __all__ = ['cntv_download', 'cntv_download_by_id'] 10 | 11 | 12 | class CNTV(VideoExtractor): 13 | name = 'CNTV.com' 14 | stream_types = [ 15 | {'id': '1', 'video_profile': '1280x720_2000kb/s', 'map_to': 'chapters4'}, 16 | {'id': '2', 'video_profile': '1280x720_1200kb/s', 'map_to': 'chapters3'}, 17 | {'id': '3', 'video_profile': '640x360_850kb/s', 'map_to': 'chapters2'}, 18 | {'id': '4', 'video_profile': '480x270_450kb/s', 'map_to': 'chapters'}, 19 | {'id': '5', 'video_profile': '320x180_200kb/s', 'map_to': 'lowChapters'}, 20 | ] 21 | 22 | ep = 'http://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?pid={}' 23 | 24 | def __init__(self): 25 | super().__init__() 26 | self.api_data = None 27 | 28 | def prepare(self, **kwargs): 29 | self.api_data = json.loads(get_content(self.__class__.ep.format(self.vid))) 30 | self.title = self.api_data['title'] 31 | for s in self.api_data['video']: 32 | for st in self.__class__.stream_types: 33 | if st['map_to'] == s: 34 | urls = self.api_data['video'][s] 35 | src = [u['url'] for u in urls] 36 | stream_data = dict(src=src, size=0, container='mp4', video_profile=st['video_profile']) 37 | self.streams[st['id']] = stream_data 38 | 39 | 40 | def cntv_download_by_id(rid, **kwargs): 41 | CNTV().download_by_vid(rid, **kwargs) 42 | 43 | 44 | def cntv_download(url, **kwargs): 45 | if re.match(r'http://tv\.cntv\.cn/video/(\w+)/(\w+)', url): 46 | rid = match1(url, r'http://tv\.cntv\.cn/video/\w+/(\w+)') 47 | elif re.match(r'http://tv\.cctv\.com/\d+/\d+/\d+/\w+.shtml', url): 48 | rid = r1(r'var guid = "(\w+)"', get_content(url)) 49 | elif re.match(r'http://\w+\.cntv\.cn/(\w+/\w+/(classpage/video/)?)?\d+/\d+\.shtml', url) or \ 50 | re.match(r'http://\w+.cntv.cn/(\w+/)*VIDE\d+.shtml', url) or \ 51 | re.match(r'http://(\w+).cntv.cn/(\w+)/classpage/video/(\d+)/(\d+).shtml', url) or \ 52 | re.match(r'http://\w+.cctv.com/\d+/\d+/\d+/\w+.shtml', url) or \ 53 | re.match(r'http://\w+.cntv.cn/\d+/\d+/\d+/\w+.shtml', url): 54 | page = get_content(url) 55 | rid = r1(r'videoCenterId","(\w+)"', page) 56 | if rid is None: 57 | guid = re.search(r'guid\s*=\s*"([0-9a-z]+)"', page).group(1) 58 | rid = guid 59 | elif re.match(r'http://xiyou.cntv.cn/v-[\w-]+\.html', url): 60 | rid = r1(r'http://xiyou.cntv.cn/v-([\w-]+)\.html', url) 61 | else: 62 | raise NotImplementedError(url) 63 | 64 | CNTV().download_by_vid(rid, **kwargs) 65 | 66 | site_info = "CNTV.com" 67 | download = cntv_download 68 | download_playlist = playlist_not_supported('cntv') 69 | -------------------------------------------------------------------------------- /src/you_get/extractors/dailymotion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __all__ = ['dailymotion_download'] 4 | 5 | from ..common import * 6 | import urllib.parse 7 | 8 | def rebuilt_url(url): 9 | path = urllib.parse.urlparse(url).path 10 | aid = path.split('/')[-1].split('_')[0] 11 | return 'http://www.dailymotion.com/embed/video/{}?autoplay=1'.format(aid) 12 | 13 | def dailymotion_download(url, output_dir='.', merge=True, info_only=False, **kwargs): 14 | """Downloads Dailymotion videos by URL. 15 | """ 16 | 17 | html = get_content(rebuilt_url(url)) 18 | info = json.loads(match1(html, r'qualities":({.+?}),"')) 19 | title = match1(html, r'"video_title"\s*:\s*"([^"]+)"') or \ 20 | match1(html, r'"title"\s*:\s*"([^"]+)"') 21 | title = unicodize(title) 22 | 23 | for quality in ['1080','720','480','380','240','144','auto']: 24 | try: 25 | real_url = info[quality][1]["url"] 26 | if real_url: 27 | break 28 | except KeyError: 29 | pass 30 | 31 | mime, ext, size = url_info(real_url) 32 | 33 | print_info(site_info, title, mime, size) 34 | if not info_only: 35 | download_urls([real_url], title, ext, size, output_dir=output_dir, merge=merge) 36 | 37 | site_info = "Dailymotion.com" 38 | download = dailymotion_download 39 | download_playlist = playlist_not_supported('dailymotion') 40 | -------------------------------------------------------------------------------- /src/you_get/extractors/dilidili.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __all__ = ['dilidili_download'] 4 | 5 | from ..common import * 6 | from .ckplayer import ckplayer_download 7 | 8 | headers = { 9 | 'DNT': '1', 10 | 'Accept-Encoding': 'gzip, deflate, sdch, br', 11 | 'Accept-Language': 'en-CA,en;q=0.8,en-US;q=0.6,zh-CN;q=0.4,zh;q=0.2', 12 | 'Upgrade-Insecure-Requests': '1', 13 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36', 14 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 15 | 'Cache-Control': 'max-age=0', 16 | 'Referer': 'http://www.dilidili.com/', 17 | 'Connection': 'keep-alive', 18 | 'Save-Data': 'on', 19 | } 20 | 21 | #---------------------------------------------------------------------- 22 | def dilidili_parser_data_to_stream_types(typ ,vid ,hd2 ,sign, tmsign, ulk): 23 | """->list""" 24 | another_url = 'https://newplayer.jfrft.com/parse.php?xmlurl=null&type={typ}&vid={vid}&hd={hd2}&sign={sign}&tmsign={tmsign}&userlink={ulk}'.format(typ = typ, vid = vid, hd2 = hd2, sign = sign, tmsign = tmsign, ulk = ulk) 25 | parse_url = 'http://player.005.tv/parse.php?xmlurl=null&type={typ}&vid={vid}&hd={hd2}&sign={sign}&tmsign={tmsign}&userlink={ulk}'.format(typ = typ, vid = vid, hd2 = hd2, sign = sign, tmsign = tmsign, ulk = ulk) 26 | html = get_content(another_url, headers=headers) 27 | 28 | info = re.search(r'(\{[^{]+\})(\{[^{]+\})(\{[^{]+\})(\{[^{]+\})(\{[^{]+\})', html).groups() 29 | info = [i.strip('{}').split('->') for i in info] 30 | info = {i[0]: i [1] for i in info} 31 | 32 | stream_types = [] 33 | for i in zip(info['deft'].split('|'), info['defa'].split('|')): 34 | stream_types.append({'id': str(i[1][-1]), 'container': 'mp4', 'video_profile': i[0]}) 35 | return stream_types 36 | 37 | #---------------------------------------------------------------------- 38 | def dilidili_download(url, output_dir = '.', merge = False, info_only = False, **kwargs): 39 | global headers 40 | re_str = r'http://www.dilidili.com/watch\S+' 41 | if re.match(r'http://www.dilidili.wang', url): 42 | re_str = r'http://www.dilidili.wang/watch\S+' 43 | headers['Referer'] = 'http://www.dilidili.wang/' 44 | elif re.match(r'http://www.dilidili.mobi', url): 45 | re_str = r'http://www.dilidili.mobi/watch\S+' 46 | headers['Referer'] = 'http://www.dilidili.mobi/' 47 | 48 | if re.match(re_str, url): 49 | html = get_content(url) 50 | title = match1(html, r'(.+)丨(.+)') #title 51 | 52 | # player loaded via internal iframe 53 | frame_url = re.search(r'