mirror of
https://github.com/soimort/you-get.git
synced 2025-02-11 12:42:29 +03:00
rewrite letv
rewrite letv using VideoExtractor move letvcloud to another class letvcloud using VideoExtractor
This commit is contained in:
parent
54aa6513af
commit
573cfd7c9f
@ -1,34 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
__all__ = ['letv_download', 'letvcloud_download', 'letvcloud_download_by_vu']
|
||||
|
||||
import json
|
||||
import random
|
||||
import xml.etree.ElementTree as ET
|
||||
import base64, hashlib, urllib, time, re
|
||||
import base64, time, re
|
||||
|
||||
from ..common import *
|
||||
|
||||
#@DEPRECATED
|
||||
def get_timestamp():
|
||||
tn = random.random()
|
||||
url = 'http://api.letv.com/time?tn={}'.format(tn)
|
||||
result = get_content(url)
|
||||
return json.loads(result)['stime']
|
||||
#@DEPRECATED
|
||||
def get_key(t):
|
||||
for s in range(0, 8):
|
||||
e = 1 & t
|
||||
t >>= 1
|
||||
e <<= 31
|
||||
t += e
|
||||
return t ^ 185025305
|
||||
from ..extractor import VideoExtractor
|
||||
|
||||
def calcTimeKey(t):
|
||||
ror = lambda val, r_bits, : ((val & (2**32-1)) >> r_bits%32) | (val << (32-(r_bits%32)) & (2**32-1))
|
||||
return ror(ror(t,773625421%13)^773625421,773625421%17)
|
||||
|
||||
|
||||
def decode(data):
|
||||
version = data[0:5]
|
||||
if version.lower() == b'vc_01':
|
||||
@ -48,35 +30,43 @@ def decode(data):
|
||||
# directly return
|
||||
return data
|
||||
|
||||
class Letv(VideoExtractor):
|
||||
name = "乐视 (Letv)"
|
||||
|
||||
stream_types = [
|
||||
{'id': '1080p', 'container': 'mp4', 'video_profile': '1080p'},
|
||||
{'id': '1300', 'container': 'mp4', 'video_profile': '超清'},
|
||||
{'id': '1000', 'container': 'mp4', 'video_profile': '高清'},
|
||||
{'id': '720p', 'container': 'mp4', 'video_profile': '标清'},
|
||||
{'id': '350', 'container': 'mp4', 'video_profile': '流畅'},
|
||||
]
|
||||
|
||||
def prepare(self, **kwargs):
|
||||
assert self.url or self.vid
|
||||
|
||||
def video_info(vid,**kwargs):
|
||||
url = 'http://api.letv.com/mms/out/video/playJson?id={}&platid=1&splatid=101&format=1&tkey={}&domain=www.letv.com'.format(vid,calcTimeKey(int(time.time())))
|
||||
r = get_content(url, decoded=False)
|
||||
if self.vid:
|
||||
self.url = "http://www.letv.com/ptv/vplay/{}.html".format(self.vid)
|
||||
html = get_content(self.url)
|
||||
if not self.vid:
|
||||
self.vid = match1(self.url, r'http://www.letv.com/ptv/vplay/(\d+).html')
|
||||
if not self.vid:
|
||||
#self embed
|
||||
vids = matchall(html, ['vid="(\d+)"'])
|
||||
for v in vids:
|
||||
self.download_by_vid(v, **kwargs)
|
||||
|
||||
#normal process
|
||||
self.title = match1(html,r'name="irTitle" content="(.*?)"')
|
||||
info_url = 'http://api.letv.com/mms/out/video/playJson?id={}&platid=1&splatid=101&format=1&tkey={}&domain=www.letv.com'.format(self.vid, calcTimeKey(int(time.time())))
|
||||
r = get_content(info_url, decoded=False)
|
||||
info=json.loads(str(r,"utf-8"))
|
||||
|
||||
|
||||
stream_id = None
|
||||
support_stream_id = info["playurl"]["dispatch"].keys()
|
||||
if "stream_id" in kwargs and kwargs["stream_id"].lower() in support_stream_id:
|
||||
stream_id = kwargs["stream_id"]
|
||||
else:
|
||||
print("Current Video Supports:")
|
||||
for i in support_stream_id:
|
||||
print("\t--format",i,"<URL>")
|
||||
if "1080p" in support_stream_id:
|
||||
stream_id = '1080p'
|
||||
elif "720p" in support_stream_id:
|
||||
stream_id = '720p'
|
||||
else:
|
||||
stream_id =sorted(support_stream_id,key= lambda i: int(i[1:]))[-1]
|
||||
|
||||
url =info["playurl"]["domain"][0]+info["playurl"]["dispatch"][stream_id][0]
|
||||
ext = info["playurl"]["dispatch"][stream_id][1].split('.')[-1]
|
||||
url+="&ctv=pc&m3v=1&termid=1&format=1&hwtype=un&ostype=Linux&tag=letv&sign=letv&expect=3&tn={}&pay=0&iscpn=f9051&rateid={}".format(random.random(),stream_id)
|
||||
|
||||
r2=get_content(url,decoded=False)
|
||||
for stream in self.stream_types:
|
||||
if stream['id'] in support_stream_id:
|
||||
s_url =info["playurl"]["domain"][0]+info["playurl"]["dispatch"][stream['id']][0]
|
||||
ext = info["playurl"]["dispatch"][stream['id']][1].split('.')[-1]
|
||||
s_url+="&ctv=pc&m3v=1&termid=1&format=1&hwtype=un&ostype=Linux&tag=letv&sign=letv&expect=3&tn={}&pay=0&iscpn=f9051&rateid={}".format(random.random(),stream['id'])
|
||||
r2=get_content(s_url,decoded=False)
|
||||
info2=json.loads(str(r2,"utf-8"))
|
||||
|
||||
# hold on ! more things to do
|
||||
@ -84,66 +74,42 @@ def video_info(vid,**kwargs):
|
||||
m3u8 = get_content(info2["location"],decoded=False)
|
||||
m3u8_list = decode(m3u8)
|
||||
urls = re.findall(r'^[^#][^\r]*',m3u8_list,re.MULTILINE)
|
||||
return ext,urls
|
||||
self.streams[stream['id']] = {'container': ext, 'video_profile': stream['video_profile'], 'src': urls, 'size' : 0}
|
||||
|
||||
def letv_download_by_vid(vid,title, output_dir='.', merge=True, info_only=False,**kwargs):
|
||||
ext , urls = video_info(vid,**kwargs)
|
||||
def extract(self, **kwargs):
|
||||
if 'info_only' in kwargs and kwargs['info_only']:
|
||||
for stream_id in self.streams.keys():
|
||||
size = 0
|
||||
for i in urls:
|
||||
for i in self.streams[stream_id]['src']:
|
||||
_, _, tmp = url_info(i)
|
||||
size += tmp
|
||||
stream['size'] = size
|
||||
return
|
||||
#ignore video size in download/play mode, for preformence issue
|
||||
if 'stream_id' in kwargs and kwargs['stream_id']:
|
||||
# Extract the stream
|
||||
stream_id = kwargs['stream_id']
|
||||
|
||||
print_info(site_info, title, ext, size)
|
||||
if not info_only:
|
||||
download_urls(urls, title, ext, size, output_dir=output_dir, merge=merge)
|
||||
|
||||
def letvcloud_download_by_vu(vu, uu, title=None, output_dir='.', merge=True, info_only=False):
|
||||
#ran = float('0.' + str(random.randint(0, 9999999999999999))) # For ver 2.1
|
||||
#str2Hash = 'cfflashformatjsonran{ran}uu{uu}ver2.2vu{vu}bie^#@(%27eib58'.format(vu = vu, uu = uu, ran = ran) #Magic!/ In ver 2.1
|
||||
argumet_dict ={'cf' : 'flash', 'format': 'json', 'ran': str(int(time.time())), 'uu': str(uu),'ver': '2.2', 'vu': str(vu), }
|
||||
sign_key = '2f9d6924b33a165a6d8b5d3d42f4f987' #ALL YOUR BASE ARE BELONG TO US
|
||||
str2Hash = ''.join([i + argumet_dict[i] for i in sorted(argumet_dict)]) + sign_key
|
||||
sign = hashlib.md5(str2Hash.encode('utf-8')).hexdigest()
|
||||
request_info = urllib.request.Request('http://api.letvcloud.com/gpc.php?' + '&'.join([i + '=' + argumet_dict[i] for i in argumet_dict]) + '&sign={sign}'.format(sign = sign))
|
||||
response = urllib.request.urlopen(request_info)
|
||||
data = response.read()
|
||||
info = json.loads(data.decode('utf-8'))
|
||||
type_available = []
|
||||
for video_type in info['data']['video_info']['media']:
|
||||
type_available.append({'video_url': info['data']['video_info']['media'][video_type]['play_url']['main_url'], 'video_quality': int(info['data']['video_info']['media'][video_type]['play_url']['vtype'])})
|
||||
urls = [base64.b64decode(sorted(type_available, key = lambda x:x['video_quality'])[-1]['video_url']).decode("utf-8")]
|
||||
size = urls_size(urls)
|
||||
ext = 'mp4'
|
||||
print_info(site_info, title, ext, size)
|
||||
if not info_only:
|
||||
download_urls(urls, title, ext, size, output_dir=output_dir, merge=merge)
|
||||
|
||||
def letvcloud_download(url, output_dir='.', merge=True, info_only=False):
|
||||
for i in url.split('&'):
|
||||
if 'vu=' in i:
|
||||
vu = i[3:]
|
||||
if 'uu=' in i:
|
||||
uu = i[3:]
|
||||
if len(vu) == 0:
|
||||
raise ValueError('Cannot get vu!')
|
||||
if len(uu) == 0:
|
||||
raise ValueError('Cannot get uu!')
|
||||
title = "LETV-%s" % vu
|
||||
letvcloud_download_by_vu(vu, uu, title=title, output_dir=output_dir, merge=merge, info_only=info_only)
|
||||
|
||||
def letv_download(url, output_dir='.', merge=True, info_only=False ,**kwargs):
|
||||
if re.match(r'http://yuntv.letv.com/', url):
|
||||
letvcloud_download(url, output_dir=output_dir, merge=merge, info_only=info_only)
|
||||
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:
|
||||
html = get_content(url)
|
||||
#to get title
|
||||
if re.match(r'http://www.letv.com/ptv/vplay/(\d+).html', url):
|
||||
vid = match1(url, r'http://www.letv.com/ptv/vplay/(\d+).html')
|
||||
else:
|
||||
vid = match1(html, r'vid="(\d+)"')
|
||||
title = match1(html,r'name="irTitle" content="(.*?)"')
|
||||
letv_download_by_vid(vid, title=title, output_dir=output_dir, merge=merge, info_only=info_only,**kwargs)
|
||||
# Extract stream with the best quality
|
||||
stream_id = self.streams_sorted[0]['id']
|
||||
|
||||
site_info = "LeTV.com"
|
||||
download = letv_download
|
||||
size = 0
|
||||
for i in self.streams[stream_id]['src']:
|
||||
_, _, tmp = url_info(i)
|
||||
size += tmp
|
||||
self.streams[stream_id]['size'] = size
|
||||
|
||||
|
||||
def letvcloud_download_by_vu(vu, uu, title=None, output_dir='.', merge=True, info_only=False, **kwargs):
|
||||
from .letvcloud import letvcloud_download_by_vid
|
||||
letvcloud_download_by_vid((vu, uu), title=title, output_dir=output_dir, merge=merge, info_only=info_only,**kwargs)
|
||||
|
||||
site = Letv()
|
||||
download = site.download_by_url
|
||||
letv_download_by_vid = site.download_by_vid
|
||||
download_playlist = playlist_not_supported('letv')
|
||||
|
53
src/you_get/extractors/letvcloud.py
Normal file
53
src/you_get/extractors/letvcloud.py
Normal file
@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from ..common import *
|
||||
from ..extractor import VideoExtractor
|
||||
import json
|
||||
import base64, hashlib, time, re
|
||||
|
||||
class Letvcloud(VideoExtractor):
|
||||
name = "乐视云 (Letvcloud)"
|
||||
|
||||
stream_types = [
|
||||
{'id': 'yuanhua', 'container': 'mp4', 'video_profile': '原画'},
|
||||
{'id': 'super', 'container': 'mp4', 'video_profile': '超清'},
|
||||
{'id': 'high', 'container': 'mp4', 'video_profile': '高清'},
|
||||
{'id': 'low', 'container': 'mp4', 'video_profile': '标清'},
|
||||
]
|
||||
|
||||
def letvcloud_download_by_vu(self):
|
||||
#ran = float('0.' + str(random.randint(0, 9999999999999999))) # For ver 2.1
|
||||
#str2Hash = 'cfflashformatjsonran{ran}uu{uu}ver2.2vu{vu}bie^#@(%27eib58'.format(vu = vu, uu = uu, ran = ran) #Magic!/ In ver 2.1
|
||||
vu, uu = self.vid
|
||||
argumet_dict ={'cf' : 'flash', 'format': 'json', 'ran': str(int(time.time())), 'uu': str(uu),'ver': '2.2', 'vu': str(vu), }
|
||||
sign_key = '2f9d6924b33a165a6d8b5d3d42f4f987' #ALL YOUR BASE ARE BELONG TO US
|
||||
str2Hash = ''.join([i + argumet_dict[i] for i in sorted(argumet_dict)]) + sign_key
|
||||
sign = hashlib.md5(str2Hash.encode('utf-8')).hexdigest()
|
||||
html = get_content('http://api.letvcloud.com/gpc.php?' + '&'.join([i + '=' + argumet_dict[i] for i in argumet_dict]) + '&sign={sign}'.format(sign = sign), decoded = False)
|
||||
info = json.loads(str(html,"utf-8"))
|
||||
|
||||
available_stream_type = info['data']['video_info']['media'].keys()
|
||||
for stream in self.stream_types:
|
||||
if stream['id'] in available_stream_type:
|
||||
urls = [base64.b64decode(info['data']['video_info']['media'][stream['id']]['play_url']['main_url']).decode("utf-8")]
|
||||
size = urls_size(urls)
|
||||
ext = 'mp4'
|
||||
self.streams[stream['id']] = {'container': ext, 'video_profile': stream['video_profile'], 'src': urls, 'size' : size}
|
||||
|
||||
def prepare(self, **kwargs):
|
||||
assert self.url or self.vid
|
||||
|
||||
if self.url and not self.vid:
|
||||
#maybe error!!
|
||||
self.vid = (vu, uu) = matchall(self.url, ["vu=([^&]+)","uu=([^&]+)"])
|
||||
_, vu = self.vid
|
||||
if 'title' in kwargs and kwargs['title']:
|
||||
self.title = kwargs['title']
|
||||
else:
|
||||
self.title = "LeTV - {}".format(vu)
|
||||
self.letvcloud_download_by_vu()
|
||||
|
||||
site = Letvcloud()
|
||||
download = site.download_by_url
|
||||
letvcloud_download_by_vid = site.download_by_vid
|
||||
download_playlist = playlist_not_supported('letvcloud')
|
Loading…
Reference in New Issue
Block a user