diff --git a/src/you_get/extractors/iqiyi.py b/src/you_get/extractors/iqiyi.py index b1fc5deb..51dc93c2 100644 --- a/src/you_get/extractors/iqiyi.py +++ b/src/you_get/extractors/iqiyi.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -__all__ = ['iqiyi_download'] - from ..common import * +from ..extractor import VideoExtractor from uuid import uuid4 from random import random,randint import json @@ -44,7 +43,6 @@ bid meaning for quality 96 topspeed ''' - def mix(tvid): enc = [] enc.append('3cba91f1453145438ac5e4f5983bc086') @@ -75,90 +73,128 @@ def getVrsEncodeCode(vlink): loc2+=chr(loc6) return loc2[::-1] -def getVMS(tvid,vid,uid): - #tm ->the flash run time for md5 usage - #um -> vip 1 normal 0 - #authkey -> for password protected video ,replace '' with your password - #puid user.passportid may empty? - #TODO: support password protected video - tm,sc,src = mix(tvid) - vmsreq='http://cache.video.qiyi.com/vms?key=fvip&src=1702633101b340d8917a69cf8a4b8c7' +\ - "&tvId="+tvid+"&vid="+vid+"&vinfo=1&tm="+tm+\ - "&enc="+sc+\ - "&qyid="+uid+"&tn="+str(random()) +"&um=1" +\ - "&authkey="+hashlib.new('md5',bytes(''+str(tm)+tvid,'utf-8')).hexdigest() - return json.loads(get_content(vmsreq)) - def getDispathKey(rid): tp=")(*&^flash@#$%a" #magic from swf time=json.loads(get_content("http://data.video.qiyi.com/t?tn="+str(random())))["t"] t=str(int(floor(int(time)/(10*60.0)))) return hashlib.new("md5",bytes(t+tp+rid,"utf-8")).hexdigest() +class Iqiyi(VideoExtractor): + name = "爱奇艺 (Iqiyi)" -def iqiyi_download(url, output_dir = '.', merge = True, info_only = False, **kwargs): - gen_uid=uuid4().hex + stream_types = [ + {'id': '4k', 'container': 'f4v', 'video_profile': '4K'}, + {'id': 'fullhd', 'container': 'f4v', 'video_profile': '全高清'}, + {'id': 'suprt-high', 'container': 'f4v', 'video_profile': '超高清'}, + {'id': 'super', 'container': 'f4v', 'video_profile': '超清'}, + {'id': 'high', 'container': 'f4v', 'video_profile': '高清'}, + {'id': 'standard', 'container': 'f4v', 'video_profile': '标清'}, + {'id': 'topspeed', 'container': 'f4v', 'video_profile': '最差'}, + ] - html = get_html(url) + stream_to_bid = { '4k': 10, 'fullhd' : 5, 'suprt-high' : 4, 'super' : 3, 'high' : 2, 'standard' :1, 'topspeed' :96} - tvid = r1(r'data-player-tvid="([^"]+)"', html) or r1(r'tvid=([^&]+)', url) - videoid = r1(r'data-player-videoid="([^"]+)"', html) or r1(r'vid=([^&]+)', url) + stream_urls = { '4k': [] , 'fullhd' : [], 'suprt-high' : [], 'super' : [], 'high' : [], 'standard' :[], 'topspeed' :[]} - assert tvid - assert videoid + baseurl = '' - info = getVMS(tvid, videoid, gen_uid) - - assert info["code"] == "A000000" - - title = info["data"]["vi"]["vn"] - - # data.vp = json.data.vp - # data.vi = json.data.vi - # data.f4v = json.data.f4v - # if movieIsMember data.vp = json.data.np - - #for highest qualities - #for http://www.iqiyi.com/v_19rrmmz5yw.html not vp -> np - try: - if info["data"]['vp']["tkl"]=='' : - raise ValueError - except: - log.e("[Error] Do not support for iQIYI VIP video.") - exit(-1) - - bid=0 - for i in info["data"]["vp"]["tkl"][0]["vs"]: - if int(i["bid"])<=10 and int(i["bid"])>=bid: - bid=int(i["bid"]) - - video_links=i["fs"] #now in i["flvs"] not in i["fs"] - if not i["fs"][0]["l"].startswith("/"): - tmp = getVrsEncodeCode(i["fs"][0]["l"]) - if tmp.endswith('mp4'): - video_links = i["flvs"] + gen_uid = '' + def getVMS(self): + #tm ->the flash run time for md5 usage + #um -> vip 1 normal 0 + #authkey -> for password protected video ,replace '' with your password + #puid user.passportid may empty? + #TODO: support password protected video + tvid, vid = self.vid + tm, sc, src = mix(tvid) + uid = self.gen_uid + vmsreq='http://cache.video.qiyi.com/vms?key=fvip&src=1702633101b340d8917a69cf8a4b8c7' +\ + "&tvId="+tvid+"&vid="+vid+"&vinfo=1&tm="+tm+\ + "&enc="+sc+\ + "&qyid="+uid+"&tn="+str(random()) +"&um=1" +\ + "&authkey="+hashlib.new('md5',bytes(''+str(tm)+tvid,'utf-8')).hexdigest() + return json.loads(get_content(vmsreq)) - urls=[] - size=0 - for i in video_links: - vlink=i["l"] - if not vlink.startswith("/"): - #vlink is encode - vlink=getVrsEncodeCode(vlink) - key=getDispathKey(vlink.split("/")[-1].split(".")[0]) - size+=i["b"] - baseurl=info["data"]["vp"]["du"].split("/") - baseurl.insert(-1,key) - url="/".join(baseurl)+vlink+'?su='+gen_uid+'&qyid='+uuid4().hex+'&client=&z=&bt=&ct=&tn='+str(randint(10000,20000)) - urls.append(json.loads(get_content(url))["l"]) - #download should be complete in 10 minutes - #because the url is generated before start downloading - #and the key may be expired after 10 minutes - print_info(site_info, title, 'flv', size) - if not info_only: - download_urls(urls, title, 'flv', size, output_dir = output_dir, merge = merge) -site_info = "iQIYI.com" -download = iqiyi_download + def prepare(self, **kwargs): + assert self.url or self.vid + + if self.url and not self.vid: + html = get_html(self.url) + tvid = r1(r'data-player-tvid="([^"]+)"', html) or r1(r'tvid=([^&]+)', self.url) + videoid = r1(r'data-player-videoid="([^"]+)"', html) or r1(r'vid=([^&]+)', self.url) + self.vid = (tvid, videoid) + + self.gen_uid=uuid4().hex + info = self.getVMS() + + assert info["code"] == "A000000" + + self.title = info["data"]["vi"]["vn"] + + # data.vp = json.data.vp + # data.vi = json.data.vi + # data.f4v = json.data.f4v + # if movieIsMember data.vp = json.data.np + + #for highest qualities + #for http://www.iqiyi.com/v_19rrmmz5yw.html not vp -> np + try: + if info["data"]['vp']["tkl"]=='' : + raise ValueError + except: + log.e("[Error] Do not support for iQIYI VIP video.") + exit(-1) + + vs = info["data"]["vp"]["tkl"][0]["vs"] + self.baseurl=info["data"]["vp"]["du"].split("/") + + for stream in self.stream_types: + for i in vs: + if self.stream_to_bid[stream['id']] == i['bid']: + video_links=i["fs"] #now in i["flvs"] not in i["fs"] + if not i["fs"][0]["l"].startswith("/"): + tmp = getVrsEncodeCode(i["fs"][0]["l"]) + if tmp.endswith('mp4'): + video_links = i["flvs"] + self.stream_urls[stream['id']] = video_links + size = 0 + for l in video_links: + size += l['b'] + self.streams[stream['id']] = {'container': stream['container'], 'video_profile': stream['video_profile'], 'size' : size} + break + + def extract(self, **kwargs): + if 'stream_id' in kwargs and kwargs['stream_id']: + # Extract the stream + stream_id = kwargs['stream_id'] + + if stream_id not in self.streams: + log.e('[Error] Invalid video format.') + log.e('Run \'-i\' command with no specific video format to view all available formats.') + exit(2) + else: + # Extract stream with the best quality + stream_id = self.streams_sorted[0]['id'] + + urls=[] + for i in self.stream_urls[stream_id]: + vlink=i["l"] + if not vlink.startswith("/"): + #vlink is encode + vlink=getVrsEncodeCode(vlink) + key=getDispathKey(vlink.split("/")[-1].split(".")[0]) + baseurl = [x for x in self.baseurl] + baseurl.insert(-1,key) + url="/".join(baseurl)+vlink+'?su='+self.gen_uid+'&qyid='+uuid4().hex+'&client=&z=&bt=&ct=&tn='+str(randint(10000,20000)) + urls.append(json.loads(get_content(url))["l"]) + #download should be complete in 10 minutes + #because the url is generated before start downloading + #and the key may be expired after 10 minutes + self.streams[stream_id]['src'] = urls + +site = Iqiyi() +download = site.download_by_url +iqiyi_download_by_vid = site.download_by_vid download_playlist = playlist_not_supported('iqiyi')