Skip to content

Commit

Permalink
Merge pull request #39 from ZSAIm/zsaim
Browse files Browse the repository at this point in the history
修复部分腾讯视频无法解析下载问题。
  • Loading branch information
ZSAIm authored May 7, 2019
2 parents 7e1bae9 + f75e07d commit c6d2e04
Show file tree
Hide file tree
Showing 19 changed files with 282 additions and 88 deletions.
14 changes: 11 additions & 3 deletions GUIEventBinder.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def bineEvent():

@staticmethod
def logs(event):
gui.dialog_dllog.ShowModal()
gui.dialog_dllog.Show()

@staticmethod
def settings(event):
Expand Down Expand Up @@ -105,14 +105,18 @@ def bindEvent():
class File:
@staticmethod
def bindEvent():
items = ('settings',)
items = ('logs', 'settings')
FrameParser.MemuBar.batchBind(FrameParser.MemuBar.File, gui.frame_parse.menu_bar.file, items)

@staticmethod
def settings(event):
dlg = gui.DialogSettings(gui.frame_parse)
dlg.ShowModal()

@staticmethod
def logs(event):
gui.dialog_dllog.Show()

class Help:
@staticmethod
def bindEvent():
Expand Down Expand Up @@ -171,14 +175,18 @@ def bindEvent():
class File:
@staticmethod
def bineEvent():
items = ('exit',)
items = ('logs', 'exit')
FrameMerger.MenuBar.batchBind(FrameMerger.MenuBar.File, gui.frame_merger.menu_bar.file, items)

@staticmethod
def settings(event):
dlg = gui.DialogSettings(gui.frame_merger)
dlg.ShowModal()

@staticmethod
def logs(event):
gui.dialog_dllog.Show()

@staticmethod
def exit(event):
flow.ShutDown.handle()
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@


## 更新说明

* **2019/05/07**
* 修复部分腾讯视频无法解析下载问题。
* 加入控制台日志查看(F2调出查看),方便调试。
* 修复单视频文件合并出错问题。

* **2019/05/06**
* 修复标题含有.生成的目录造成的无法下载问题。
* 分离解析核心,方便更新。
* 支持repo拉取更新核心,更新事件位于解析器的菜单[About - Update Core]。

* **2019/05/04**
* 修复腾讯视频导入Cookie无效问题。
Expand Down
3 changes: 1 addition & 2 deletions core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,12 @@ def __init__(self, base_url, title, quality, **extra_info):
self.extra_info = extra_info

def __getattr__(self, item):
if not hasattr(self, item):
if item not in dir(self):
return self.extra_info[item]
else:
return object.__getattribute__(self, item)



class BasicAudioInfo:
def __init__(self, urls, size, info, **extra_info):
self.urls = urls
Expand Down
2 changes: 1 addition & 1 deletion core/repo
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"bilibili.py": "79080c8d0c5bc75febf9361484e5d440", "iqiyi.py": "fd1db81687dc82d7db94e370a6cce369", "tencent.py": "2f4de3645495d674da09bd617f72c5fd", "youku.py": "d41d8cd98f00b204e9800998ecf8427e"}
{"bilibili.py": "79080c8d0c5bc75febf9361484e5d440", "iqiyi.py": "fd1db81687dc82d7db94e370a6cce369", "tencent.py": "7b6ec12b3d949fdac3e82cafe2fdb139", "youku.py": "d41d8cd98f00b204e9800998ecf8427e"}
175 changes: 156 additions & 19 deletions core/tencent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
import json
import PyJSCaller
import time
from urllib.parse import splittype, splithost, urlencode, unquote, splitvalue, splitquery, quote
from urllib.parse import splittype, splithost, urlencode, unquote, splitvalue, splitquery, quote, urljoin
import CommonVar as cv
import random

TENCENT = None
LASTRES = None
Expand Down Expand Up @@ -164,7 +165,57 @@

}

"""
i = {
otype: b ? "ojson" : "json",
vid: a.vid,
format: d(this.dataset.getinfoData.fl.fi),
filename: a.newFileName,
platform: this.context.dataset.platform,
appVer: Txplayer.dataset.ver,
vt: a.vt,
sdtfrom: this.context.dataset.sdtfrom,
guid: this.context.dataset.guid,
flowid: this.context.dataset.flowid,
charge: a.isNeedPay ? 1 : 0,
linkver: 2,
lnk: this.context.dataset.getinfoJSON.vl.vi[0].lnk,
tm: c ? c : l.getTimeStampStr(),
refer: f,
ehost: h
};
"""


vkeyparam = {
'otype': 'ojson',
'platform': '10201',
'appVer': '3.5.57',
'sdtfrom': 'v1010',
'charge': '0',
'linkver': '2',
'unid': '',
'encryptVer': '9.1',


'format': None, # format id
'vid': None,
'filename': None,
'vt': None, # ui[n]['vt']
'guid': None,
'flowid': None, # '_10201',
'lnk': None, # self.program['lnk']
'tm': None,
'refer': None, # base_url
'ehost': None, # base_url
'logintoken': None, # logintoken
'cKey': None,
}

global_vkey = {
'buid': 'onlyvkey',
'vkeyparam': vkeyparam,
}

class Tencent(BasicParser):
def __init__(self):
Expand Down Expand Up @@ -194,30 +245,22 @@ def parse(self, url, quality):
seg_path = path.split('/')
if seg_path[-2] == 'cover':
url = bs4.find('link', rel='canonical').get('href')
# text = self.request(url)
# video_info_rex = re.compile('var VIDEO_INFO\s*=\s*({.+?})\s*</script>')

# video_info = json.loads(video_info_rex.search(text).group(1))
s1, s2 = splittype(url)
host, path = splithost(s2)
seg_path = path.split('/')

vid = seg_path[-1].split('.html')[0]


# scripts = bs4.findAll('script')
title = video_info['title']
if self.cookie_str:
self.auth_refresh()

res_videos = []
for i in quality:
# start = time.time_ns()
with PyJSCaller.Sesson('./js/tencent.js') as sess:
getckey, createGUID, setdocument = sess.require('getckey', 'createGUID', 'setdocument')
setdocument(url)


setdocument(url, '')

tm = int(time.time())

Expand Down Expand Up @@ -264,9 +307,14 @@ def parse(self, url, quality):
res_json = json.loads(text)
res_json['vinfo'] = json.loads(res_json['vinfo'])

print(res_json)
if res_json['vinfo'].get('vl'):
res_videos.append(TencentRespond(self, res_json, res_json, BasicVideoInfo(url, title, i)))
info = BasicVideoInfo(url, title, i,
guid=guid.getValue(),
sdtfrom=req_vinfoparam['sdtfrom'],
flowid=flowid.getValue(),
logintoken=new_token,
)
res_videos.append(TencentRespond(self, res_json, res_json, info))


return res_videos
Expand All @@ -287,7 +335,7 @@ def auth_refresh(self):
res_josn = json.loads(text[text.index('{'):])

if res_josn['errcode'] != 0:
raise Exception('incorrect cookie£¬return:', res_josn['msg'])
raise Exception('incorrect cookie, return:', res_josn['msg'])

self.user.extract_headers(res.info().get_all('set-cookie'))
new_cookie_str = self.user.dumps()
Expand Down Expand Up @@ -357,7 +405,6 @@ class TencentRespond(BasicRespond):
def __init__(self, parent, full_json, res_json, extra_info):
BasicRespond.__init__(self, parent, full_json, res_json, extra_info)
self.__extract__()
pass


def __extract__(self):
Expand All @@ -366,7 +413,98 @@ def __extract__(self):
# target video urls
m3u8 = self.getM3U8()
if not m3u8:
m3u8 = self.parent.request(url=self.program['ul']['ui'][0]['url'])
_step = self.program['ul']['ui'][0]['url'].split('/')
url = self.program['ul']['ui'][0]['url']
if _step[-1] and 'm3u8' in _step[-1]:
self.__extract_m3u8__(url)
elif self.program['ul']['ui'][0].get('hls'):
url = urljoin(url, self.program['ul']['ui'][0]['hls']['pt'])
self.__extract_m3u8__(url)
else:
self._target_video_urls = []
base_name, ext = os.path.splitext(self.program['fn'])
format_name = base_name + '.%d' + ext
filenames = [format_name % (i + 1) for i in range(len(self.program['cl']['ci']))]
vkeys, _ = self.get_all_vkey(filenames, self.program['ul']['ui'][0]['vt'])
for i, j in enumerate(vkeys):
url = urljoin(url, filenames[i])
query = {
'vkey': j,
'sdtfrom': self.extra_info.sdtfrom,
'guid': self.extra_info.guid,
}
url = make_query(url, query)
self._target_video_urls.append(url)


def get_all_vkey(self, filenames, vt):
guid = self.extra_info.guid
flowid = self.extra_info.flowid
vid = self.program['vid']
base_url = self.extra_info.base_url
tm = time.time()
tm_s = []
ckeys = []
with PyJSCaller.Sesson('./js/tencent.js') as sess:
getckey, setdocument = sess.require('getckey', 'setdocument')
setdocument(base_url, '')

for i in range(len(filenames)):
cur_tm = int(tm+random.random() + random.randint(1, 2))
tm = cur_tm
tm_s.append(cur_tm)

ckey = getckey('10201', '3.5.57', vid, '', guid, cur_tm)
ckeys.append(ckey)

ckeys_expr = sess.call(ckeys)

vkeys = []
res_json_list = []
for i, j in enumerate(ckeys_expr.getValue()):
update_param = {
'format': self.get_sel_format_id(),
'vid': self.program['vid'],
'filename': filenames[i],
'vt': vt, # ui[n]['vt']
'guid': guid,
'flowid': flowid,
'lnk': self.program['lnk'], # self.program['lnk']
'tm': tm_s[i],
'refer': base_url,
'ehost': base_url,
'logintoken': self.extra_info.logintoken, # logintoken
'cKey': j,
}


req_param = global_vkey.copy()
new_vkey_param = vkeyparam.copy()
new_vkey_param.update(update_param)

req_param['vkeyparam'] = urlencode(new_vkey_param)

req_data = str(req_param).replace("'", '"').encode('utf-8')
text = self.parent.request(method='POST', url='https://vd.l.qq.com/proxyhttp', data=req_data)

res_json = json.loads(text)
if res_json['errCode'] == 0:
res_json['vkey'] = json.loads(res_json['vkey'])
vkeys.append(res_json['vkey']['key'])
res_json_list.append(res_json)

return vkeys, res_json_list


def get_sel_format_id(self):
for i in self.res_json['vinfo']['fl']['fi']:
if i['sl'] == 1:
return i['id']

raise KeyError('selected format id no found')

def __extract_m3u8__(self, m3u8_url):
m3u8 = self.parent.request(url=m3u8_url)

m3u8_parts = re.compile('#EXTINF:([\d\.]+),\s+(.+?)\s+').findall(m3u8)

Expand All @@ -377,8 +515,6 @@ def __extract__(self):
tmp_urls.append([j + i[1] for j in m3u8_paths])
self._target_video_urls = [BasicUrlGroup(tmp_urls)]

# if


def getM3U8(self):
return self.program['ul'].get('m3u8')
Expand Down Expand Up @@ -451,11 +587,12 @@ def matchParse(url, quality, features):
# tx = Tencent()
load_cookie()
user = TencentUser()
url = 'https://v.qq.com/x/cover/wvmn6sg298qr2w0/q0128rs8tpj.html'

user.extract(TENCENT.cookie_str)

res = parse(url, [6])
print(res[0].getM3U8Url())
res = parse(url, [5])
print(res[0].getM3U8Urls())



Expand Down
Loading

0 comments on commit c6d2e04

Please sign in to comment.