diff --git a/src/you_get/extractors/acfun.py b/src/you_get/extractors/acfun.py old mode 100644 new mode 100755 index e78d3636..983606d4 --- a/src/you_get/extractors/acfun.py +++ b/src/you_get/extractors/acfun.py @@ -8,7 +8,7 @@ from .le import letvcloud_download_by_vu from .qq import qq_download_by_vid from .sina import sina_download_by_vid from .tudou import tudou_download_by_iid -from .youku import youku_download_by_vid +from .youku import youku_download_by_vid, youku_open_download_by_vid import json, re @@ -32,14 +32,11 @@ def acfun_download_by_vid(vid, title, output_dir='.', merge=True, info_only=Fals elif sourceType == 'letv': letvcloud_download_by_vu(sourceId, '2d8c027396', title, output_dir=output_dir, merge=merge, info_only=info_only) elif sourceType == 'zhuzhan': - a = 'http://api.aixifan.com/plays/%s/realSource' % vid - s = json.loads(get_content(a, headers={'deviceType': '1'})) - urls = s['data']['files'][-1]['url'] - size = urls_size(urls) - print_info(site_info, title, 'mp4', size) - if not info_only: - download_urls(urls, title, 'mp4', size, - output_dir=output_dir, merge=merge) + a = 'http://api.aixifan.com/plays/%s' % vid + s = json.loads(get_content(a, headers={'deviceType': '2'})) + if s['data']['source'] == "zhuzhan-youku": + sourceId = s['data']['sourceId'] + youku_open_download_by_vid(client_id='908a519d032263f8', vid=sourceId, title=title, output_dir=output_dir, merge=merge, info_only=info_only, **kwargs) else: raise NotImplementedError(sourceType) diff --git a/src/you_get/extractors/youku.py b/src/you_get/extractors/youku.py index 3135e822..fefaf5ee 100644 --- a/src/you_get/extractors/youku.py +++ b/src/you_get/extractors/youku.py @@ -28,7 +28,11 @@ class Youku(VideoExtractor): f_code_1 = 'becaf9be' f_code_2 = 'bf7e5f01' + ctype = 12 #differ from 86 + def trans_e(a, c): + """str, str->str + This is an RC4 encryption.""" f = h = 0 b = list(range(256)) result = '' @@ -49,14 +53,14 @@ class Youku(VideoExtractor): return result - def generate_ep(no, streamfileids, sid, token): + def generate_ep(self, no, streamfileids, sid, token): number = hex(int(str(no), 10))[2:].upper() if len(number) == 1: number = '0' + number fileid = streamfileids[0:8] + number + streamfileids[10:] ep = parse.quote(base64.b64encode( - ''.join(Youku.trans_e( - Youku.f_code_2, + ''.join(self.__class__.trans_e( + self.f_code_2, #use the 86 fcode if using 86 sid + '_' + fileid + '_' + token)).encode('latin1')), safe='~()*!.\'' ) @@ -150,8 +154,17 @@ class Youku(VideoExtractor): self.download_playlist_by_url(self.url, **kwargs) exit(0) - api_url = 'http://play.youku.com/play/get.json?vid=%s&ct=10' % self.vid - api12_url = 'http://play.youku.com/play/get.json?vid=%s&ct=12' % self.vid + #HACK! + if 'api_url' in kwargs: + api_url = kwargs['api_url'] #85 + api12_url = kwargs['api12_url'] #86 + self.ctype = kwargs['ctype'] + self.title = kwargs['title'] + + else: + api_url = 'http://play.youku.com/play/get.json?vid=%s&ct=10' % self.vid + api12_url = 'http://play.youku.com/play/get.json?vid=%s&ct=12' % self.vid + try: meta = json.loads(get_content( api_url, @@ -187,7 +200,8 @@ class Youku(VideoExtractor): else: log.wtf('[Failed] Video not found.') - self.title = data['video']['title'] + if not self.title: #86 + self.title = data['video']['title'] self.ep = data12['security']['encrypt_string'] self.ip = data12['security']['ip'] @@ -264,7 +278,7 @@ class Youku(VideoExtractor): stream_id = self.streams_sorted[0]['id'] e_code = self.__class__.trans_e( - self.__class__.f_code_1, + self.f_code_1, base64.b64decode(bytes(self.ep, 'ascii')) ) sid, token = e_code.split('_') @@ -279,10 +293,10 @@ class Youku(VideoExtractor): for no in range(0, len(segs)): k = segs[no]['key'] if k == -1: break # we hit the paywall; stop here - fileid, ep = self.__class__.generate_ep(no, streamfileid, + fileid, ep = self.__class__.generate_ep(self, no, streamfileid, sid, token) q = parse.urlencode(dict( - ctype = 12, + ctype = self.ctype, ev = 1, K = k, ep = parse.unquote(ep), @@ -312,9 +326,40 @@ class Youku(VideoExtractor): if not kwargs['info_only']: self.streams[stream_id]['src'] = ksegs + def open_download_by_vid(self, client_id, vid, **kwargs): + """self, str, str, **kwargs->None + Override the original one with VideoExtractor. + Most of the credit are to @ERioK, who gave his POC.""" + self.f_code_1 = '10ehfkbv' #can be retrived by running r.translate with the keys and the list e + self.f_code_2 = 'msjv7h2b' + self.url = None + self.vid = vid + self.name = "优酷开放平台 (Youku COOP)" + + #A little bit of work before self.prepare + sign_url = "https://api.youku.com/players/custom.json?client_id={client_id}&video_id={video_id}".format(client_id = client_id, video_id = vid) + playsign = json.loads(get_content(sign_url))['playsign'] + + api85_url = 'http://play.youku.com/partner/get.json?cid={client_id}&vid={vid}&ct=85&sign={playsign}'.format(client_id = client_id, vid = vid, playsign = playsign) + api86_url = 'http://play.youku.com/partner/get.json?cid={client_id}&vid={vid}&ct=86&sign={playsign}'.format(client_id = client_id, vid = vid, playsign = playsign) + + self.prepare(api_url = api85_url, api12_url = api86_url, ctype = 86, **kwargs) + if 'extractor_proxy' in kwargs and kwargs['extractor_proxy']: + unset_proxy() + + 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) + + self.download(**kwargs) + site = Youku() download = site.download_by_url download_playlist = site.download_playlist_by_url youku_download_by_vid = site.download_by_vid +youku_open_download_by_vid = site.open_download_by_vid # Used by: acfun.py bilibili.py miomio.py tudou.py