mirror of
				https://code.hackerspace.pl/q3k/youtube-dl
				synced 2025-03-16 11:43:02 +00:00 
			
		
		
		
	Merge branch 'Celthi-youku_bugfix'
This commit is contained in:
		
						commit
						9c568178fb
					
				| @ -25,8 +25,8 @@ class YoukuIE(InfoExtractor): | |||||||
|     ''' |     ''' | ||||||
| 
 | 
 | ||||||
|     _TESTS = [{ |     _TESTS = [{ | ||||||
|  |         # MD5 is unstable | ||||||
|         'url': 'http://v.youku.com/v_show/id_XMTc1ODE5Njcy.html', |         'url': 'http://v.youku.com/v_show/id_XMTc1ODE5Njcy.html', | ||||||
|         'md5': '5f3af4192eabacc4501508d54a8cabd7', |  | ||||||
|         'info_dict': { |         'info_dict': { | ||||||
|             'id': 'XMTc1ODE5Njcy_part1', |             'id': 'XMTc1ODE5Njcy_part1', | ||||||
|             'title': '★Smile﹗♡ Git Fresh -Booty Music舞蹈.', |             'title': '★Smile﹗♡ Git Fresh -Booty Music舞蹈.', | ||||||
| @ -42,6 +42,7 @@ class YoukuIE(InfoExtractor): | |||||||
|             'title': '武媚娘传奇 85', |             'title': '武媚娘传奇 85', | ||||||
|         }, |         }, | ||||||
|         'playlist_count': 11, |         'playlist_count': 11, | ||||||
|  |         'skip': 'Available in China only', | ||||||
|     }, { |     }, { | ||||||
|         'url': 'http://v.youku.com/v_show/id_XMTI1OTczNDM5Mg==.html', |         'url': 'http://v.youku.com/v_show/id_XMTI1OTczNDM5Mg==.html', | ||||||
|         'info_dict': { |         'info_dict': { | ||||||
| @ -49,7 +50,6 @@ class YoukuIE(InfoExtractor): | |||||||
|             'title': '花千骨 04', |             'title': '花千骨 04', | ||||||
|         }, |         }, | ||||||
|         'playlist_count': 13, |         'playlist_count': 13, | ||||||
|         'skip': 'Available in China only', |  | ||||||
|     }, { |     }, { | ||||||
|         'url': 'http://v.youku.com/v_show/id_XNjA1NzA2Njgw.html', |         'url': 'http://v.youku.com/v_show/id_XNjA1NzA2Njgw.html', | ||||||
|         'note': 'Video protected with password', |         'note': 'Video protected with password', | ||||||
| @ -63,7 +63,7 @@ class YoukuIE(InfoExtractor): | |||||||
|         }, |         }, | ||||||
|     }] |     }] | ||||||
| 
 | 
 | ||||||
|     def construct_video_urls(self, data1, data2): |     def construct_video_urls(self, data): | ||||||
|         # get sid, token |         # get sid, token | ||||||
|         def yk_t(s1, s2): |         def yk_t(s1, s2): | ||||||
|             ls = list(range(256)) |             ls = list(range(256)) | ||||||
| @ -81,34 +81,24 @@ class YoukuIE(InfoExtractor): | |||||||
|             return bytes(s) |             return bytes(s) | ||||||
| 
 | 
 | ||||||
|         sid, token = yk_t( |         sid, token = yk_t( | ||||||
|             b'becaf9be', base64.b64decode(data2['ep'].encode('ascii')) |             b'becaf9be', base64.b64decode(data['security']['encrypt_string'].encode('ascii')) | ||||||
|         ).decode('ascii').split('_') |         ).decode('ascii').split('_') | ||||||
| 
 | 
 | ||||||
|         # get oip |         # get oip | ||||||
|         oip = data2['ip'] |         oip = data['security']['ip'] | ||||||
| 
 |  | ||||||
|         # get fileid |  | ||||||
|         string_ls = list( |  | ||||||
|             'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/\:._-1234567890') |  | ||||||
|         shuffled_string_ls = [] |  | ||||||
|         seed = data1['seed'] |  | ||||||
|         N = len(string_ls) |  | ||||||
|         for ii in range(N): |  | ||||||
|             seed = (seed * 0xd3 + 0x754f) % 0x10000 |  | ||||||
|             idx = seed * len(string_ls) // 0x10000 |  | ||||||
|             shuffled_string_ls.append(string_ls[idx]) |  | ||||||
|             del string_ls[idx] |  | ||||||
| 
 | 
 | ||||||
|         fileid_dict = {} |         fileid_dict = {} | ||||||
|         for format in data1['streamtypes']: |         for stream in data['stream']: | ||||||
|             streamfileid = [ |             format = stream.get('stream_type') | ||||||
|                 int(i) for i in data1['streamfileids'][format].strip('*').split('*')] |             fileid = stream['stream_fileid'] | ||||||
|             fileid = ''.join( |             fileid_dict[format] = fileid | ||||||
|                 [shuffled_string_ls[i] for i in streamfileid]) |  | ||||||
|             fileid_dict[format] = fileid[:8] + '%s' + fileid[10:] |  | ||||||
| 
 | 
 | ||||||
|         def get_fileid(format, n): |         def get_fileid(format, n): | ||||||
|             fileid = fileid_dict[format] % hex(int(n))[2:].upper().zfill(2) |             number = hex(int(str(n), 10))[2:].upper() | ||||||
|  |             if len(number) == 1: | ||||||
|  |                 number = '0' + number | ||||||
|  |             streamfileids = fileid_dict[format] | ||||||
|  |             fileid = streamfileids[0:8] + number + streamfileids[10:] | ||||||
|             return fileid |             return fileid | ||||||
| 
 | 
 | ||||||
|         # get ep |         # get ep | ||||||
| @ -123,15 +113,15 @@ class YoukuIE(InfoExtractor): | |||||||
| 
 | 
 | ||||||
|         # generate video_urls |         # generate video_urls | ||||||
|         video_urls_dict = {} |         video_urls_dict = {} | ||||||
|         for format in data1['streamtypes']: |         for stream in data['stream']: | ||||||
|  |             format = stream.get('stream_type') | ||||||
|             video_urls = [] |             video_urls = [] | ||||||
|             for dt in data1['segs'][format]: |             for dt in stream['segs']: | ||||||
|                 n = str(int(dt['no'])) |                 n = str(stream['segs'].index(dt)) | ||||||
|                 param = { |                 param = { | ||||||
|                     'K': dt['k'], |                     'K': dt['key'], | ||||||
|                     'hd': self.get_hd(format), |                     'hd': self.get_hd(format), | ||||||
|                     'myp': 0, |                     'myp': 0, | ||||||
|                     'ts': dt['seconds'], |  | ||||||
|                     'ypp': 0, |                     'ypp': 0, | ||||||
|                     'ctype': 12, |                     'ctype': 12, | ||||||
|                     'ev': 1, |                     'ev': 1, | ||||||
| @ -142,7 +132,7 @@ class YoukuIE(InfoExtractor): | |||||||
|                 video_url = \ |                 video_url = \ | ||||||
|                     'http://k.youku.com/player/getFlvPath/' + \ |                     'http://k.youku.com/player/getFlvPath/' + \ | ||||||
|                     'sid/' + sid + \ |                     'sid/' + sid + \ | ||||||
|                     '_' + str(int(n) + 1).zfill(2) + \ |                     '_00' + \ | ||||||
|                     '/st/' + self.parse_ext_l(format) + \ |                     '/st/' + self.parse_ext_l(format) + \ | ||||||
|                     '/fileid/' + get_fileid(format, n) + '?' + \ |                     '/fileid/' + get_fileid(format, n) + '?' + \ | ||||||
|                     compat_urllib_parse.urlencode(param) |                     compat_urllib_parse.urlencode(param) | ||||||
| @ -153,23 +143,30 @@ class YoukuIE(InfoExtractor): | |||||||
| 
 | 
 | ||||||
|     def get_hd(self, fm): |     def get_hd(self, fm): | ||||||
|         hd_id_dict = { |         hd_id_dict = { | ||||||
|  |             '3gp': '0', | ||||||
|  |             '3gphd': '1', | ||||||
|             'flv': '0', |             'flv': '0', | ||||||
|  |             'flvhd': '0', | ||||||
|             'mp4': '1', |             'mp4': '1', | ||||||
|  |             'mp4hd': '1', | ||||||
|  |             'mp4hd2': '1', | ||||||
|             'hd2': '2', |             'hd2': '2', | ||||||
|             'hd3': '3', |             'hd3': '3', | ||||||
|             '3gp': '0', |  | ||||||
|             '3gphd': '1' |  | ||||||
|         } |         } | ||||||
|         return hd_id_dict[fm] |         return hd_id_dict[fm] | ||||||
| 
 | 
 | ||||||
|     def parse_ext_l(self, fm): |     def parse_ext_l(self, fm): | ||||||
|         ext_dict = { |         ext_dict = { | ||||||
|  |             '3gp': 'flv', | ||||||
|  |             '3gphd': 'mp4', | ||||||
|             'flv': 'flv', |             'flv': 'flv', | ||||||
|  |             'flvhd': 'flv', | ||||||
|             'mp4': 'mp4', |             'mp4': 'mp4', | ||||||
|  |             'mp4hd': 'mp4', | ||||||
|  |             'mp4hd2': 'flv', | ||||||
|  |             'mp4hd3': 'flv', | ||||||
|             'hd2': 'flv', |             'hd2': 'flv', | ||||||
|             'hd3': 'flv', |             'hd3': 'flv', | ||||||
|             '3gp': 'flv', |  | ||||||
|             '3gphd': 'mp4' |  | ||||||
|         } |         } | ||||||
|         return ext_dict[fm] |         return ext_dict[fm] | ||||||
| 
 | 
 | ||||||
| @ -178,9 +175,13 @@ class YoukuIE(InfoExtractor): | |||||||
|             '3gp': 'h6', |             '3gp': 'h6', | ||||||
|             '3gphd': 'h5', |             '3gphd': 'h5', | ||||||
|             'flv': 'h4', |             'flv': 'h4', | ||||||
|  |             'flvhd': 'h4', | ||||||
|             'mp4': 'h3', |             'mp4': 'h3', | ||||||
|  |             'mp4hd': 'h3', | ||||||
|  |             'mp4hd2': 'h4', | ||||||
|  |             'mp4hd3': 'h4', | ||||||
|             'hd2': 'h2', |             'hd2': 'h2', | ||||||
|             'hd3': 'h1' |             'hd3': 'h1', | ||||||
|         } |         } | ||||||
|         return _dict[fm] |         return _dict[fm] | ||||||
| 
 | 
 | ||||||
| @ -188,45 +189,46 @@ class YoukuIE(InfoExtractor): | |||||||
|         video_id = self._match_id(url) |         video_id = self._match_id(url) | ||||||
| 
 | 
 | ||||||
|         def retrieve_data(req_url, note): |         def retrieve_data(req_url, note): | ||||||
|             req = sanitized_Request(req_url) |             headers = { | ||||||
|  |                 'Referer': req_url, | ||||||
|  |             } | ||||||
|  |             self._set_cookie('youku.com', 'xreferrer', 'http://www.youku.com') | ||||||
|  |             req = sanitized_Request(req_url, headers=headers) | ||||||
| 
 | 
 | ||||||
|             cn_verification_proxy = self._downloader.params.get('cn_verification_proxy') |             cn_verification_proxy = self._downloader.params.get('cn_verification_proxy') | ||||||
|             if cn_verification_proxy: |             if cn_verification_proxy: | ||||||
|                 req.add_header('Ytdl-request-proxy', cn_verification_proxy) |                 req.add_header('Ytdl-request-proxy', cn_verification_proxy) | ||||||
| 
 | 
 | ||||||
|             raw_data = self._download_json(req, video_id, note=note) |             raw_data = self._download_json(req, video_id, note=note) | ||||||
|             return raw_data['data'][0] | 
 | ||||||
|  |             return raw_data['data'] | ||||||
| 
 | 
 | ||||||
|         video_password = self._downloader.params.get('videopassword', None) |         video_password = self._downloader.params.get('videopassword', None) | ||||||
| 
 | 
 | ||||||
|         # request basic data |         # request basic data | ||||||
|         basic_data_url = 'http://v.youku.com/player/getPlayList/VideoIDS/%s' % video_id |         basic_data_url = "http://play.youku.com/play/get.json?vid=%s&ct=12" % video_id | ||||||
|         if video_password: |         if video_password: | ||||||
|             basic_data_url += '?password=%s' % video_password |             basic_data_url += '&pwd=%s' % video_password | ||||||
| 
 | 
 | ||||||
|         data1 = retrieve_data( |         data = retrieve_data(basic_data_url, 'Downloading JSON metadata') | ||||||
|             basic_data_url, |  | ||||||
|             'Downloading JSON metadata 1') |  | ||||||
|         data2 = retrieve_data( |  | ||||||
|             'http://v.youku.com/player/getPlayList/VideoIDS/%s/Pf/4/ctype/12/ev/1' % video_id, |  | ||||||
|             'Downloading JSON metadata 2') |  | ||||||
| 
 | 
 | ||||||
|         error_code = data1.get('error_code') |         error = data.get('error') | ||||||
|         if error_code: |         if error: | ||||||
|             error = data1.get('error') |             error_note = error.get('note') | ||||||
|             if error is not None and '因版权原因无法观看此视频' in error: |             if error_note is not None and '因版权原因无法观看此视频' in error_note: | ||||||
|                 raise ExtractorError( |                 raise ExtractorError( | ||||||
|                     'Youku said: Sorry, this video is available in China only', expected=True) |                     'Youku said: Sorry, this video is available in China only', expected=True) | ||||||
|             else: |             else: | ||||||
|                 msg = 'Youku server reported error %i' % error_code |                 msg = 'Youku server reported error %i' % error.get('code') | ||||||
|                 if error is not None: |                 if error is not None: | ||||||
|                     msg += ': ' + error |                     msg += ': ' + error_note | ||||||
|                 raise ExtractorError(msg) |                 raise ExtractorError(msg) | ||||||
| 
 | 
 | ||||||
|         title = data1['title'] |         # get video title | ||||||
|  |         title = data['video']['title'] | ||||||
| 
 | 
 | ||||||
|         # generate video_urls_dict |         # generate video_urls_dict | ||||||
|         video_urls_dict = self.construct_video_urls(data1, data2) |         video_urls_dict = self.construct_video_urls(data) | ||||||
| 
 | 
 | ||||||
|         # construct info |         # construct info | ||||||
|         entries = [{ |         entries = [{ | ||||||
| @ -235,10 +237,11 @@ class YoukuIE(InfoExtractor): | |||||||
|             'formats': [], |             'formats': [], | ||||||
|             # some formats are not available for all parts, we have to detect |             # some formats are not available for all parts, we have to detect | ||||||
|             # which one has all |             # which one has all | ||||||
|         } for i in range(max(len(v) for v in data1['segs'].values()))] |         } for i in range(max(len(v.get('segs')) for v in data['stream']))] | ||||||
|         for fm in data1['streamtypes']: |         for stream in data['stream']: | ||||||
|  |             fm = stream.get('stream_type') | ||||||
|             video_urls = video_urls_dict[fm] |             video_urls = video_urls_dict[fm] | ||||||
|             for video_url, seg, entry in zip(video_urls, data1['segs'][fm], entries): |             for video_url, seg, entry in zip(video_urls, stream['segs'], entries): | ||||||
|                 entry['formats'].append({ |                 entry['formats'].append({ | ||||||
|                     'url': video_url, |                     'url': video_url, | ||||||
|                     'format_id': self.get_format_name(fm), |                     'format_id': self.get_format_name(fm), | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Yen Chi Hsuan
						Yen Chi Hsuan