From 7a9855f2693c70cb6b2b8ca865920492cccc248c Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Sun, 20 Jul 2014 15:15:33 +0200 Subject: [PATCH 01/18] Prompt for alternative audio languages, fix #369 --- src/you_get/common.py | 16 +++++++++++++--- src/you_get/extractor/youku.py | 5 +++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/you_get/common.py b/src/you_get/common.py index d04c7ad7..deb1c24e 100644 --- a/src/you_get/common.py +++ b/src/you_get/common.py @@ -838,7 +838,7 @@ def script_main(script_name, download, download_playlist = None): ''' short_opts = 'Vhfiuc:nSF:o:p:x:y:' - opts = ['version', 'help', 'force', 'info', 'url', 'cookies', 'no-merge', 'no-proxy', 'debug', 'sogou', 'format=', 'stream=', 'itag=', 'output-dir=', 'player=', 'http-proxy=', 'extractor-proxy=', 'sogou-proxy=', 'sogou-env='] + opts = ['version', 'help', 'force', 'info', 'url', 'cookies', 'no-merge', 'no-proxy', 'debug', 'sogou', 'format=', 'stream=', 'itag=', 'output-dir=', 'player=', 'http-proxy=', 'extractor-proxy=', 'sogou-proxy=', 'sogou-env=', 'lang='] if download_playlist: short_opts = 'l' + short_opts opts = ['playlist'] + opts @@ -863,6 +863,7 @@ def script_main(script_name, download, download_playlist = None): playlist = False merge = True stream_id = None + lang = None output_dir = '.' proxy = None extractor_proxy = None @@ -909,6 +910,8 @@ def script_main(script_name, download, download_playlist = None): sogou_proxy = parse_host(a) elif o in ('--sogou-env',): sogou_env = a + elif o in ('--lang',): + lang = a else: log.e("try 'you-get --help' for more options") sys.exit(2) @@ -933,9 +936,9 @@ def script_main(script_name, download, download_playlist = None): try: if stream_id: - download_main(download, download_playlist, args, playlist, stream_id=stream_id, output_dir=output_dir, merge=merge, info_only=info_only) + download_main(download, download_playlist, args, playlist, stream_id=stream_id, lang=lang, output_dir=output_dir, merge=merge, info_only=info_only) else: - download_main(download, download_playlist, args, playlist, output_dir=output_dir, merge=merge, info_only=info_only) + download_main(download, download_playlist, args, playlist, lang=lang, output_dir=output_dir, merge=merge, info_only=info_only) except KeyboardInterrupt: if traceback: raise @@ -965,6 +968,7 @@ class VideoExtractor(): self.vid = None self.streams = {} self.streams_sorted = [] + self.audiolang = None if args: self.url = args[0] @@ -1068,6 +1072,12 @@ class VideoExtractor(): for stream in self.streams_sorted: self.p_stream(stream['id'] if 'id' in stream else stream['itag']) + if self.audiolang: + print("audio-languages:") + for i in self.audiolang: + print(" - lang: {}".format(i['lang'])) + print(" download-url: {}\n".format(i['url'])) + def p_playlist(self, stream_id=None): print("site: %s" % self.__class__.name) print("playlist: %s" % self.title) diff --git a/src/you_get/extractor/youku.py b/src/you_get/extractor/youku.py index b7460714..2cb7a5ce 100644 --- a/src/you_get/extractor/youku.py +++ b/src/you_get/extractor/youku.py @@ -63,6 +63,11 @@ class Youku(VideoExtractor): self.title = metadata0['title'] + if 'dvd' in metadata0 and 'audiolang' in metadata0['dvd']: + self.audiolang = metadata0['dvd']['audiolang'] + for i in self.audiolang: + i['url'] = 'http://v.youku.com/v_show/id_{}'.format(i['vid']) + for stream_type in self.stream_types: if stream_type['id'] in metadata0['streamsizes']: stream_id = stream_type['id'] From cebaa890f4566830f3860f555a9fe65478f11d11 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Sun, 20 Jul 2014 15:36:29 +0200 Subject: [PATCH 02/18] id -> format --- src/you_get/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/you_get/common.py b/src/you_get/common.py index deb1c24e..d2ab5c7b 100644 --- a/src/you_get/common.py +++ b/src/you_get/common.py @@ -1024,7 +1024,7 @@ class VideoExtractor(): if 'itag' in stream: print(" - itag: \033[7m%s\033[0m" % stream_id) else: - print(" - id: \033[7m%s\033[0m" % stream_id) + print(" - format: \033[7m%s\033[0m" % stream_id) if 'container' in stream: print(" container: %s" % stream['container']) From 2adc337093174382c31aece57d1d050bf894acba Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Sun, 20 Jul 2014 16:10:41 +0200 Subject: [PATCH 03/18] add classifier: "Programming Language :: Python :: 3.4" --- you-get.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/you-get.json b/you-get.json index dc988868..d5c1190a 100644 --- a/you-get.json +++ b/you-get.json @@ -4,10 +4,10 @@ "author_email": "mort.yao@gmail.com", "url": "http://www.soimort.org/you-get/", "license": "MIT", - + "description": "A YouTube/Youku/Niconico video downloader written in Python 3.", "keywords": "video download youtube youku niconico", - + "classifiers": [ "Development Status :: 2 - Pre-Alpha", "Environment :: Console", @@ -23,13 +23,14 @@ "Programming Language :: Python :: 3.1", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", "Topic :: Internet", "Topic :: Internet :: WWW/HTTP", "Topic :: Multimedia", "Topic :: Multimedia :: Video", "Topic :: Utilities" ], - + "console_scripts": [ "you-get = you_get.extractor.__main__:main" ] From c3b56def6d28a05135cea976f4cbb17cfc112558 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Sun, 20 Jul 2014 21:26:47 +0200 Subject: [PATCH 04/18] remove sogou_proxy --- README.md | 2 - README.txt | 2 - src/you_get/common.py | 49 ++--------- src/you_get/extractor/sohu.py | 13 --- src/you_get/util/__init__.py | 1 - src/you_get/util/sogou_proxy.py | 141 -------------------------------- 6 files changed, 6 insertions(+), 202 deletions(-) delete mode 100644 src/you_get/util/sogou_proxy.py diff --git a/README.md b/README.md index fe312c72..8a9ac7cc 100644 --- a/README.md +++ b/README.md @@ -186,8 +186,6 @@ For a complete list of all available options, see: -x | --http-proxy Use specific HTTP proxy for downloading. -y | --extractor-proxy Use specific HTTP proxy for extracting stream data. --no-proxy Don't use any proxy. (ignore $http_proxy) - -S | --sogou Use a Sogou proxy server for downloading. - --sogou-proxy Run a standalone Sogou proxy server. --debug Show traceback on KeyboardInterrupt. ## License diff --git a/README.txt b/README.txt index f6106aed..f8ffd878 100644 --- a/README.txt +++ b/README.txt @@ -194,8 +194,6 @@ For a complete list of all available options, see:: -x | --http-proxy Use specific HTTP proxy for downloading. -y | --extractor-proxy Use specific HTTP proxy for extracting stream data. --no-proxy Don't use any proxy. (ignore $http_proxy) - -S | --sogou Use a Sogou proxy server for downloading. - --sogou-proxy Run a standalone Sogou proxy server. --debug Show traceback on KeyboardInterrupt. License diff --git a/src/you_get/common.py b/src/you_get/common.py index d2ab5c7b..253e0a18 100644 --- a/src/you_get/common.py +++ b/src/you_get/common.py @@ -11,14 +11,13 @@ import platform import threading from .version import __version__ -from .util import log, sogou_proxy_server, get_filename, unescape_html +from .util import log +from .util.strings import get_filename, unescape_html dry_run = False force = False player = None extractor_proxy = None -sogou_proxy = None -sogou_env = None cookies_txt = None fake_headers = { @@ -764,9 +763,6 @@ def parse_host(host): port = o.port or 0 return (hostname, port) -def get_sogou_proxy(): - return sogou_proxy - def set_proxy(proxy): proxy_handler = request.ProxyHandler({ 'http': '%s:%s' % proxy, @@ -803,16 +799,6 @@ def download_main(download, download_playlist, urls, playlist, **kwargs): else: download(url, **kwargs) -def get_version(): - try: - import subprocess - real_dir = os.path.dirname(os.path.realpath(__file__)) - git_hash = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], cwd=real_dir, stderr=subprocess.DEVNULL).decode('utf-8').strip() - assert git_hash - return '%s-%s' % (__version__, git_hash) - except: - return __version__ - def script_main(script_name, download, download_playlist = None): version = 'You-Get %s, a video downloader.' % get_version() help = 'Usage: %s [OPTION]... [URL]...\n' % script_name @@ -832,13 +818,11 @@ def script_main(script_name, download, download_playlist = None): -x | --http-proxy Use specific HTTP proxy for downloading. -y | --extractor-proxy Use specific HTTP proxy for extracting stream data. --no-proxy Don't use any proxy. (ignore $http_proxy) - -S | --sogou Use a Sogou proxy server for downloading. - --sogou-proxy Run a standalone Sogou proxy server. --debug Show traceback on KeyboardInterrupt. ''' - short_opts = 'Vhfiuc:nSF:o:p:x:y:' - opts = ['version', 'help', 'force', 'info', 'url', 'cookies', 'no-merge', 'no-proxy', 'debug', 'sogou', 'format=', 'stream=', 'itag=', 'output-dir=', 'player=', 'http-proxy=', 'extractor-proxy=', 'sogou-proxy=', 'sogou-env=', 'lang='] + short_opts = 'Vhfiuc:nF:o:p:x:y:' + opts = ['version', 'help', 'force', 'info', 'url', 'cookies', 'no-merge', 'no-proxy', 'debug', 'format=', 'stream=', 'itag=', 'output-dir=', 'player=', 'http-proxy=', 'extractor-proxy=', 'lang='] if download_playlist: short_opts = 'l' + short_opts opts = ['playlist'] + opts @@ -854,8 +838,6 @@ def script_main(script_name, download, download_playlist = None): global dry_run global player global extractor_proxy - global sogou_proxy - global sogou_env global cookies_txt cookies_txt = None @@ -904,33 +886,14 @@ def script_main(script_name, download, download_playlist = None): proxy = a elif o in ('-y', '--extractor-proxy'): extractor_proxy = a - elif o in ('-S', '--sogou'): - sogou_proxy = ("0.0.0.0", 0) - elif o in ('--sogou-proxy',): - sogou_proxy = parse_host(a) - elif o in ('--sogou-env',): - sogou_env = a elif o in ('--lang',): lang = a else: log.e("try 'you-get --help' for more options") sys.exit(2) if not args: - if sogou_proxy is not None: - try: - if sogou_env is not None: - server = sogou_proxy_server(sogou_proxy, network_env=sogou_env) - else: - server = sogou_proxy_server(sogou_proxy) - server.serve_forever() - except KeyboardInterrupt: - if traceback: - raise - else: - sys.exit() - else: - print(help) - sys.exit() + print(help) + sys.exit() set_http_proxy(proxy) diff --git a/src/you_get/extractor/sohu.py b/src/you_get/extractor/sohu.py index 9a1e109b..6ee472e0 100644 --- a/src/you_get/extractor/sohu.py +++ b/src/you_get/extractor/sohu.py @@ -19,14 +19,6 @@ def sohu_download(url, output_dir = '.', merge = True, info_only = False): vid = r1(r'\Wvid\s*[\:=]\s*[\'"]?(\d+)[\'"]?', html) assert vid - # Open Sogou proxy if required - if get_sogou_proxy() is not None: - server = sogou_proxy_server(get_sogou_proxy(), ostream=open(os.devnull, 'w')) - server_thread = threading.Thread(target=server.serve_forever) - server_thread.daemon = True - server_thread.start() - set_proxy(server.server_address) - if re.match(r'http://tv.sohu.com/', url): data = json.loads(get_decoded_html('http://hot.vrs.sohu.com/vrs_flash.action?vid=%s' % vid)) for qtyp in ["oriVid","superVid","highVid" ,"norVid","relativeId"]: @@ -58,11 +50,6 @@ def sohu_download(url, output_dir = '.', merge = True, info_only = False): urls.append(real_url(host, prot, file, new)) assert data['clipsURL'][0].endswith('.mp4') - # Close Sogou proxy if required - if get_sogou_proxy() is not None: - server.shutdown() - unset_proxy() - print_info(site_info, title, 'mp4', size) if not info_only: download_urls(urls, title, 'mp4', size, output_dir, refer = url, merge = merge) diff --git a/src/you_get/util/__init__.py b/src/you_get/util/__init__.py index 947ea465..5345f0ac 100644 --- a/src/you_get/util/__init__.py +++ b/src/you_get/util/__init__.py @@ -2,5 +2,4 @@ from .fs import * from .log import * -from .sogou_proxy import * from .strings import * diff --git a/src/you_get/util/sogou_proxy.py b/src/you_get/util/sogou_proxy.py deleted file mode 100644 index 01ffb572..00000000 --- a/src/you_get/util/sogou_proxy.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python - -# Original code from: -# http://xiaoxia.org/2011/03/26/using-python-to-write-a-local-sogou-proxy-server-procedures/ - -from . import log - -from http.client import HTTPResponse -from http.server import BaseHTTPRequestHandler, HTTPServer -from socketserver import ThreadingMixIn -from threading import Thread -import random, socket, struct, sys, time - -def sogou_proxy_server( - host=("0.0.0.0", 0), - network_env='CERNET', - ostream=sys.stderr): - """Returns a Sogou proxy server object. - """ - - x_sogou_auth = '9CD285F1E7ADB0BD403C22AD1D545F40/30/853edc6d49ba4e27' - proxy_host = 'h0.cnc.bj.ie.sogou.com' - proxy_port = 80 - - def sogou_hash(t, host): - s = (t + host + 'SogouExplorerProxy').encode('ascii') - code = len(s) - dwords = int(len(s) / 4) - rest = len(s) % 4 - v = struct.unpack(str(dwords) + 'i' + str(rest) + 's', s) - for vv in v: - if type(vv) != bytes: - a = (vv & 0xFFFF) - b = (vv >> 16) - code += a - code = code ^ (((code << 5) ^ b) << 0xb) - # To avoid overflows - code &= 0xffffffff - code += code >> 0xb - if rest == 3: - code += s[len(s) - 2] * 256 + s[len(s) - 3] - code = code ^ ((code ^ (s[len(s) - 1]) * 4) << 0x10) - code &= 0xffffffff - code += code >> 0xb - elif rest == 2: - code += (s[len(s) - 1]) * 256 + (s[len(s) - 2]) - code ^= code << 0xb - code &= 0xffffffff - code += code >> 0x11 - elif rest == 1: - code += s[len(s) - 1] - code ^= code << 0xa - code &= 0xffffffff - code += code >> 0x1 - code ^= code * 8 - code &= 0xffffffff - code += code >> 5 - code ^= code << 4 - code = code & 0xffffffff - code += code >> 0x11 - code ^= code << 0x19 - code = code & 0xffffffff - code += code >> 6 - code = code & 0xffffffff - return hex(code)[2:].rstrip('L').zfill(8) - - class Handler(BaseHTTPRequestHandler): - _socket = None - def do_proxy(self): - try: - if self._socket is None: - self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self._socket.connect((proxy_host, proxy_port)) - self._socket.send(self.requestline.encode('ascii') + b'\r\n') - log.d(self.requestline, ostream) - - # Add Sogou Verification Tags - self.headers['X-Sogou-Auth'] = x_sogou_auth - t = hex(int(time.time()))[2:].rstrip('L').zfill(8) - self.headers['X-Sogou-Tag'] = sogou_hash(t, self.headers['Host']) - self.headers['X-Sogou-Timestamp'] = t - self._socket.send(str(self.headers).encode('ascii') + b'\r\n') - - # Send POST data - if self.command == 'POST': - self._socket.send(self.rfile.read(int(self.headers['Content-Length']))) - response = HTTPResponse(self._socket, method=self.command) - response.begin() - - # Response - status = 'HTTP/1.1 %s %s' % (response.status, response.reason) - self.wfile.write(status.encode('ascii') + b'\r\n') - h = '' - for hh, vv in response.getheaders(): - if hh.upper() != 'TRANSFER-ENCODING': - h += hh + ': ' + vv + '\r\n' - self.wfile.write(h.encode('ascii') + b'\r\n') - while True: - response_data = response.read(8192) - if len(response_data) == 0: - break - self.wfile.write(response_data) - - except socket.error: - log.e('Socket error for ' + self.requestline, ostream) - - def do_POST(self): - self.do_proxy() - - def do_GET(self): - self.do_proxy() - - class ThreadingHTTPServer(ThreadingMixIn, HTTPServer): - pass - - # Server starts - log.printlog('Sogou Proxy Mini-Server', color='bold-green', ostream=ostream) - - try: - server = ThreadingHTTPServer(host, Handler) - except Exception as ex: - log.wtf("Socket error: %s" % ex, ostream) - exit(1) - host = server.server_address - - if network_env.upper() == 'CERNET': - proxy_host = 'h%s.edu.bj.ie.sogou.com' % random.randint(0, 10) - elif network_env.upper() == 'CTCNET': - proxy_host = 'h%s.ctc.bj.ie.sogou.com' % random.randint(0, 3) - elif network_env.upper() == 'CNCNET': - proxy_host = 'h%s.cnc.bj.ie.sogou.com' % random.randint(0, 3) - elif network_env.upper() == 'DXT': - proxy_host = 'h%s.dxt.bj.ie.sogou.com' % random.randint(0, 10) - else: - proxy_host = 'h%s.edu.bj.ie.sogou.com' % random.randint(0, 10) - - log.i('Remote host: %s' % log.underlined(proxy_host), ostream) - log.i('Proxy server running on %s' % - log.underlined("%s:%s" % host), ostream) - - return server From 8a032df683f6674f8ec4a92223d0d8ffa46fdda3 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Sun, 20 Jul 2014 21:43:17 +0200 Subject: [PATCH 05/18] fix NameError: name get_version is not defined --- src/you_get/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/you_get/common.py b/src/you_get/common.py index 253e0a18..f5df12d3 100644 --- a/src/you_get/common.py +++ b/src/you_get/common.py @@ -800,7 +800,7 @@ def download_main(download, download_playlist, urls, playlist, **kwargs): download(url, **kwargs) def script_main(script_name, download, download_playlist = None): - version = 'You-Get %s, a video downloader.' % get_version() + version = 'You-Get, a video downloader.' help = 'Usage: %s [OPTION]... [URL]...\n' % script_name help += '''\nStartup options: -V | --version Display the version and exit. From fb475bf0c20f2db166d389e14887f7cd709937c6 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Sun, 20 Jul 2014 21:52:04 +0200 Subject: [PATCH 06/18] fix version again --- src/you_get/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/you_get/common.py b/src/you_get/common.py index f5df12d3..cea87816 100644 --- a/src/you_get/common.py +++ b/src/you_get/common.py @@ -800,7 +800,7 @@ def download_main(download, download_playlist, urls, playlist, **kwargs): download(url, **kwargs) def script_main(script_name, download, download_playlist = None): - version = 'You-Get, a video downloader.' + version = 'You-Get %s, a video downloader.' % __version__ help = 'Usage: %s [OPTION]... [URL]...\n' % script_name help += '''\nStartup options: -V | --version Display the version and exit. From 03749ecb194ed5c5e200d4185191ebb071c89e19 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Sun, 20 Jul 2014 23:41:20 +0200 Subject: [PATCH 07/18] update util.log --- src/you_get/util/log.py | 191 +++++++++++++++++----------------------- 1 file changed, 79 insertions(+), 112 deletions(-) diff --git a/src/you_get/util/log.py b/src/you_get/util/log.py index 33c07f9d..97eb3784 100644 --- a/src/you_get/util/log.py +++ b/src/you_get/util/log.py @@ -1,130 +1,97 @@ #!/usr/bin/env python +# This file is Python 2 compliant. -from ..version import __name__ +from .. import __name__ as library_name -import os, sys, subprocess +import os, sys -# Is terminal ANSI/VT100 compatible -if os.getenv('TERM') in ( - 'xterm', - 'vt100', - 'linux', - 'eterm-color', - 'screen', - ): - has_colors = True -else: - try: - # Eshell - ppid = os.getppid() - has_colors = (subprocess.getoutput('ps -p %d -ocomm=' % ppid) - == 'emacs') - except: - has_colors = False +IS_ANSI_TERMINAL = os.getenv('TERM') in ( + 'eterm-color', + 'linux', + 'screen', + 'vt100', + 'xterm') -# ANSI/VT100 escape code -# http://en.wikipedia.org/wiki/ANSI_escape_code -colors = { - 'none': '', - 'reset': '\033[0m', +# ANSI escape code +# See +RESET = 0 +BOLD = 1 +UNDERLINE = 4 +NEGATIVE = 7 +NO_BOLD = 21 +NO_UNDERLINE = 24 +POSITIVE = 27 +BLACK = 30 +RED = 31 +GREEN = 32 +YELLOW = 33 +BLUE = 34 +MAGENTA = 35 +CYAN = 36 +LIGHT_GRAY = 37 +DEFAULT = 39 +BLACK_BACKGROUND = 40 +RED_BACKGROUND = 41 +GREEN_BACKGROUND = 42 +YELLOW_BACKGROUND = 43 +BLUE_BACKGROUND = 44 +MAGENTA_BACKGROUND = 45 +CYAN_BACKGROUND = 46 +LIGHT_GRAY_BACKGROUND = 47 +DEFAULT_BACKGROUND = 49 +DARK_GRAY = 90 # xterm +LIGHT_RED = 91 # xterm +LIGHT_GREEN = 92 # xterm +LIGHT_YELLOW = 93 # xterm +LIGHT_BLUE = 94 # xterm +LIGHT_MAGENTA = 95 # xterm +LIGHT_CYAN = 96 # xterm +WHITE = 97 # xterm +DARK_GRAY_BACKGROUND = 100 # xterm +LIGHT_RED_BACKGROUND = 101 # xterm +LIGHT_GREEN_BACKGROUND = 102 # xterm +LIGHT_YELLOW_BACKGROUND = 103 # xterm +LIGHT_BLUE_BACKGROUND = 104 # xterm +LIGHT_MAGENTA_BACKGROUND = 105 # xterm +LIGHT_CYAN_BACKGROUND = 106 # xterm +WHITE_BACKGROUND = 107 # xterm - 'black': '\033[30m', - 'bold-black': '\033[30;1m', - 'dark-gray': '\033[90m', - 'bold-dark-gray': '\033[90;1m', +def sprint(text, *colors): + """Format text with color or other effects into ANSI escaped string.""" + return "\33[{}m{content}\33[{}m".format(";".join([str(color) for color in colors]), RESET, content=text) if IS_ANSI_TERMINAL and colors else text - 'red': '\033[31m', - 'bold-red': '\033[31;1m', - 'light-red': '\033[91m', - 'bold-light-red': '\033[91;1m', +def println(text, *colors): + """Print text to standard output.""" + sys.stdout.write(sprint(text, *colors) + "\n") - 'green': '\033[32m', - 'bold-green': '\033[32;1m', - 'light-green': '\033[92m', - 'bold-light-green': '\033[92;1m', +def print_err(text, *colors): + """Print text to standard error.""" + sys.stderr.write(sprint(text, *colors) + "\n") - 'yellow': '\033[33m', - 'bold-yellow': '\033[33;1m', - 'light-yellow': '\033[93m', - 'bold-light-yellow': '\033[93;1m', +def print_log(text, *colors): + """Print a log message to standard error.""" + sys.stderr.write(sprint("{}: {}".format(library_name, text), *colors) + "\n") - 'blue': '\033[34m', - 'bold-blue': '\033[34;1m', - 'light-blue': '\033[94m', - 'bold-light-blue': '\033[94;1m', +def i(message): + """Print a normal log message.""" + print_log(message) - 'magenta': '\033[35m', - 'bold-magenta': '\033[35;1m', - 'light-magenta': '\033[95m', - 'bold-light-magenta': '\033[95;1m', +def d(message): + """Print a debug log message.""" + print_log(message, BLUE) - 'cyan': '\033[36m', - 'bold-cyan': '\033[36;1m', - 'light-cyan': '\033[96m', - 'bold-light-cyan': '\033[96;1m', +def w(message): + """Print a warning log message.""" + print_log(message, YELLOW) - 'light-gray': '\033[37m', - 'bold-light-gray': '\033[37;1m', - 'white': '\033[97m', - 'bold-white': '\033[97;1m', -} - -def underlined(text): - """Returns an underlined text. - """ - return "\33[4m%s\33[24m" % text if has_colors else text - -def println(text, color=None, ostream=sys.stdout): - """Prints a text line to stream. - """ - if has_colors and color in colors: - ostream.write("{0}{1}{2}\n".format(colors[color], text, colors['reset'])) - else: - ostream.write("{0}\n".format(text)) - -def printlog(message, color=None, ostream=sys.stderr): - """Prints a log message to stream. - """ - if has_colors and color in colors: - ostream.write("{0}{1}: {2}{3}\n".format(colors[color], __name__, message, colors['reset'])) - else: - ostream.write("{0}: {1}\n".format(__name__, message)) - -def i(message, ostream=sys.stderr): - """Sends an info log message. - """ - printlog(message, - None, - ostream=ostream) - -def d(message, ostream=sys.stderr): - """Sends a debug log message. - """ - printlog(message, - 'blue' if has_colors else None, - ostream=ostream) - -def w(message, ostream=sys.stderr): - """Sends a warning log message. - """ - printlog(message, - 'yellow' if has_colors else None, - ostream=ostream) - -def e(message, ostream=sys.stderr, exit_code=None): - """Sends an error log message. - """ - printlog(message, - 'bold-yellow' if has_colors else None, - ostream=ostream) +def e(message, exit_code=None): + """Print an error log message.""" + print_log(message, YELLOW, BOLD) if exit_code is not None: exit(exit_code) -def wtf(message, ostream=sys.stderr, exit_code=-1): - """What a Terrible Failure. - """ - printlog(message, - 'bold-red' if has_colors else None, - ostream=ostream) +def wtf(message, exit_code=-1): + """What a Terrible Failure!""" + print_log(message, RED, BOLD) if exit_code is not None: exit(exit_code) From cb9ccc91abc163c143c8b3d7eec6ea66fb8552e0 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Sun, 20 Jul 2014 23:41:54 +0200 Subject: [PATCH 08/18] update Makefile --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index fa3c7ce1..16f1388c 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ clean: zenity --question rm -fr build/ dist/ src/*.egg-info/ find . | grep __pycache__ | xargs rm -fr + find . | grep .pyc | xargs rm -f all: build sdist bdist bdist_egg From 4fa150f68b6b314e3ecdbcfe484337e9b46150df Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Mon, 21 Jul 2014 00:02:45 +0200 Subject: [PATCH 09/18] add util.git --- src/you_get/util/git.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/you_get/util/git.py diff --git a/src/you_get/util/git.py b/src/you_get/util/git.py new file mode 100644 index 00000000..01a8ce17 --- /dev/null +++ b/src/you_get/util/git.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python + +import os + +def get_head(repo_path): + """Get (branch, commit) from HEAD of a git repo.""" + ref = open(os.path.join(repo_path, '.git', 'HEAD'), 'r').read().strip()[5:].split('/') + return ref[-1], open(os.path.join(repo_path, '.git', *ref), 'r').read().strip()[:7] From e8bf96fc212225a6482fa1976ba8843e1f9a7082 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Mon, 21 Jul 2014 00:25:26 +0200 Subject: [PATCH 10/18] update util.git --- src/you_get/util/git.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/you_get/util/git.py b/src/you_get/util/git.py index 01a8ce17..6891709e 100644 --- a/src/you_get/util/git.py +++ b/src/you_get/util/git.py @@ -4,5 +4,10 @@ import os def get_head(repo_path): """Get (branch, commit) from HEAD of a git repo.""" - ref = open(os.path.join(repo_path, '.git', 'HEAD'), 'r').read().strip()[5:].split('/') - return ref[-1], open(os.path.join(repo_path, '.git', *ref), 'r').read().strip()[:7] + try: + ref = open(os.path.join(repo_path, '.git', 'HEAD'), 'r').read().strip()[5:].split('/') + branch = ref[-1] + commit = open(os.path.join(repo_path, '.git', *ref), 'r').read().strip()[:7] + return branch, commit + except: + return None From c1f33401377464c888e1ebe7baea823aa631bb71 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Mon, 21 Jul 2014 01:37:21 +0200 Subject: [PATCH 11/18] hotfix: unexpected keyword argument 'lang' --- src/you_get/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/you_get/common.py b/src/you_get/common.py index cea87816..1c20b538 100644 --- a/src/you_get/common.py +++ b/src/you_get/common.py @@ -899,9 +899,9 @@ def script_main(script_name, download, download_playlist = None): try: if stream_id: - download_main(download, download_playlist, args, playlist, stream_id=stream_id, lang=lang, output_dir=output_dir, merge=merge, info_only=info_only) + download_main(download, download_playlist, args, playlist, stream_id=stream_id, output_dir=output_dir, merge=merge, info_only=info_only) else: - download_main(download, download_playlist, args, playlist, lang=lang, output_dir=output_dir, merge=merge, info_only=info_only) + download_main(download, download_playlist, args, playlist, output_dir=output_dir, merge=merge, info_only=info_only) except KeyboardInterrupt: if traceback: raise From 13d40fa694de9bd6496c011206cd876b6ad37cc0 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Mon, 21 Jul 2014 02:39:40 +0200 Subject: [PATCH 12/18] Major refactoring * Change entry point to you_get.__main__:main * New entry point for development (you-get-dev): you_get.__main__:main_dev * you_get.extractor -> you_get.extractors --- src/you_get/__init__.py | 19 +- src/you_get/__main__.py | 91 ++++++ src/you_get/common.py | 270 +++++++----------- src/you_get/extractor.py | 179 ++++++++++++ src/you_get/extractor/__main__.py | 100 ------- .../{extractor => extractors}/__init__.py | 2 - .../{extractor => extractors}/acfun.py | 0 .../{extractor => extractors}/alive.py | 0 .../{extractor => extractors}/baidu.py | 1 - .../{extractor => extractors}/bilibili.py | 0 src/you_get/{extractor => extractors}/blip.py | 0 .../{extractor => extractors}/catfun.py | 0 src/you_get/{extractor => extractors}/cbs.py | 0 src/you_get/{extractor => extractors}/cntv.py | 0 .../{extractor => extractors}/coursera.py | 0 .../{extractor => extractors}/dailymotion.py | 0 .../{extractor => extractors}/douban.py | 0 src/you_get/{extractor => extractors}/ehow.py | 0 .../{extractor => extractors}/facebook.py | 0 .../{extractor => extractors}/freesound.py | 0 .../{extractor => extractors}/google.py | 0 .../{extractor => extractors}/ifeng.py | 0 .../{extractor => extractors}/instagram.py | 0 .../{extractor => extractors}/iqiyi.py | 0 src/you_get/{extractor => extractors}/joy.py | 0 .../{extractor => extractors}/jpopsuki.py | 0 src/you_get/{extractor => extractors}/khan.py | 0 src/you_get/{extractor => extractors}/ku6.py | 0 .../{extractor => extractors}/kugou.py | 0 src/you_get/{extractor => extractors}/kuwo.py | 0 src/you_get/{extractor => extractors}/letv.py | 0 .../{extractor => extractors}/magisto.py | 0 .../{extractor => extractors}/miomio.py | 0 .../{extractor => extractors}/mixcloud.py | 0 .../{extractor => extractors}/mtv81.py | 0 .../{extractor => extractors}/netease.py | 0 .../{extractor => extractors}/nicovideo.py | 0 src/you_get/{extractor => extractors}/pptv.py | 0 src/you_get/{extractor => extractors}/qq.py | 0 src/you_get/{extractor => extractors}/sina.py | 0 src/you_get/{extractor => extractors}/sohu.py | 0 .../{extractor => extractors}/songtaste.py | 0 .../{extractor => extractors}/soundcloud.py | 0 src/you_get/{extractor => extractors}/ted.py | 0 .../{extractor => extractors}/theplatform.py | 0 .../{extractor => extractors}/tudou.py | 0 .../{extractor => extractors}/tumblr.py | 0 .../{extractor => extractors}/vid48.py | 0 .../{extractor => extractors}/vimeo.py | 0 src/you_get/{extractor => extractors}/vine.py | 0 src/you_get/{extractor => extractors}/vk.py | 0 src/you_get/{extractor => extractors}/w56.py | 0 .../{extractor => extractors}/xiami.py | 0 .../{extractor => extractors}/yinyuetai.py | 0 .../{extractor => extractors}/youku.py | 1 + .../{extractor => extractors}/youtube.py | 1 + src/you_get/util/__init__.py | 5 - src/you_get/version.py | 6 +- you-get | 22 +- you-get-dev | 18 ++ you-get.json | 2 +- 61 files changed, 422 insertions(+), 295 deletions(-) create mode 100644 src/you_get/__main__.py create mode 100644 src/you_get/extractor.py delete mode 100644 src/you_get/extractor/__main__.py rename src/you_get/{extractor => extractors}/__init__.py (97%) rename src/you_get/{extractor => extractors}/acfun.py (100%) rename src/you_get/{extractor => extractors}/alive.py (100%) rename src/you_get/{extractor => extractors}/baidu.py (99%) rename src/you_get/{extractor => extractors}/bilibili.py (100%) rename src/you_get/{extractor => extractors}/blip.py (100%) rename src/you_get/{extractor => extractors}/catfun.py (100%) rename src/you_get/{extractor => extractors}/cbs.py (100%) rename src/you_get/{extractor => extractors}/cntv.py (100%) rename src/you_get/{extractor => extractors}/coursera.py (100%) rename src/you_get/{extractor => extractors}/dailymotion.py (100%) rename src/you_get/{extractor => extractors}/douban.py (100%) rename src/you_get/{extractor => extractors}/ehow.py (100%) rename src/you_get/{extractor => extractors}/facebook.py (100%) rename src/you_get/{extractor => extractors}/freesound.py (100%) rename src/you_get/{extractor => extractors}/google.py (100%) rename src/you_get/{extractor => extractors}/ifeng.py (100%) rename src/you_get/{extractor => extractors}/instagram.py (100%) rename src/you_get/{extractor => extractors}/iqiyi.py (100%) rename src/you_get/{extractor => extractors}/joy.py (100%) rename src/you_get/{extractor => extractors}/jpopsuki.py (100%) rename src/you_get/{extractor => extractors}/khan.py (100%) rename src/you_get/{extractor => extractors}/ku6.py (100%) rename src/you_get/{extractor => extractors}/kugou.py (100%) rename src/you_get/{extractor => extractors}/kuwo.py (100%) rename src/you_get/{extractor => extractors}/letv.py (100%) rename src/you_get/{extractor => extractors}/magisto.py (100%) rename src/you_get/{extractor => extractors}/miomio.py (100%) rename src/you_get/{extractor => extractors}/mixcloud.py (100%) rename src/you_get/{extractor => extractors}/mtv81.py (100%) rename src/you_get/{extractor => extractors}/netease.py (100%) rename src/you_get/{extractor => extractors}/nicovideo.py (100%) rename src/you_get/{extractor => extractors}/pptv.py (100%) rename src/you_get/{extractor => extractors}/qq.py (100%) rename src/you_get/{extractor => extractors}/sina.py (100%) rename src/you_get/{extractor => extractors}/sohu.py (100%) rename src/you_get/{extractor => extractors}/songtaste.py (100%) rename src/you_get/{extractor => extractors}/soundcloud.py (100%) rename src/you_get/{extractor => extractors}/ted.py (100%) rename src/you_get/{extractor => extractors}/theplatform.py (100%) rename src/you_get/{extractor => extractors}/tudou.py (100%) rename src/you_get/{extractor => extractors}/tumblr.py (100%) rename src/you_get/{extractor => extractors}/vid48.py (100%) rename src/you_get/{extractor => extractors}/vimeo.py (100%) rename src/you_get/{extractor => extractors}/vine.py (100%) rename src/you_get/{extractor => extractors}/vk.py (100%) rename src/you_get/{extractor => extractors}/w56.py (100%) rename src/you_get/{extractor => extractors}/xiami.py (100%) rename src/you_get/{extractor => extractors}/yinyuetai.py (100%) rename src/you_get/{extractor => extractors}/youku.py (99%) rename src/you_get/{extractor => extractors}/youtube.py (99%) create mode 100755 you-get-dev diff --git a/src/you_get/__init__.py b/src/you_get/__init__.py index f8ee6011..5da7138f 100644 --- a/src/you_get/__init__.py +++ b/src/you_get/__init__.py @@ -1,7 +1,18 @@ #!/usr/bin/env python +# This file is Python 2 compliant. -from .common import * -from .version import * +import sys -from .cli_wrapper import * -from .extractor import * +if sys.version_info[0] == 3: + #from .extractor import Extractor, VideoExtractor + #from .util import log + + from .__main__ import * + + #from .common import * + #from .version import * + #from .cli_wrapper import * + #from .extractor import * +else: + # Don't import anything. + pass diff --git a/src/you_get/__main__.py b/src/you_get/__main__.py new file mode 100644 index 00000000..027854a7 --- /dev/null +++ b/src/you_get/__main__.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python + +import getopt +import os +import platform +import sys +from .version import script_name, __version__ +from .util import git, log + +_options = [ + 'help', + 'version', + 'gui', + 'force', + 'playlists', +] +_short_options = 'hVgfl' + +_help = """Usage: {} [OPTION]... [URL]... +TODO +""".format(script_name) + +def main_dev(**kwargs): + """Main entry point. + you-get-dev + """ + + # Get (branch, commit) if running from a git repo. + head = git.get_head(kwargs['repo_path']) + + # Get options and arguments. + try: + opts, args = getopt.getopt(sys.argv[1:], _short_options, _options) + except getopt.GetoptError as e: + log.wtf(""" + [Fatal] {}. + Try '{} --help' for more options.""".format(e, script_name)) + + if not opts and not args: + # Display help. + print(_help) + # Enter GUI mode. + #from .gui import gui_main + #gui_main() + else: + conf = {} + for opt, arg in opts: + if opt in ('-h', '--help'): + # Display help. + print(_help) + + elif opt in ('-V', '--version'): + # Display version. + log.println("you-get:", log.BOLD) + log.println(" version: {}".format(__version__)) + if head is not None: + log.println(" branch: {}\n commit: {}".format(*head)) + else: + log.println(" branch: {}\n commit: {}".format("(stable)", "(tag v{})".format(__version__))) + + log.println(" platform: {}".format(platform.platform())) + log.println(" python: {}".format(sys.version.split('\n')[0])) + + elif opt in ('-g', '--gui'): + # Run using GUI. + conf['gui'] = True + + elif opt in ('-f', '--force'): + # Force download. + conf['force'] = True + + elif opt in ('-l', '--playlist', '--playlists'): + # Download playlist whenever possible. + conf['playlist'] = True + + if args: + if 'gui' in conf and conf['gui']: + # Enter GUI mode. + from .gui import gui_main + gui_main(*args, **conf) + else: + # Enter console mode. + from .console import console_main + console_main(*args, **conf) + +def main(**kwargs): + """Main entry point. + you-get (legacy) + """ + from .common import main + main() diff --git a/src/you_get/common.py b/src/you_get/common.py index 1c20b538..a7035bf5 100644 --- a/src/you_get/common.py +++ b/src/you_get/common.py @@ -4,11 +4,10 @@ import getopt import json import locale import os +import platform import re import sys from urllib import request, parse -import platform -import threading from .version import __version__ from .util import log @@ -751,6 +750,18 @@ def print_info(site_info, title, type, size): print("Size: ", round(size / 1048576, 2), "MiB (" + str(size) + " Bytes)") print() +def mime_to_container(mime): + mapping = { + 'video/3gpp': '3gp', + 'video/mp4': 'mp4', + 'video/webm': 'webm', + 'video/x-flv': 'flv', + } + if mime in mapping: + return mapping[mime] + else: + return mime.split('/')[1] + def parse_host(host): """Parses host name and port number from a string. """ @@ -787,6 +798,10 @@ def set_http_proxy(proxy): opener = request.build_opener(proxy_support) request.install_opener(opener) + + +from .extractors import * + def download_main(download, download_playlist, urls, playlist, **kwargs): for url in urls: if url.startswith('https://'): @@ -908,180 +923,93 @@ def script_main(script_name, download, download_playlist = None): else: sys.exit(1) +def url_to_module(url): + video_host = r1(r'https?://([^/]+)/', url) + video_url = r1(r'https?://[^/]+(.*)', url) + assert video_host and video_url, 'invalid url: ' + url + if video_host.endswith('.com.cn'): + video_host = video_host[:-3] + domain = r1(r'(\.[^.]+\.[^.]+)$', video_host) or video_host + assert domain, 'unsupported url: ' + url -def mime_to_container(mime): - mapping = { - 'video/3gpp': '3gp', - 'video/mp4': 'mp4', - 'video/webm': 'webm', - 'video/x-flv': 'flv', + k = r1(r'([^.]+)', domain) + downloads = { + '163': netease, + '56': w56, + 'acfun': acfun, + 'baidu': baidu, + 'bilibili': bilibili, + 'blip': blip, + 'catfun':catfun, + 'cntv': cntv, + 'cbs': cbs, + 'coursera': coursera, + 'dailymotion': dailymotion, + 'douban': douban, + 'ehow': ehow, + 'facebook': facebook, + 'freesound': freesound, + 'google': google, + 'iask': sina, + 'ifeng': ifeng, + 'in': alive, + 'instagram': instagram, + 'iqiyi': iqiyi, + 'joy': joy, + 'jpopsuki': jpopsuki, + 'kankanews': bilibili, + 'khanacademy': khan, + 'ku6': ku6, + 'kugou':kugou, + 'kuwo':kuwo, + 'letv': letv, + 'magisto': magisto, + 'miomio': miomio, + 'mixcloud': mixcloud, + 'mtv81': mtv81, + 'nicovideo': nicovideo, + 'pptv': pptv, + 'qq': qq, + 'sina': sina, + 'smgbb': bilibili, + 'sohu': sohu, + 'songtaste':songtaste, + 'soundcloud': soundcloud, + 'ted': ted, + 'theplatform': theplatform, + 'tudou': tudou, + 'tumblr': tumblr, + 'vid48': vid48, + 'vimeo': vimeo, + 'vine': vine, + 'vk': vk, + 'xiami': xiami, + 'yinyuetai': yinyuetai, + 'youku': youku, + 'youtu': youtube, + 'youtube': youtube, } - if mime in mapping: - return mapping[mime] + if k in downloads: + return downloads[k], url else: - return mime.split('/')[1] - - - -class VideoExtractor(): - def __init__(self, *args): - self.url = None - self.title = None - self.vid = None - self.streams = {} - self.streams_sorted = [] - self.audiolang = None - - if args: - self.url = args[0] - - def download_by_url(self, url, **kwargs): - self.url = url - - global extractor_proxy - if extractor_proxy: - set_proxy(parse_host(extractor_proxy)) - self.prepare(**kwargs) - - try: - 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] - except: - self.streams_sorted = [dict([('itag', stream_type['itag'])] + list(self.streams[stream_type['itag']].items())) for stream_type in self.__class__.stream_types if stream_type['itag'] in self.streams] - - self.extract(**kwargs) - if extractor_proxy: - unset_proxy() - - self.download(**kwargs) - - def download_by_vid(self, vid, **kwargs): - self.vid = vid - - global extractor_proxy - if extractor_proxy: - set_proxy(parse_host(extractor_proxy)) - self.prepare(**kwargs) - - try: - 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] - except: - self.streams_sorted = [dict([('itag', stream_type['itag'])] + list(self.streams[stream_type['itag']].items())) for stream_type in self.__class__.stream_types if stream_type['itag'] in self.streams] - - self.extract(**kwargs) - if extractor_proxy: - unset_proxy() - - self.download(**kwargs) - - def prepare(self, **kwargs): - pass - #raise NotImplementedError() - - def extract(self, **kwargs): - pass - #raise NotImplementedError() - - def p_stream(self, stream_id): - stream = self.streams[stream_id] - if 'itag' in stream: - print(" - itag: \033[7m%s\033[0m" % stream_id) + import http.client + conn = http.client.HTTPConnection(video_host) + conn.request("HEAD", video_url) + res = conn.getresponse() + location = res.getheader('location') + if location is None: + raise NotImplementedError(url) else: - print(" - format: \033[7m%s\033[0m" % stream_id) + return url_to_module(location) - if 'container' in stream: - print(" container: %s" % stream['container']) +def any_download(url, **kwargs): + m, url = url_to_module(url) + m.download(url, **kwargs) - if 'video_profile' in stream: - print(" video-profile: %s" % stream['video_profile']) +def any_download_playlist(url, **kwargs): + m, url = url_to_module(url) + m.download_playlist(url, **kwargs) - if 'quality' in stream: - print(" quality: %s" % stream['quality']) - - if 'size' in stream: - print(" size: %s MiB (%s bytes)" % (round(stream['size'] / 1048576, 1), stream['size'])) - - if 'itag' in stream: - print(" # download-with: \033[4myou-get --itag=%s [URL]\033[0m" % stream_id) - else: - print(" # download-with: \033[4myou-get --format=%s [URL]\033[0m" % stream_id) - - print() - - def p_i(self, stream_id): - stream = self.streams[stream_id] - print(" - title: %s" % self.title) - print(" size: %s MiB (%s bytes)" % (round(stream['size'] / 1048576, 1), stream['size'])) - print(" url: %s" % self.url) - print() - - def p(self, stream_id=None): - print("site: %s" % self.__class__.name) - print("title: %s" % self.title) - if stream_id: - # Print the stream - print("stream:") - self.p_stream(stream_id) - - elif stream_id is None: - # Print stream with best quality - print("stream: # Best quality") - stream_id = self.streams_sorted[0]['id'] if 'id' in self.streams_sorted[0] else self.streams_sorted[0]['itag'] - self.p_stream(stream_id) - - elif stream_id == []: - # Print all available streams - print("streams: # Available quality and codecs") - for stream in self.streams_sorted: - self.p_stream(stream['id'] if 'id' in stream else stream['itag']) - - if self.audiolang: - print("audio-languages:") - for i in self.audiolang: - print(" - lang: {}".format(i['lang'])) - print(" download-url: {}\n".format(i['url'])) - - def p_playlist(self, stream_id=None): - print("site: %s" % self.__class__.name) - print("playlist: %s" % self.title) - print("videos:") - - def download(self, **kwargs): - if 'info_only' in kwargs and kwargs['info_only']: - if 'stream_id' in kwargs and kwargs['stream_id']: - # Display the stream - stream_id = kwargs['stream_id'] - if 'index' not in kwargs: - self.p(stream_id) - else: - self.p_i(stream_id) - else: - # Display all available streams - if 'index' not in kwargs: - self.p([]) - else: - stream_id = self.streams_sorted[0]['id'] if 'id' in self.streams_sorted[0] else self.streams_sorted[0]['itag'] - self.p_i(stream_id) - - else: - if 'stream_id' in kwargs and kwargs['stream_id']: - # Download the stream - stream_id = kwargs['stream_id'] - else: - # Download stream with the best quality - stream_id = self.streams_sorted[0]['id'] if 'id' in self.streams_sorted[0] else self.streams_sorted[0]['itag'] - - if 'index' not in kwargs: - self.p(None) - else: - self.p_i(stream_id) - - urls = self.streams[stream_id]['src'] - if not urls: - log.e('[Failed] Cannot extract video source.') - log.e('This is most likely because the video has not been made available in your country.') - log.e('You may try to use a proxy via \'-y\' for extracting stream data.') - exit(1) - download_urls(urls, self.title, self.streams[stream_id]['container'], self.streams[stream_id]['size'], output_dir=kwargs['output_dir'], merge=kwargs['merge']) - - self.__init__() +def main(): + script_main('you-get', any_download, any_download_playlist) diff --git a/src/you_get/extractor.py b/src/you_get/extractor.py new file mode 100644 index 00000000..7c193db3 --- /dev/null +++ b/src/you_get/extractor.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python + +from .common import match1, download_urls +from .util import log + +class Extractor(): + def __init__(self, *args): + self.url = None + self.title = None + self.vid = None + self.streams = {} + self.streams_sorted = [] + + if args: + self.url = args[0] + +class VideoExtractor(): + def __init__(self, *args): + self.url = None + self.title = None + self.vid = None + self.streams = {} + self.streams_sorted = [] + self.audiolang = None + + if args: + self.url = args[0] + + def download_by_url(self, url, **kwargs): + self.url = url + + #global extractor_proxy + #if extractor_proxy: + # set_proxy(parse_host(extractor_proxy)) + self.prepare(**kwargs) + + try: + 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] + except: + self.streams_sorted = [dict([('itag', stream_type['itag'])] + list(self.streams[stream_type['itag']].items())) for stream_type in self.__class__.stream_types if stream_type['itag'] in self.streams] + + self.extract(**kwargs) + + #if extractor_proxy: + # unset_proxy() + + self.download(**kwargs) + + def download_by_vid(self, vid, **kwargs): + self.vid = vid + + #global extractor_proxy + #if extractor_proxy: + # set_proxy(parse_host(extractor_proxy)) + self.prepare(**kwargs) + + try: + 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] + except: + self.streams_sorted = [dict([('itag', stream_type['itag'])] + list(self.streams[stream_type['itag']].items())) for stream_type in self.__class__.stream_types if stream_type['itag'] in self.streams] + + self.extract(**kwargs) + #if extractor_proxy: + # unset_proxy() + + self.download(**kwargs) + + def prepare(self, **kwargs): + pass + #raise NotImplementedError() + + def extract(self, **kwargs): + pass + #raise NotImplementedError() + + def p_stream(self, stream_id): + stream = self.streams[stream_id] + if 'itag' in stream: + print(" - itag: \033[7m%s\033[0m" % stream_id) + else: + print(" - format: \033[7m%s\033[0m" % stream_id) + + if 'container' in stream: + print(" container: %s" % stream['container']) + + if 'video_profile' in stream: + print(" video-profile: %s" % stream['video_profile']) + + if 'quality' in stream: + print(" quality: %s" % stream['quality']) + + if 'size' in stream: + print(" size: %s MiB (%s bytes)" % (round(stream['size'] / 1048576, 1), stream['size'])) + + if 'itag' in stream: + print(" # download-with: \033[4myou-get --itag=%s [URL]\033[0m" % stream_id) + else: + print(" # download-with: \033[4myou-get --format=%s [URL]\033[0m" % stream_id) + + print() + + def p_i(self, stream_id): + stream = self.streams[stream_id] + print(" - title: %s" % self.title) + print(" size: %s MiB (%s bytes)" % (round(stream['size'] / 1048576, 1), stream['size'])) + print(" url: %s" % self.url) + print() + + def p(self, stream_id=None): + print("site: %s" % self.__class__.name) + print("title: %s" % self.title) + if stream_id: + # Print the stream + print("stream:") + self.p_stream(stream_id) + + elif stream_id is None: + # Print stream with best quality + print("stream: # Best quality") + stream_id = self.streams_sorted[0]['id'] if 'id' in self.streams_sorted[0] else self.streams_sorted[0]['itag'] + self.p_stream(stream_id) + + elif stream_id == []: + # Print all available streams + print("streams: # Available quality and codecs") + for stream in self.streams_sorted: + self.p_stream(stream['id'] if 'id' in stream else stream['itag']) + + if self.audiolang: + print("audio-languages:") + for i in self.audiolang: + print(" - lang: {}".format(i['lang'])) + print(" download-url: {}\n".format(i['url'])) + + def p_playlist(self, stream_id=None): + print("site: %s" % self.__class__.name) + print("playlist: %s" % self.title) + print("videos:") + + def download(self, **kwargs): + if 'info_only' in kwargs and kwargs['info_only']: + if 'stream_id' in kwargs and kwargs['stream_id']: + # Display the stream + stream_id = kwargs['stream_id'] + if 'index' not in kwargs: + self.p(stream_id) + else: + self.p_i(stream_id) + else: + # Display all available streams + if 'index' not in kwargs: + self.p([]) + else: + stream_id = self.streams_sorted[0]['id'] if 'id' in self.streams_sorted[0] else self.streams_sorted[0]['itag'] + self.p_i(stream_id) + + else: + if 'stream_id' in kwargs and kwargs['stream_id']: + # Download the stream + stream_id = kwargs['stream_id'] + else: + # Download stream with the best quality + stream_id = self.streams_sorted[0]['id'] if 'id' in self.streams_sorted[0] else self.streams_sorted[0]['itag'] + + if 'index' not in kwargs: + self.p(None) + else: + self.p_i(stream_id) + + urls = self.streams[stream_id]['src'] + if not urls: + log.e('[Failed] Cannot extract video source.') + log.e('This is most likely because the video has not been made available in your country.') + log.e('You may try to use a proxy via \'-y\' for extracting stream data.') + exit(1) + #download_urls(urls, self.title, self.streams[stream_id]['container'], self.streams[stream_id]['size'], output_dir=kwargs['output_dir'], merge=kwargs['merge']) + download_urls(urls, self.title, self.streams[stream_id]['container'], self.streams[stream_id]['size']) + + self.__init__() diff --git a/src/you_get/extractor/__main__.py b/src/you_get/extractor/__main__.py deleted file mode 100644 index 8bfc15cc..00000000 --- a/src/you_get/extractor/__main__.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python -__all__ = ['main', 'any_download', 'any_download_playlist'] - -from ..extractor import * -from ..common import * - -def url_to_module(url): - video_host = r1(r'https?://([^/]+)/', url) - video_url = r1(r'https?://[^/]+(.*)', url) - assert video_host and video_url, 'invalid url: ' + url - - if video_host.endswith('.com.cn'): - video_host = video_host[:-3] - domain = r1(r'(\.[^.]+\.[^.]+)$', video_host) or video_host - assert domain, 'unsupported url: ' + url - - k = r1(r'([^.]+)', domain) - downloads = { - '163': netease, - '56': w56, - 'acfun': acfun, - 'baidu': baidu, - 'bilibili': bilibili, - 'blip': blip, - 'catfun':catfun, - 'cntv': cntv, - 'cbs': cbs, - 'coursera': coursera, - 'dailymotion': dailymotion, - 'douban': douban, - 'ehow': ehow, - 'facebook': facebook, - 'freesound': freesound, - 'google': google, - 'iask': sina, - 'ifeng': ifeng, - 'in': alive, - 'instagram': instagram, - 'iqiyi': iqiyi, - 'joy': joy, - 'jpopsuki': jpopsuki, - 'kankanews': bilibili, - 'ku6': ku6, - 'kugou':kugou, - 'kuwo':kuwo, - 'letv': letv, - 'magisto': magisto, - 'miomio': miomio, - 'mixcloud': mixcloud, - 'mtv81':mtv81, - 'nicovideo': nicovideo, - 'pptv': pptv, - 'qq': qq, - 'sina': sina, - 'smgbb': bilibili, - 'sohu': sohu, - 'songtaste':songtaste, - 'soundcloud': soundcloud, - 'ted': ted, - 'theplatform': theplatform, - 'tudou': tudou, - 'tumblr': tumblr, - 'vid48': vid48, - 'vimeo': vimeo, - 'vine': vine, - 'vk': vk, - 'xiami': xiami, - 'yinyuetai': yinyuetai, - 'youku': youku, - 'youtu': youtube, - 'youtube': youtube, - 'khanacademy': khan, - #TODO - } - if k in downloads: - return downloads[k], url - else: - import http.client - conn = http.client.HTTPConnection(video_host) - conn.request("HEAD", video_url) - res = conn.getresponse() - location = res.getheader('location') - if location is None: - raise NotImplementedError(url) - else: - return url_to_module(location) - -def any_download(url, **kwargs): - m, url = url_to_module(url) - m.download(url, **kwargs) - -def any_download_playlist(url, **kwargs): - m, url = url_to_module(url) - m.download_playlist(url, **kwargs) - -def main(): - script_main('you-get', any_download, any_download_playlist) - -if __name__ == "__main__": - main() diff --git a/src/you_get/extractor/__init__.py b/src/you_get/extractors/__init__.py similarity index 97% rename from src/you_get/extractor/__init__.py rename to src/you_get/extractors/__init__.py index 628f4dbb..bcd926ff 100644 --- a/src/you_get/extractor/__init__.py +++ b/src/you_get/extractors/__init__.py @@ -50,5 +50,3 @@ from .youku import * from .youtube import * from .ted import * from .khan import * - -from .__main__ import * diff --git a/src/you_get/extractor/acfun.py b/src/you_get/extractors/acfun.py similarity index 100% rename from src/you_get/extractor/acfun.py rename to src/you_get/extractors/acfun.py diff --git a/src/you_get/extractor/alive.py b/src/you_get/extractors/alive.py similarity index 100% rename from src/you_get/extractor/alive.py rename to src/you_get/extractors/alive.py diff --git a/src/you_get/extractor/baidu.py b/src/you_get/extractors/baidu.py similarity index 99% rename from src/you_get/extractor/baidu.py rename to src/you_get/extractors/baidu.py index c671fa74..fdf58f28 100755 --- a/src/you_get/extractor/baidu.py +++ b/src/you_get/extractors/baidu.py @@ -4,7 +4,6 @@ __all__ = ['baidu_download'] from ..common import * -from .. import common from urllib import parse diff --git a/src/you_get/extractor/bilibili.py b/src/you_get/extractors/bilibili.py similarity index 100% rename from src/you_get/extractor/bilibili.py rename to src/you_get/extractors/bilibili.py diff --git a/src/you_get/extractor/blip.py b/src/you_get/extractors/blip.py similarity index 100% rename from src/you_get/extractor/blip.py rename to src/you_get/extractors/blip.py diff --git a/src/you_get/extractor/catfun.py b/src/you_get/extractors/catfun.py similarity index 100% rename from src/you_get/extractor/catfun.py rename to src/you_get/extractors/catfun.py diff --git a/src/you_get/extractor/cbs.py b/src/you_get/extractors/cbs.py similarity index 100% rename from src/you_get/extractor/cbs.py rename to src/you_get/extractors/cbs.py diff --git a/src/you_get/extractor/cntv.py b/src/you_get/extractors/cntv.py similarity index 100% rename from src/you_get/extractor/cntv.py rename to src/you_get/extractors/cntv.py diff --git a/src/you_get/extractor/coursera.py b/src/you_get/extractors/coursera.py similarity index 100% rename from src/you_get/extractor/coursera.py rename to src/you_get/extractors/coursera.py diff --git a/src/you_get/extractor/dailymotion.py b/src/you_get/extractors/dailymotion.py similarity index 100% rename from src/you_get/extractor/dailymotion.py rename to src/you_get/extractors/dailymotion.py diff --git a/src/you_get/extractor/douban.py b/src/you_get/extractors/douban.py similarity index 100% rename from src/you_get/extractor/douban.py rename to src/you_get/extractors/douban.py diff --git a/src/you_get/extractor/ehow.py b/src/you_get/extractors/ehow.py similarity index 100% rename from src/you_get/extractor/ehow.py rename to src/you_get/extractors/ehow.py diff --git a/src/you_get/extractor/facebook.py b/src/you_get/extractors/facebook.py similarity index 100% rename from src/you_get/extractor/facebook.py rename to src/you_get/extractors/facebook.py diff --git a/src/you_get/extractor/freesound.py b/src/you_get/extractors/freesound.py similarity index 100% rename from src/you_get/extractor/freesound.py rename to src/you_get/extractors/freesound.py diff --git a/src/you_get/extractor/google.py b/src/you_get/extractors/google.py similarity index 100% rename from src/you_get/extractor/google.py rename to src/you_get/extractors/google.py diff --git a/src/you_get/extractor/ifeng.py b/src/you_get/extractors/ifeng.py similarity index 100% rename from src/you_get/extractor/ifeng.py rename to src/you_get/extractors/ifeng.py diff --git a/src/you_get/extractor/instagram.py b/src/you_get/extractors/instagram.py similarity index 100% rename from src/you_get/extractor/instagram.py rename to src/you_get/extractors/instagram.py diff --git a/src/you_get/extractor/iqiyi.py b/src/you_get/extractors/iqiyi.py similarity index 100% rename from src/you_get/extractor/iqiyi.py rename to src/you_get/extractors/iqiyi.py diff --git a/src/you_get/extractor/joy.py b/src/you_get/extractors/joy.py similarity index 100% rename from src/you_get/extractor/joy.py rename to src/you_get/extractors/joy.py diff --git a/src/you_get/extractor/jpopsuki.py b/src/you_get/extractors/jpopsuki.py similarity index 100% rename from src/you_get/extractor/jpopsuki.py rename to src/you_get/extractors/jpopsuki.py diff --git a/src/you_get/extractor/khan.py b/src/you_get/extractors/khan.py similarity index 100% rename from src/you_get/extractor/khan.py rename to src/you_get/extractors/khan.py diff --git a/src/you_get/extractor/ku6.py b/src/you_get/extractors/ku6.py similarity index 100% rename from src/you_get/extractor/ku6.py rename to src/you_get/extractors/ku6.py diff --git a/src/you_get/extractor/kugou.py b/src/you_get/extractors/kugou.py similarity index 100% rename from src/you_get/extractor/kugou.py rename to src/you_get/extractors/kugou.py diff --git a/src/you_get/extractor/kuwo.py b/src/you_get/extractors/kuwo.py similarity index 100% rename from src/you_get/extractor/kuwo.py rename to src/you_get/extractors/kuwo.py diff --git a/src/you_get/extractor/letv.py b/src/you_get/extractors/letv.py similarity index 100% rename from src/you_get/extractor/letv.py rename to src/you_get/extractors/letv.py diff --git a/src/you_get/extractor/magisto.py b/src/you_get/extractors/magisto.py similarity index 100% rename from src/you_get/extractor/magisto.py rename to src/you_get/extractors/magisto.py diff --git a/src/you_get/extractor/miomio.py b/src/you_get/extractors/miomio.py similarity index 100% rename from src/you_get/extractor/miomio.py rename to src/you_get/extractors/miomio.py diff --git a/src/you_get/extractor/mixcloud.py b/src/you_get/extractors/mixcloud.py similarity index 100% rename from src/you_get/extractor/mixcloud.py rename to src/you_get/extractors/mixcloud.py diff --git a/src/you_get/extractor/mtv81.py b/src/you_get/extractors/mtv81.py similarity index 100% rename from src/you_get/extractor/mtv81.py rename to src/you_get/extractors/mtv81.py diff --git a/src/you_get/extractor/netease.py b/src/you_get/extractors/netease.py similarity index 100% rename from src/you_get/extractor/netease.py rename to src/you_get/extractors/netease.py diff --git a/src/you_get/extractor/nicovideo.py b/src/you_get/extractors/nicovideo.py similarity index 100% rename from src/you_get/extractor/nicovideo.py rename to src/you_get/extractors/nicovideo.py diff --git a/src/you_get/extractor/pptv.py b/src/you_get/extractors/pptv.py similarity index 100% rename from src/you_get/extractor/pptv.py rename to src/you_get/extractors/pptv.py diff --git a/src/you_get/extractor/qq.py b/src/you_get/extractors/qq.py similarity index 100% rename from src/you_get/extractor/qq.py rename to src/you_get/extractors/qq.py diff --git a/src/you_get/extractor/sina.py b/src/you_get/extractors/sina.py similarity index 100% rename from src/you_get/extractor/sina.py rename to src/you_get/extractors/sina.py diff --git a/src/you_get/extractor/sohu.py b/src/you_get/extractors/sohu.py similarity index 100% rename from src/you_get/extractor/sohu.py rename to src/you_get/extractors/sohu.py diff --git a/src/you_get/extractor/songtaste.py b/src/you_get/extractors/songtaste.py similarity index 100% rename from src/you_get/extractor/songtaste.py rename to src/you_get/extractors/songtaste.py diff --git a/src/you_get/extractor/soundcloud.py b/src/you_get/extractors/soundcloud.py similarity index 100% rename from src/you_get/extractor/soundcloud.py rename to src/you_get/extractors/soundcloud.py diff --git a/src/you_get/extractor/ted.py b/src/you_get/extractors/ted.py similarity index 100% rename from src/you_get/extractor/ted.py rename to src/you_get/extractors/ted.py diff --git a/src/you_get/extractor/theplatform.py b/src/you_get/extractors/theplatform.py similarity index 100% rename from src/you_get/extractor/theplatform.py rename to src/you_get/extractors/theplatform.py diff --git a/src/you_get/extractor/tudou.py b/src/you_get/extractors/tudou.py similarity index 100% rename from src/you_get/extractor/tudou.py rename to src/you_get/extractors/tudou.py diff --git a/src/you_get/extractor/tumblr.py b/src/you_get/extractors/tumblr.py similarity index 100% rename from src/you_get/extractor/tumblr.py rename to src/you_get/extractors/tumblr.py diff --git a/src/you_get/extractor/vid48.py b/src/you_get/extractors/vid48.py similarity index 100% rename from src/you_get/extractor/vid48.py rename to src/you_get/extractors/vid48.py diff --git a/src/you_get/extractor/vimeo.py b/src/you_get/extractors/vimeo.py similarity index 100% rename from src/you_get/extractor/vimeo.py rename to src/you_get/extractors/vimeo.py diff --git a/src/you_get/extractor/vine.py b/src/you_get/extractors/vine.py similarity index 100% rename from src/you_get/extractor/vine.py rename to src/you_get/extractors/vine.py diff --git a/src/you_get/extractor/vk.py b/src/you_get/extractors/vk.py similarity index 100% rename from src/you_get/extractor/vk.py rename to src/you_get/extractors/vk.py diff --git a/src/you_get/extractor/w56.py b/src/you_get/extractors/w56.py similarity index 100% rename from src/you_get/extractor/w56.py rename to src/you_get/extractors/w56.py diff --git a/src/you_get/extractor/xiami.py b/src/you_get/extractors/xiami.py similarity index 100% rename from src/you_get/extractor/xiami.py rename to src/you_get/extractors/xiami.py diff --git a/src/you_get/extractor/yinyuetai.py b/src/you_get/extractors/yinyuetai.py similarity index 100% rename from src/you_get/extractor/yinyuetai.py rename to src/you_get/extractors/yinyuetai.py diff --git a/src/you_get/extractor/youku.py b/src/you_get/extractors/youku.py similarity index 99% rename from src/you_get/extractor/youku.py rename to src/you_get/extractors/youku.py index 2cb7a5ce..8b4304e4 100644 --- a/src/you_get/extractor/youku.py +++ b/src/you_get/extractors/youku.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- from ..common import * +from ..extractor import VideoExtractor class Youku(VideoExtractor): name = "优酷 (Youku)" diff --git a/src/you_get/extractor/youtube.py b/src/you_get/extractors/youtube.py similarity index 99% rename from src/you_get/extractor/youtube.py rename to src/you_get/extractors/youtube.py index d419488f..ddd63cf0 100644 --- a/src/you_get/extractor/youtube.py +++ b/src/you_get/extractors/youtube.py @@ -1,6 +1,7 @@ #!/usr/bin/env python from ..common import * +from ..extractor import VideoExtractor class YouTube(VideoExtractor): name = "YouTube" diff --git a/src/you_get/util/__init__.py b/src/you_get/util/__init__.py index 5345f0ac..e69de29b 100644 --- a/src/you_get/util/__init__.py +++ b/src/you_get/util/__init__.py @@ -1,5 +0,0 @@ -#!/usr/bin/env python - -from .fs import * -from .log import * -from .strings import * diff --git a/src/you_get/version.py b/src/you_get/version.py index c3d6c953..f0e15558 100644 --- a/src/you_get/version.py +++ b/src/you_get/version.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -__all__ = ['__version__', '__date__'] -__name__ = 'you-get' -__version__ = '0.3.30dev-20140716' -__date__ = '2014-07-16' +script_name = 'you-get' +__version__ = '0.3.30dev' diff --git a/you-get b/you-get index 8bdc77c7..e576af99 100755 --- a/you-get +++ b/you-get @@ -1,10 +1,18 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python +# This file is Python 2 compliant. import os, sys -__path__ = os.path.dirname(os.path.realpath(__file__)) -__srcdir__ = 'src' -sys.path.insert(1, os.path.join(__path__, __srcdir__)) -from you_get.extractor import main -if __name__ == '__main__': - main() +_srcdir = 'src/' +_filepath = os.path.dirname(os.path.realpath(__file__)) +sys.path.insert(1, os.path.join(_filepath, _srcdir)) + +if sys.version_info[0] == 3: + import you_get + if __name__ == '__main__': + you_get.main(repo_path=_filepath) +else: + from you_get.util import log + log.wtf(""" + [Fatal] Python 3 is required. + If Python 3 is already installed on your machine, try to run this script using 'python3 you-get'.""") diff --git a/you-get-dev b/you-get-dev new file mode 100755 index 00000000..a63493b4 --- /dev/null +++ b/you-get-dev @@ -0,0 +1,18 @@ +#!/usr/bin/env python +# This file is Python 2 compliant. + +import os, sys + +_srcdir = 'src/' +_filepath = os.path.dirname(os.path.realpath(__file__)) +sys.path.insert(1, os.path.join(_filepath, _srcdir)) + +if sys.version_info[0] == 3: + import you_get + if __name__ == '__main__': + you_get.main_dev(repo_path=_filepath) +else: + from you_get.util import log + log.wtf(""" + [Fatal] Python 3 is required. + If Python 3 is already installed on your machine, try to run this script using 'python3 you-get'.""") diff --git a/you-get.json b/you-get.json index d5c1190a..f331b834 100644 --- a/you-get.json +++ b/you-get.json @@ -32,6 +32,6 @@ ], "console_scripts": [ - "you-get = you_get.extractor.__main__:main" + "you-get = you_get.__main__:main" ] } From 7f2f2035101089183460ebda9d710e80ab6ad40f Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Mon, 21 Jul 2014 03:17:30 +0200 Subject: [PATCH 13/18] fix tests --- src/you_get/common.py | 8 ++++---- tests/test.py | 40 ++++++++++++---------------------------- tests/test_common.py | 2 +- tests/test_util.py | 2 +- 4 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src/you_get/common.py b/src/you_get/common.py index a7035bf5..5f5228f9 100644 --- a/src/you_get/common.py +++ b/src/you_get/common.py @@ -941,7 +941,7 @@ def url_to_module(url): 'baidu': baidu, 'bilibili': bilibili, 'blip': blip, - 'catfun':catfun, + 'catfun': catfun, 'cntv': cntv, 'cbs': cbs, 'coursera': coursera, @@ -961,8 +961,8 @@ def url_to_module(url): 'kankanews': bilibili, 'khanacademy': khan, 'ku6': ku6, - 'kugou':kugou, - 'kuwo':kuwo, + 'kugou': kugou, + 'kuwo': kuwo, 'letv': letv, 'magisto': magisto, 'miomio': miomio, @@ -974,7 +974,7 @@ def url_to_module(url): 'sina': sina, 'smgbb': bilibili, 'sohu': sohu, - 'songtaste':songtaste, + 'songtaste': songtaste, 'soundcloud': soundcloud, 'ted': ted, 'theplatform': theplatform, diff --git a/tests/test.py b/tests/test.py index 0d51f86e..97fa58dd 100644 --- a/tests/test.py +++ b/tests/test.py @@ -1,47 +1,31 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import unittest from you_get import * -from you_get.extractor.__main__ import url_to_module - -def test_urls(urls): - for url in urls: - url_to_module(url)[0].download(url, info_only = True) +from you_get.extractors import * +from you_get.common import * class YouGetTests(unittest.TestCase): def test_freesound(self): - test_urls([ - "http://www.freesound.org/people/Corsica_S/sounds/184419/", - ]) + freesound.download("http://www.freesound.org/people/Corsica_S/sounds/184419/", info_only=True) def test_magisto(self): - test_urls([ - "http://www.magisto.com/album/video/f3x9AAQORAkfDnIFDA", - ]) + magisto.download("http://www.magisto.com/album/video/f3x9AAQORAkfDnIFDA", info_only=True) def test_mixcloud(self): - test_urls([ - "http://www.mixcloud.com/beatbopz/beat-bopz-disco-mix/", - "http://www.mixcloud.com/DJVadim/north-america-are-you-ready/", - ]) + mixcloud.download("http://www.mixcloud.com/beatbopz/beat-bopz-disco-mix/", info_only=True) + mixcloud.download("http://www.mixcloud.com/DJVadim/north-america-are-you-ready/", info_only=True) def test_ted(self): - test_urls([ - "http://www.ted.com/talks/jennifer_lin_improvs_piano_magic.html", - "http://www.ted.com/talks/derek_paravicini_and_adam_ockelford_in_the_key_of_genius.html", - ]) + ted.download("http://www.ted.com/talks/jennifer_lin_improvs_piano_magic.html", info_only=True) + ted.download("http://www.ted.com/talks/derek_paravicini_and_adam_ockelford_in_the_key_of_genius.html", info_only=True) def test_vimeo(self): - test_urls([ - "http://vimeo.com/56810854", - ]) + vimeo.download("http://vimeo.com/56810854", info_only=True) def test_youtube(self): - test_urls([ - "http://www.youtube.com/watch?v=pzKerr0JIPA", - "http://youtu.be/pzKerr0JIPA", - "http://www.youtube.com/attribution_link?u=/watch?v%3DldAKIzq7bvs%26feature%3Dshare" - ]) + youtube.download("http://www.youtube.com/watch?v=pzKerr0JIPA", info_only=True) + youtube.download("http://youtu.be/pzKerr0JIPA", info_only=True) + youtube.download("http://www.youtube.com/attribution_link?u=/watch?v%3DldAKIzq7bvs%26feature%3Dshare", info_only=True) diff --git a/tests/test_common.py b/tests/test_common.py index 5e97b77b..f1ef9262 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -2,7 +2,7 @@ import unittest -from you_get import * +from you_get.common import * class TestCommon(unittest.TestCase): diff --git a/tests/test_util.py b/tests/test_util.py index 0b7b0231..239083bc 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -2,7 +2,7 @@ import unittest -from you_get.util import * +from you_get.util.fs import * class TestUtil(unittest.TestCase): def test_legitimize(self): From 61ac0da5c110162f996309a234d25fed57ed0a43 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Mon, 21 Jul 2014 04:00:47 +0200 Subject: [PATCH 14/18] resolve a namespace conflict --- src/you_get/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/you_get/common.py b/src/you_get/common.py index 5f5228f9..50f68263 100644 --- a/src/you_get/common.py +++ b/src/you_get/common.py @@ -800,8 +800,6 @@ def set_http_proxy(proxy): -from .extractors import * - def download_main(download, download_playlist, urls, playlist, **kwargs): for url in urls: if url.startswith('https://'): @@ -924,6 +922,8 @@ def script_main(script_name, download, download_playlist = None): sys.exit(1) def url_to_module(url): + from .extractors import netease, w56, acfun, baidu, bilibili, blip, catfun, cntv, cbs, coursera, dailymotion, douban, ehow, facebook, freesound, google, sina, ifeng, alive, instagram, iqiyi, joy, jpopsuki, khan, ku6, kugou, kuwo, letv, magisto, miomio, mixcloud, mtv81, nicovideo, pptv, qq, sohu, songtaste, soundcloud, ted, theplatform, tudou, tumblr, vid48, vimeo, vine, vk, xiami, yinyuetai, youku, youtube + video_host = r1(r'https?://([^/]+)/', url) video_url = r1(r'https?://[^/]+(.*)', url) assert video_host and video_url, 'invalid url: ' + url From 8ef58481613cb8f0b97ae40fa39d4435e0af6373 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Mon, 21 Jul 2014 04:19:08 +0200 Subject: [PATCH 15/18] remove you-get-dev --- .gitignore | 1 + you-get-dev | 18 ------------------ 2 files changed, 1 insertion(+), 18 deletions(-) delete mode 100755 you-get-dev diff --git a/.gitignore b/.gitignore index 1d987ed9..4f8158a5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.py[cod] _*/ +*_ *.bak *.download diff --git a/you-get-dev b/you-get-dev deleted file mode 100755 index a63493b4..00000000 --- a/you-get-dev +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python -# This file is Python 2 compliant. - -import os, sys - -_srcdir = 'src/' -_filepath = os.path.dirname(os.path.realpath(__file__)) -sys.path.insert(1, os.path.join(_filepath, _srcdir)) - -if sys.version_info[0] == 3: - import you_get - if __name__ == '__main__': - you_get.main_dev(repo_path=_filepath) -else: - from you_get.util import log - log.wtf(""" - [Fatal] Python 3 is required. - If Python 3 is already installed on your machine, try to run this script using 'python3 you-get'.""") From f78e4c8078922321201f3b484ae775d4d7976707 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Mon, 21 Jul 2014 04:27:57 +0200 Subject: [PATCH 16/18] update README: add Catfun.tv --- README.md | 1 + README.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 8a9ac7cc..b9a007b8 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ __中文说明__已移至[wiki](https://github.com/soimort/you-get/wiki/%E4%B8%A * SongTaste * Alive.in.th * VK +* Catfun (喵星球) ## Dependencies diff --git a/README.txt b/README.txt index f8ffd878..5826a869 100644 --- a/README.txt +++ b/README.txt @@ -68,6 +68,7 @@ Supported Sites (As of Now) * SongTaste http://www.songtaste.com * Alive.in.th http://alive.in.th * VK http://vk.com +* Catfun (喵星球) http://www.catfun.tv Dependencies ------------ From 07a224ed7c4a6bb54f0b8c63deed4ab21e481c8a Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Mon, 21 Jul 2014 13:41:31 +0200 Subject: [PATCH 17/18] Catfun: reformat --- src/you_get/extractors/catfun.py | 94 +++++++++++++++----------------- 1 file changed, 45 insertions(+), 49 deletions(-) diff --git a/src/you_get/extractors/catfun.py b/src/you_get/extractors/catfun.py index de8552ba..8b547982 100644 --- a/src/you_get/extractors/catfun.py +++ b/src/you_get/extractors/catfun.py @@ -8,73 +8,69 @@ from ..common import * from xml.dom.minidom import * def parse_item(item): - if item["type"]=="youku": - page=get_content("http://www.catfun.tv/index.php?m=catfun&c=catfun_video&a=get_youku_video_info&youku_id="+item["vid"]) - dom=parseString(page) - ext=dom.getElementsByTagName("format")[0].firstChild.nodeValue; - size=0 - urls=[] + if item["type"] == "youku": + page = get_content("http://www.catfun.tv/index.php?m=catfun&c=catfun_video&a=get_youku_video_info&youku_id=" + item["vid"]) + dom = parseString(page) + ext = dom.getElementsByTagName("format")[0].firstChild.nodeValue; + size = 0 + urls = [] for i in dom.getElementsByTagName("durl"): urls.append(i.getElementsByTagName("url")[0].firstChild.nodeValue) - size+=int(i.getElementsByTagName("size")[0].firstChild.nodeValue); - return urls,ext,size - pass + size += int(i.getElementsByTagName("size")[0].firstChild.nodeValue); + return urls, ext, size - elif item["type"]=="qq": - page=get_content("http://www.catfun.tv/index.php?m=catfun&c=catfun_video&a=get_qq_video_info&qq_id="+item["vid"]) - dom=parseString(page) - size=0 - urls=[] + elif item["type"] == "qq": + page = get_content("http://www.catfun.tv/index.php?m=catfun&c=catfun_video&a=get_qq_video_info&qq_id=" + item["vid"]) + dom = parseString(page) + size = 0 + urls = [] for i in dom.getElementsByTagName("durl"): - url=i.getElementsByTagName("url")[0].firstChild.nodeValue - urls.append(url) - vtype,ext,_size=url_info(url) - size+=_size - return urls,ext,size - pass + url = i.getElementsByTagName("url")[0].firstChild.nodeValue + urls.append(url) + vtype, ext, _size = url_info(url) + size += _size + return urls, ext, size - elif item["type"]=="sina": - page=get_content("http://www.catfun.tv/index.php?m=catfun&c=catfun_video&a=get_sina_video_info&sina_id=" + item["vid"]) + elif item["type"] == "sina": + page = get_content("http://www.catfun.tv/index.php?m=catfun&c=catfun_video&a=get_sina_video_info&sina_id=" + item["vid"]) try: - dom=parseString(page) + dom = parseString(page) except: #refresh page encountered - page=get_content(match1(page,r'url=(.+?)"')) - dom=parseString(page) - size=0 - urls=[] + page = get_content(match1(page, r'url=(.+?)"')) + dom = parseString(page) + size = 0 + urls = [] for i in dom.getElementsByTagName("durl"): - url=i.getElementsByTagName("url")[0].firstChild.nodeValue + url = i.getElementsByTagName("url")[0].firstChild.nodeValue urls.append(url) - vtype,ext,_size=url_info(url) + vtype, ext, _size = url_info(url) if not ext: - ext=match1(url,r'\.(\w+?)\?') - size+=_size - #sina's result does not contains content-type - return urls,ext,size - pass - - + ext = match1(url,r'\.(\w+?)\?') + size += _size + #sina's result does not contains content-type + return urls, ext, size def catfun_download(url, output_dir = '.', merge = True, info_only = False): - # html=get_content(url) - title=match1(get_content(url),r'

(.+?)

') - vid=match1(url,r"v\d+/cat(\d+)") - j=json.loads(get_content("http://www.catfun.tv/index.php?m=catfun&c=catfun_video&a=get_video&modelid=11&id={}".format(vid))) + # html = get_content(url) + title = match1(get_content(url), r'

(.+?)

') + vid = match1(url, r"v\d+/cat(\d+)") + j = json.loads(get_content("http://www.catfun.tv/index.php?m=catfun&c=catfun_video&a=get_video&modelid=11&id={}".format(vid))) for item in j: - if item["name"]!="\u672a\u547d\u540d1": - t=title+"-"+item["name"] + if item["name"] != "\u672a\u547d\u540d1": + t = title + "-" + item["name"] else: - t=title - if item["type"]=="tudou": + t = title + if item["type"] == "tudou": tudou_download_by_id(item["vid"], title, output_dir, merge, info_only) else: - urls,ext,size=parse_item(item) - - download_urls(urls,t,ext,size,output_dir) + urls, ext, size = parse_item(item) + print_info(site_info, title, ext, size) + if not info_only: + download_urls(urls, t, ext, size, output_dir, merge=merge) -site_info = "catfun.com" +site_info = "CatFun.tv" download = catfun_download -download_playlist = playlist_not_supported('catfun') \ No newline at end of file +download_playlist = playlist_not_supported('catfun') From cf3fce9e86773120575163239e996c0d9cb778a3 Mon Sep 17 00:00:00 2001 From: Mort Yao Date: Mon, 21 Jul 2014 14:44:27 +0200 Subject: [PATCH 18/18] extractor: use util.log to print formatted text --- src/you_get/extractor.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/you_get/extractor.py b/src/you_get/extractor.py index 7c193db3..94d54ca3 100644 --- a/src/you_get/extractor.py +++ b/src/you_get/extractor.py @@ -76,9 +76,9 @@ class VideoExtractor(): def p_stream(self, stream_id): stream = self.streams[stream_id] if 'itag' in stream: - print(" - itag: \033[7m%s\033[0m" % stream_id) + print(" - itag: %s" % log.sprint(stream_id, log.NEGATIVE)) else: - print(" - format: \033[7m%s\033[0m" % stream_id) + print(" - format: %s" % log.sprint(stream_id, log.NEGATIVE)) if 'container' in stream: print(" container: %s" % stream['container']) @@ -93,9 +93,9 @@ class VideoExtractor(): print(" size: %s MiB (%s bytes)" % (round(stream['size'] / 1048576, 1), stream['size'])) if 'itag' in stream: - print(" # download-with: \033[4myou-get --itag=%s [URL]\033[0m" % stream_id) + print(" # download-with: %s" % log.sprint("you-get --itag=%s [URL]" % stream_id, log.UNDERLINE)) else: - print(" # download-with: \033[4myou-get --format=%s [URL]\033[0m" % stream_id) + print(" # download-with: %s" % log.sprint("you-get --format=%s [URL]" % stream_id, log.UNDERLINE)) print()