diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 76fc394bc..2bc02f8ca 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -277,6 +277,7 @@ class YoutubeDL(object): self._num_downloads = 0 self._screen_file = [sys.stdout, sys.stderr][params.get('logtostderr', False)] self._err_file = sys.stderr + self._openers_pool = {} self.params = params self.cache = Cache(self) @@ -320,7 +321,7 @@ class YoutubeDL(object): if '%(stitle)s' in self.params.get('outtmpl', ''): self.report_warning('%(stitle)s is deprecated. Use the %(title)s and the --restrict-filenames flag(which also secures %(uploader)s et al) instead.') - self._setup_opener() + self._setup_openers() if auto_init: self.print_debug_header() @@ -1729,12 +1730,16 @@ class YoutubeDL(object): 'See https://yt-dl.org/update if you need help updating.' % latest_version) - def _setup_opener(self): + def _setup_openers(self): + self._setup_single_opener('default', self.params.get('proxy')) + self._setup_single_opener('alternative', self.params.get('alternative_proxy')) + self.use_opener('default') + + def _setup_single_opener(self, opener_name, opts_proxy): timeout_val = self.params.get('socket_timeout') self._socket_timeout = 600 if timeout_val is None else float(timeout_val) opts_cookiefile = self.params.get('cookiefile') - opts_proxy = self.params.get('proxy') if opts_cookiefile is None: self.cookiejar = compat_cookiejar.CookieJar() @@ -1767,7 +1772,13 @@ class YoutubeDL(object): # cases where our custom HTTP handler doesn't come into play # (See https://github.com/rg3/youtube-dl/issues/1309 for details) opener.addheaders = [] - self._opener = opener + self._openers_pool[opener_name] = opener + + def use_opener(self, opener_name): + if opener_name in self._openers_pool: + self._opener = self._openers_pool[opener_name] + else: + raise Exception('Invalid opener name ' + opener_name) def encode(self, s): if isinstance(s, bytes): diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 5ce201800..781033a9a 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -327,6 +327,7 @@ def _real_main(argv=None): 'nocheckcertificate': opts.no_check_certificate, 'prefer_insecure': opts.prefer_insecure, 'proxy': opts.proxy, + 'alternative_proxy': opts.alternative_proxy, 'socket_timeout': opts.socket_timeout, 'bidi_workaround': opts.bidi_workaround, 'debug_printtraffic': opts.debug_printtraffic, diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 7977fa8d0..65f29de8a 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -1053,6 +1053,15 @@ class InfoExtractor(object): def _get_automatic_captions(self, *args, **kwargs): raise NotImplementedError("This method must be implemented by subclasses") + def _multiple_opener_supported(self): + return hasattr(self._downloader, 'use_opener') + + def _use_opener(self, opener_name): + if self._multiple_opener_supported(): + self._downloader.use_opener(opener_name) + else: + raise Exception('Multiple opener not supported') + class SearchInfoExtractor(InfoExtractor): """ diff --git a/youtube_dl/extractor/letv.py b/youtube_dl/extractor/letv.py index 583ce35b9..c3886125d 100644 --- a/youtube_dl/extractor/letv.py +++ b/youtube_dl/extractor/letv.py @@ -33,6 +33,7 @@ class LetvIE(InfoExtractor): } }, { 'url': 'http://www.letv.com/ptv/vplay/1415246.html', + 'md5': 'b4b0a9248ecf34d80ee52a2609627a88', 'info_dict': { 'id': '1415246', 'ext': 'mp4', @@ -42,9 +43,23 @@ class LetvIE(InfoExtractor): 'expected_warnings': [ 'publish time' ] + }, { + # This video is available only in Mainland China, thus a proxy is needed + 'url': 'http://www.letv.com/ptv/vplay/1118082.html', + 'md5': 'f80936fbe20fb2f58648e81386ff7927', + 'info_dict': { + 'id': '1118082', + 'ext': 'mp4', + 'title': '与龙共舞 完整版', + 'description': 'md5:7506a5eeb1722bb9d4068f85024e3986', + }, + 'expected_warnings': [ + 'publish time' + ], + 'params': { + 'alternative_proxy': 'proxy.uku.im:8888' + } }] - # http://www.letv.com/ptv/vplay/1118082.html - # This video is available only in Mainland China @staticmethod def urshift(val, n): @@ -76,10 +91,17 @@ class LetvIE(InfoExtractor): 'tkey': self.calc_time_key(int(time.time())), 'domain': 'www.letv.com' } + + if self._multiple_opener_supported(): + self._use_opener('alternative') + play_json = self._download_json( 'http://api.letv.com/mms/out/video/playJson?' + compat_urllib_parse.urlencode(params), media_id, 'playJson data') + if self._multiple_opener_supported(): + self._use_opener('default') + # Check for errors playstatus = play_json['playstatus'] if playstatus['status'] == 0: diff --git a/youtube_dl/options.py b/youtube_dl/options.py index 886ce9613..8cfa7ec7c 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -176,6 +176,11 @@ def parseOpts(overrideArguments=None): '--proxy', dest='proxy', default=None, metavar='URL', help='Use the specified HTTP/HTTPS proxy. Pass in an empty string (--proxy "") for direct connection') + network.add_option( + '--alternative-proxy', dest='alternative_proxy', + default=None, metavar='URL', + help='Use the specified HTTP/HTTPS address as the alternative proxy. Pass in an empty string (--alternative-proxy "") for direct connection' + ) network.add_option( '--socket-timeout', dest='socket_timeout', type=float, default=None, metavar='SECONDS',