mirror of
https://github.com/soimort/you-get.git
synced 2025-02-12 13:05:19 +03:00
stream_id % 10 ** 3 if stream_id < 10 ** 4 else stream_id % 10 ** 4
This commit is contained in:
parent
eeae0da6ed
commit
c95d537fb4
@ -3,7 +3,7 @@ __all__ = ['qq_download']
|
|||||||
|
|
||||||
from ..common import *
|
from ..common import *
|
||||||
from .qie import download as qieDownload, VideoExtractor
|
from .qie import download as qieDownload, VideoExtractor
|
||||||
from urllib.parse import urlparse,parse_qs
|
from urllib.parse import urlparse, parse_qs
|
||||||
import struct
|
import struct
|
||||||
import base64
|
import base64
|
||||||
import random
|
import random
|
||||||
@ -17,6 +17,7 @@ ZERO_LEN = 7
|
|||||||
|
|
||||||
SEED = 0xdead
|
SEED = 0xdead
|
||||||
|
|
||||||
|
|
||||||
def rand():
|
def rand():
|
||||||
global SEED
|
global SEED
|
||||||
if SEED == 0:
|
if SEED == 0:
|
||||||
@ -28,19 +29,22 @@ def rand():
|
|||||||
SEED = SEED + 2147483647
|
SEED = SEED + 2147483647
|
||||||
return SEED
|
return SEED
|
||||||
|
|
||||||
|
|
||||||
def pack(data):
|
def pack(data):
|
||||||
target = []
|
target = []
|
||||||
for i in data:
|
for i in data:
|
||||||
target.extend(struct.pack('>I', i))
|
target.extend(struct.pack('>I', i))
|
||||||
return target
|
return target
|
||||||
|
|
||||||
|
|
||||||
def unpack(data):
|
def unpack(data):
|
||||||
data = bytes(data)
|
data = bytes(data)
|
||||||
target = []
|
target = []
|
||||||
for i in range(0, len(data), 4):
|
for i in range(0, len(data), 4):
|
||||||
target.extend(struct.unpack('>I', data[i:i+4]))
|
target.extend(struct.unpack('>I', data[i:i + 4]))
|
||||||
return target
|
return target
|
||||||
|
|
||||||
|
|
||||||
def tea_encrypt(v, key):
|
def tea_encrypt(v, key):
|
||||||
s = 0
|
s = 0
|
||||||
key = unpack(key)
|
key = unpack(key)
|
||||||
@ -48,12 +52,13 @@ def tea_encrypt(v, key):
|
|||||||
for i in range(ROUNDS):
|
for i in range(ROUNDS):
|
||||||
s += DELTA
|
s += DELTA
|
||||||
s &= 0xffffffff
|
s &= 0xffffffff
|
||||||
v[0] += (v[1]+s) ^ ((v[1]>>5)+key[1]) ^ ((v[1]<<4)+key[0])
|
v[0] += (v[1] + s) ^ ((v[1] >> 5) + key[1]) ^ ((v[1] << 4) + key[0])
|
||||||
v[0] &= 0xffffffff
|
v[0] &= 0xffffffff
|
||||||
v[1] += (v[0]+s) ^ ((v[0]>>5)+key[3]) ^ ((v[0]<<4)+key[2])
|
v[1] += (v[0] + s) ^ ((v[0] >> 5) + key[3]) ^ ((v[0] << 4) + key[2])
|
||||||
v[1] &= 0xffffffff
|
v[1] &= 0xffffffff
|
||||||
return pack(v)
|
return pack(v)
|
||||||
|
|
||||||
|
|
||||||
def oi_symmetry_encrypt2(raw_data, key):
|
def oi_symmetry_encrypt2(raw_data, key):
|
||||||
pad_salt_body_zero_len = 1 + SALT_LEN + len(raw_data) + ZERO_LEN
|
pad_salt_body_zero_len = 1 + SALT_LEN + len(raw_data) + ZERO_LEN
|
||||||
pad_len = pad_salt_body_zero_len % 8
|
pad_len = pad_salt_body_zero_len % 8
|
||||||
@ -72,12 +77,12 @@ def oi_symmetry_encrypt2(raw_data, key):
|
|||||||
for i in range(8, len(data), 8):
|
for i in range(8, len(data), 8):
|
||||||
d1 = data[i:]
|
d1 = data[i:]
|
||||||
for j in range(8):
|
for j in range(8):
|
||||||
d1[j] = d1[j] ^ enc[i-8+j]
|
d1[j] = d1[j] ^ enc[i - 8 + j]
|
||||||
d1 = tea_encrypt(d1, key)
|
d1 = tea_encrypt(d1, key)
|
||||||
for j in range(8):
|
for j in range(8):
|
||||||
d1[j] = d1[j] ^ data[i-8+j] ^ temp[j]
|
d1[j] = d1[j] ^ data[i - 8 + j] ^ temp[j]
|
||||||
enc.append(d1[j])
|
enc.append(d1[j])
|
||||||
temp[j] = enc[i-8+j]
|
temp[j] = enc[i - 8 + j]
|
||||||
return enc
|
return enc
|
||||||
|
|
||||||
|
|
||||||
@ -86,20 +91,23 @@ KEY = [
|
|||||||
0x39, 0x6, 0x33, 0xee, 0xfb, 0xbf, 0xf3, 0xb6
|
0x39, 0x6, 0x33, 0xee, 0xfb, 0xbf, 0xf3, 0xb6
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def packstr(data):
|
def packstr(data):
|
||||||
l = len(data)
|
l = len(data)
|
||||||
t = []
|
t = []
|
||||||
t.append((l&0xFF00) >> 8)
|
t.append((l & 0xFF00) >> 8)
|
||||||
t.append(l&0xFF)
|
t.append(l & 0xFF)
|
||||||
t.extend([ord(c) for c in data])
|
t.extend([ord(c) for c in data])
|
||||||
return t
|
return t
|
||||||
|
|
||||||
|
|
||||||
def strsum(data):
|
def strsum(data):
|
||||||
s = 0
|
s = 0
|
||||||
for c in data:
|
for c in data:
|
||||||
s = s*131 + c
|
s = s * 131 + c
|
||||||
return 0x7fffffff & s
|
return 0x7fffffff & s
|
||||||
|
|
||||||
|
|
||||||
def echo_ckeyv3(vid, guid='', t=None, player_version='3.2.38.401', platform=10902, stdfrom='bcng'):
|
def echo_ckeyv3(vid, guid='', t=None, player_version='3.2.38.401', platform=10902, stdfrom='bcng'):
|
||||||
data = []
|
data = []
|
||||||
data.extend(pack([21507, 3168485562]))
|
data.extend(pack([21507, 3168485562]))
|
||||||
@ -108,7 +116,7 @@ def echo_ckeyv3(vid, guid='', t=None, player_version='3.2.38.401', platform=1090
|
|||||||
if not t:
|
if not t:
|
||||||
t = time.time()
|
t = time.time()
|
||||||
seconds = int(t)
|
seconds = int(t)
|
||||||
microseconds = int(1000000*(t - int(t)))
|
microseconds = int(1000000 * (t - int(t)))
|
||||||
data.extend(pack([microseconds, seconds]))
|
data.extend(pack([microseconds, seconds]))
|
||||||
data.extend(packstr(stdfrom))
|
data.extend(packstr(stdfrom))
|
||||||
|
|
||||||
@ -123,12 +131,12 @@ def echo_ckeyv3(vid, guid='', t=None, player_version='3.2.38.401', platform=1090
|
|||||||
data.extend([0x00, 0x00, 0x00, 0x00])
|
data.extend([0x00, 0x00, 0x00, 0x00])
|
||||||
|
|
||||||
l = len(data)
|
l = len(data)
|
||||||
data.insert(0, l&0xFF)
|
data.insert(0, l & 0xFF)
|
||||||
data.insert(0, (l&0xFF00) >> 8)
|
data.insert(0, (l & 0xFF00) >> 8)
|
||||||
|
|
||||||
enc = oi_symmetry_encrypt2(data, KEY)
|
enc = oi_symmetry_encrypt2(data, KEY)
|
||||||
|
|
||||||
pad = [0x00, 0x00, 0x00, 0x00, 0xff&rand(), 0xff&rand(), 0xff&rand(), 0xff&rand()]
|
pad = [0x00, 0x00, 0x00, 0x00, 0xff & rand(), 0xff & rand(), 0xff & rand(), 0xff & rand()]
|
||||||
pad[0] = pad[4] ^ 71 & 0xFF
|
pad[0] = pad[4] ^ 71 & 0xFF
|
||||||
pad[1] = pad[5] ^ -121 & 0xFF
|
pad[1] = pad[5] ^ -121 & 0xFF
|
||||||
pad[2] = pad[6] ^ -84 & 0xFF
|
pad[2] = pad[6] ^ -84 & 0xFF
|
||||||
@ -176,13 +184,18 @@ class QQ(VideoExtractor):
|
|||||||
dict.__init__(self, **kwargs)
|
dict.__init__(self, **kwargs)
|
||||||
self.stream_id = stream_id
|
self.stream_id = stream_id
|
||||||
|
|
||||||
|
def _getfilename(self, lnk, stream_id, idx):
|
||||||
|
return '{lnk}.p{num}.{idx}.mp4'.format(lnk=lnk, num=stream_id % 10 ** 3 if stream_id < 10 ** 4 else stream_id % 10 ** 4, idx=idx)
|
||||||
|
|
||||||
def _getvkey(self, vid, format, idx):
|
def _getvkey(self, vid, format, idx):
|
||||||
import uuid
|
import uuid
|
||||||
appver = '3.2.38.401'
|
appver = '3.2.38.401'
|
||||||
guid = uuid.uuid4().hex.upper()
|
guid = uuid.uuid4().hex.upper()
|
||||||
platform = 11
|
platform = 11
|
||||||
cKey = echo_ckeyv3(vid=vid, guid=guid, player_version=appver, platform=platform)
|
cKey = echo_ckeyv3(vid=vid, guid=guid, player_version=appver, platform=platform)
|
||||||
key_api = 'http://vv.video.qq.com/getvkey?vid={vid}&appver={appver}&platform={platform}&otype=json&filename={lnk}.p{format1000}.{idx}.mp4&format={format}&cKey={cKey}&guid={guid}&charge=1&encryptVer=5.4&lnk={vid}'.format(vid=vid, appver=appver, format1000=format%1000, format=format, cKey=cKey, guid=guid, platform=platform, idx=idx, lnk=lnk)
|
key_api = 'http://vv.video.qq.com/getvkey?vid={vid}&appver={appver}&platform={platform}&otype=json&filename={filename}&format={format}&cKey={cKey}&guid={guid}&charge=1&encryptVer=5.4&lnk={vid}'.format(
|
||||||
|
vid=vid, appver=appver, filename=self._getfilename(lnk, format, idx),
|
||||||
|
format=format, cKey=cKey, guid=guid, platform=platform, lnk=lnk)
|
||||||
part_info = get_html(key_api)
|
part_info = get_html(key_api)
|
||||||
key_json = json.loads(match1(part_info, r'QZOutputJson=(.*)')[:-1])
|
key_json = json.loads(match1(part_info, r'QZOutputJson=(.*)')[:-1])
|
||||||
return 'key' in key_json and key_json['key']
|
return 'key' in key_json and key_json['key']
|
||||||
@ -190,10 +203,10 @@ class QQ(VideoExtractor):
|
|||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if key == 'src' and 'src' not in self:
|
if key == 'src' and 'src' not in self:
|
||||||
self['src'] = []
|
self['src'] = []
|
||||||
for idx in range(1, vi0['cl']['fc']+1):
|
for idx in range(1, vi0['cl']['fc'] + 1):
|
||||||
vkey = self._getvkey(vid, self.stream_id, idx)
|
vkey = self._getvkey(vid, self.stream_id, idx)
|
||||||
if vkey:
|
if vkey:
|
||||||
url = '{prefix}/{lnk}.p{format1000}.{idx}.mp4?vkey={vkey}'.format(prefix=url_prefix, format1000=self.stream_id%1000, idx=idx, vkey=vkey, lnk=lnk)
|
url = '{prefix}/{filename}?vkey={vkey}'.format(prefix=url_prefix, filename=self._getfilename(lnk=lnk, stream_id=self.stream_id, idx=idx), vkey=vkey)
|
||||||
self['src'].append(url)
|
self['src'].append(url)
|
||||||
return self['src']
|
return self['src']
|
||||||
else:
|
else:
|
||||||
@ -232,7 +245,7 @@ def qq_download(url, output_dir='.', merge=True, info_only=False, **kwargs):
|
|||||||
site.download_by_vid(vid=vid, output_dir=output_dir, merge=merge, info_only=info_only, **kwargs)
|
site.download_by_vid(vid=vid, output_dir=output_dir, merge=merge, info_only=info_only, **kwargs)
|
||||||
return
|
return
|
||||||
|
|
||||||
#do redirect
|
# do redirect
|
||||||
if 'v.qq.com/page' in url:
|
if 'v.qq.com/page' in url:
|
||||||
# for URLs like this:
|
# for URLs like this:
|
||||||
# http://v.qq.com/page/k/9/7/k0194pwgw97.html
|
# http://v.qq.com/page/k/9/7/k0194pwgw97.html
|
||||||
@ -249,16 +262,18 @@ def qq_download(url, output_dir='.', merge=True, info_only=False, **kwargs):
|
|||||||
title = vid
|
title = vid
|
||||||
else:
|
else:
|
||||||
content = get_html(url)
|
content = get_html(url)
|
||||||
vid = parse_qs(urlparse(url).query).get('vid') #for links specified vid like http://v.qq.com/cover/p/ps6mnfqyrfo7es3.html?vid=q0181hpdvo5
|
vid = parse_qs(urlparse(url).query).get(
|
||||||
vid = vid[0] if vid else match1(content, r'vid"*\s*:\s*"\s*([^"]+)"') #general fallback
|
'vid') # for links specified vid like http://v.qq.com/cover/p/ps6mnfqyrfo7es3.html?vid=q0181hpdvo5
|
||||||
title = match1(content,r'<a.*?id\s*=\s*"%s".*?title\s*=\s*"(.+?)".*?>'%vid)
|
vid = vid[0] if vid else match1(content, r'vid"*\s*:\s*"\s*([^"]+)"') # general fallback
|
||||||
|
title = match1(content, r'<a.*?id\s*=\s*"%s".*?title\s*=\s*"(.+?)".*?>' % vid)
|
||||||
title = match1(content, r'title">([^"]+)</p>') if not title else title
|
title = match1(content, r'title">([^"]+)</p>') if not title else title
|
||||||
title = match1(content, r'"title":"([^"]+)"') if not title else title
|
title = match1(content, r'"title":"([^"]+)"') if not title else title
|
||||||
title = vid if not title else title #general fallback
|
title = vid if not title else title # general fallback
|
||||||
|
|
||||||
site.download_by_vid(vid=vid, output_dir=output_dir, merge=merge, info_only=info_only, **kwargs)
|
site.download_by_vid(vid=vid, output_dir=output_dir, merge=merge, info_only=info_only, **kwargs)
|
||||||
|
|
||||||
qq_download_by_vid=site.download_by_vid
|
|
||||||
|
qq_download_by_vid = site.download_by_vid
|
||||||
site_info = "QQ.com"
|
site_info = "QQ.com"
|
||||||
download = qq_download
|
download = qq_download
|
||||||
download_playlist = playlist_not_supported('qq')
|
download_playlist = playlist_not_supported('qq')
|
||||||
|
Loading…
Reference in New Issue
Block a user