Open simonfire007 opened 5 years ago
需要破解算法。
用 ppbox.so 下载了看吧。分段flv比较简单,主要是 下载地址要找到
http://www.huaren.tv/sports 可以关注下,英超应该是 pptv那里来的源
下载直播?
算法和pptv差不多
网页使用的是live2 (5s一个block)
但可以用M3U8拼接
http://{ip}/live/{interval}/{delay}/{rid}.m3u8?type={type}&k={k}
从数据里面可以匹配到interval delay rid sh等相关参数 直播api没有id数据(< id>xxx< /id>),可以忽略
<dt ft="3" rid="115c87c2c55abddc7ae50c28996b94f6">
<sh limit="0|2000">61.164.212.42:80</sh>
<st>Wed Dec 18 11:34:41 2019 UTC</st>
<bwt>0</bwt>
<key expire="Wed Dec 18 23:34:41 2019 UTC">
e25a8439c45f5f941fdb162f42c819e0-4b9a-1576712081%26bppcataid%3D38
</key>
<bh limit="0|2000">219.146.248.53:80</bh>
</dt>
<bc>
<bwt>0</bwt>
</bc>
<itemList>
<item id="4" intValue="0" itemValue=""/>
<item id="3" intValue="0" itemValue=""/>
<item id="9" intValue="0" itemValue=""/>
<item id="7" intValue="0" itemValue=""/>
<item id="8" intValue="0" itemValue=""/>
<item id="172" intValue="0" itemValue=""/>
<item id="173" intValue="0" itemValue=""/>
<item id="174" intValue="0" itemValue=""/>
<item id="175" intValue="0" itemValue=""/>
<item id="214" intValue="0" itemValue="delay,30;interval,5">delay,30;interval,5</item>
<item id="201" intValue="0" itemValue="3,4">3,4</item>
<item id="216" intValue="0" itemValue=""/>
</itemList>
kdecrypt算法(通用)
from Crypto.Cipher import AES
from binascii import hexlify, unhexlify
import hashlib
def sha256(string):
return hashlib.sha256(string.encode("utf-8")).hexdigest()
def kdecrypt(key, sh, st, id, bh, iv):
playAppKey = "V8oo0Or1f047NaiMTxK123LMFuINTNeI"
hashkey = sha256("{}{}{}{}{}{}".format(sh, st, id, bh, iv, playAppKey))
cipher = AES.new(unhexlify(hashkey), AES.MODE_ECB)
plaintext = cipher.decrypt(unhexlify(key[0:32]))
return "{}{}".format(bytes.decode(hexlify(plaintext)[0:32]), key[32:])
key='5b06c0d53cbf4afa89d6aa8e76967ea5-4f0e-1576701296%26bppcataid%3D38'
sh='61.164.212.42:80'
st='Wed Dec 18 08:34:56 2019 UTC'
id=''
bh='117.21.186.148:80'
iv='0a604b7ae4d4b3f5af43c47aa00a027a'
k= kdecrypt(key, sh, st,id, bh, iv)
print(k)
年底比较忙,空闲都用在另一个项目上了。欢迎有人能挤出时间来 PR。
要当前有直播才能调试,可是都是晚上。有点尴尬。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@File : pptv.py
@Time : 2019/12/18 17:14
"""
from Crypto.Cipher import AES
from binascii import hexlify, unhexlify
import importlib
def query(self, p):
logger = self.logging.getLogger("query")
common = self.common
if p["parse"].startswith("http"):
vid = common.match("sectionid=(\d+)", p["parse"])
else:
vid = p["parse"]
if p["query"]:
url = (
"https://sportlive.suning.com/slsp-web/cms/competitionschedule/v1/detail/section.do?sectionid=%s&liveFlag=0&app=web&longzhu=0"
% vid
)
html = common.curl(url)
logger.debug("section: " + html + "\r\n")
json = common.loads(html)
title = json["data"]["sectionInfo"]["title"]
return self.compact("query")
def parse(self, p):
logger = self.logging.getLogger("parse")
common = self.common
assert p["vid"], self.message.output("vid")
vid = p["vid"]
url = (
"https://sportlive.suning.com/slsp-web/cms/competitionschedule/v1/detail/section.do?sectionid=%s&liveFlag=0&app=web&longzhu=0"
% vid
)
html = common.curl(url)
logger.debug("section: " + html + "\r\n")
json = common.loads(html)
title = json["data"]["sectionInfo"]["title"]
# assert json["data"]["liveFlag"] == "1", self.message.output("close")
if json["data"]["liveFlag"] == "1":
cid = json["data"]["sectionInfo"]["lives"][0]["cid"]
webplayParams = {
"zone": "8",
"vvid": "5199ebda-7ce8-6463-97e9-18254ef22e2b",
"username": "",
"param": "type=web&ahl_ver=1&ahl_random=5c6c25342d512d295f726b3838355827&ahl_signa=b2c418ee1293af26e29e732c1853317813b2b19cc481b993e517ca16d5ff5d41&userType=0&o=m.ppsport.com",
"isSports": "1",
"vts": "0",
"pageUrl": "https://sports.pptv.com/sportslive?sectionid=171471",
"o": "m.ppsport.com",
"type": "web",
"salt": "pv",
"sl": "1",
"referrer": "https://m.ppsport.com/live/z5D1c9tBse9S0Dg",
"version": "6",
"appplt": "flp",
"appid": "pptv.flashplayer.live",
"appver": "2.12.59",
"nddp": "1",
}
webplayUrl = "https://web-play.pptv.com/webplay3-0-{}.xml?{}".format(
cid, common.urlencode(webplayParams)
)
webplayHtml = common.curl(webplayUrl)
logger.debug("xml: " + webplayHtml + "\r\n")
dtList = common.matchall("<dt(.*?)<\/dt>", webplayHtml.replace("\n", ""))
assert dtList, self.message.output("lists")
# common.data函数,列表按hd取一组数据
dt = common.data(dtList, p["hd"])
rid = common.match('rid="(\w+)', dt)
ary = ["流畅", "标清", "高清", "超清", "蓝光"]
quality = ary[0 : len(dt)]
show = common.data(quality, p["hd"])
match = common.matchall(
"<(\w+).*?>([^\<]+)<\/\w+>", dt.replace("<ip_serviceid/>", "")
)
array = {i[0]: i[1] for i in match}
key = kdecrypt(
self, array["key"], array["sh"], array["st"], "", array["bh"], array["iv"]
)
delay, interval = common.match("delay,(\d+);interval,(\d+)", webplayHtml)
m3u8 = "http://%s/live/%s/%s/%s.m3u8?k=%s&type=web" % (
array["sh"],
interval,
delay,
rid,
key,
)
ext = playback = "m3u8"
elif json["data"]["liveFlag"] == "2":
self.params["vtype"] = "video"
afterCid = json["data"]["sectionInfo"]["lives"][0]["afterCid"]
image = "http://s1.pplive.cn/v/cap/%s/w640.jpg" % afterCid
imp = importlib.import_module("parse.video.pptv")
data = imp.parse(self, {"vid": afterCid, "hd": p["hd"], "from": "pptv"})
for i in data:
locals()[i] = data[i]
return self.compact("parse")
def kdecrypt(self, key, sh, st, id, bh, iv):
playAppKey = "V8oo0Or1f047NaiMTxK123LMFuINTNeI"
hashkey = self.common.sha256("{}{}{}{}{}{}".format(sh, st, id, bh, iv, playAppKey))
cipher = AES.new(unhexlify(hashkey), AES.MODE_ECB)
plaintext = cipher.decrypt(unhexlify(key[0:32]))
return "{}{}".format(bytes.decode(hexlify(plaintext)[0:32]), key[32:])
算法差不多是这样,可以当下参考
{
"cid": "505779",
"ext": "m3u8",
"hd": 5,
"multirates": 5,
"parse": "http://sports.pptv.com/sportslive/pg_h5live?sectionid=172160&matchid=",
"playback": "m3u8",
"quality": [
"流畅",
"标清",
"高清",
"超清",
"蓝光"
],
"show": "蓝光",
"site": "PPTV直播(PPTV)",
"streams": {
"m3u8": "http://27.159.123.226:80/live/5/30/557ce94254c89ce64edeb8d38530d64d.m3u8?k=03b935baf58f785f8adba83e96917eca-5592-1578687462%26bppcataid%3D38&type=web"
},
"title": "走进CBA全明星",
"type": "pptv",
"vid": "172160",
"vtype": "live"
}
very good!
@airdge 好像失效了。可惜
@airdge 好像失效了。可惜
type=mhpptv
@airdge 好像失效了。可惜
type=mhpptv
I will try it! THX!!!
#!/usr/bin/env python # -*- coding: utf-8 -*- """ @File : pptv.py @Time : 2019/12/18 17:14 """ from Crypto.Cipher import AES from binascii import hexlify, unhexlify import importlib def query(self, p): logger = self.logging.getLogger("query") common = self.common if p["parse"].startswith("http"): vid = common.match("sectionid=(\d+)", p["parse"]) else: vid = p["parse"] if p["query"]: url = ( "https://sportlive.suning.com/slsp-web/cms/competitionschedule/v1/detail/section.do?sectionid=%s&liveFlag=0&app=web&longzhu=0" % vid ) html = common.curl(url) logger.debug("section: " + html + "\r\n") json = common.loads(html) title = json["data"]["sectionInfo"]["title"] return self.compact("query") def parse(self, p): logger = self.logging.getLogger("parse") common = self.common assert p["vid"], self.message.output("vid") vid = p["vid"] url = ( "https://sportlive.suning.com/slsp-web/cms/competitionschedule/v1/detail/section.do?sectionid=%s&liveFlag=0&app=web&longzhu=0" % vid ) html = common.curl(url) logger.debug("section: " + html + "\r\n") json = common.loads(html) title = json["data"]["sectionInfo"]["title"] # assert json["data"]["liveFlag"] == "1", self.message.output("close") if json["data"]["liveFlag"] == "1": cid = json["data"]["sectionInfo"]["lives"][0]["cid"] webplayParams = { "zone": "8", "vvid": "5199ebda-7ce8-6463-97e9-18254ef22e2b", "username": "", "param": "type=web&ahl_ver=1&ahl_random=5c6c25342d512d295f726b3838355827&ahl_signa=b2c418ee1293af26e29e732c1853317813b2b19cc481b993e517ca16d5ff5d41&userType=0&o=m.ppsport.com", "isSports": "1", "vts": "0", "pageUrl": "https://sports.pptv.com/sportslive?sectionid=171471", "o": "m.ppsport.com", "type": "web", "salt": "pv", "sl": "1", "referrer": "https://m.ppsport.com/live/z5D1c9tBse9S0Dg", "version": "6", "appplt": "flp", "appid": "pptv.flashplayer.live", "appver": "2.12.59", "nddp": "1", } webplayUrl = "https://web-play.pptv.com/webplay3-0-{}.xml?{}".format( cid, common.urlencode(webplayParams) ) webplayHtml = common.curl(webplayUrl) logger.debug("xml: " + webplayHtml + "\r\n") dtList = common.matchall("<dt(.*?)<\/dt>", webplayHtml.replace("\n", "")) assert dtList, self.message.output("lists") # common.data函数,列表按hd取一组数据 dt = common.data(dtList, p["hd"]) rid = common.match('rid="(\w+)', dt) ary = ["流畅", "标清", "高清", "超清", "蓝光"] quality = ary[0 : len(dt)] show = common.data(quality, p["hd"]) match = common.matchall( "<(\w+).*?>([^\<]+)<\/\w+>", dt.replace("<ip_serviceid/>", "") ) array = {i[0]: i[1] for i in match} key = kdecrypt( self, array["key"], array["sh"], array["st"], "", array["bh"], array["iv"] ) delay, interval = common.match("delay,(\d+);interval,(\d+)", webplayHtml) m3u8 = "http://%s/live/%s/%s/%s.m3u8?k=%s&type=web" % ( array["sh"], interval, delay, rid, key, ) ext = playback = "m3u8" elif json["data"]["liveFlag"] == "2": self.params["vtype"] = "video" afterCid = json["data"]["sectionInfo"]["lives"][0]["afterCid"] image = "http://s1.pplive.cn/v/cap/%s/w640.jpg" % afterCid imp = importlib.import_module("parse.video.pptv") data = imp.parse(self, {"vid": afterCid, "hd": p["hd"], "from": "pptv"}) for i in data: locals()[i] = data[i] return self.compact("parse") def kdecrypt(self, key, sh, st, id, bh, iv): playAppKey = "V8oo0Or1f047NaiMTxK123LMFuINTNeI" hashkey = self.common.sha256("{}{}{}{}{}{}".format(sh, st, id, bh, iv, playAppKey)) cipher = AES.new(unhexlify(hashkey), AES.MODE_ECB) plaintext = cipher.decrypt(unhexlify(key[0:32])) return "{}{}".format(bytes.decode(hexlify(plaintext)[0:32]), key[32:])
算法差不多是这样,可以当下参考
{ "cid": "505779", "ext": "m3u8", "hd": 5, "multirates": 5, "parse": "http://sports.pptv.com/sportslive/pg_h5live?sectionid=172160&matchid=", "playback": "m3u8", "quality": [ "流畅", "标清", "高清", "超清", "蓝光" ], "show": "蓝光", "site": "PPTV直播(PPTV)", "streams": { "m3u8": "http://27.159.123.226:80/live/5/30/557ce94254c89ce64edeb8d38530d64d.m3u8?k=03b935baf58f785f8adba83e96917eca-5592-1578687462%26bppcataid%3D38&type=web" }, "title": "走进CBA全明星", "type": "pptv", "vid": "172160", "vtype": "live" }
#!/usr/bin/env python # -*- coding: utf-8 -*- """ @File : pptv.py @Time : 2019/12/18 17:14 """ from Crypto.Cipher import AES from binascii import hexlify, unhexlify import importlib def query(self, p): logger = self.logging.getLogger("query") common = self.common if p["parse"].startswith("http"): vid = common.match("sectionid=(\d+)", p["parse"]) else: vid = p["parse"] if p["query"]: url = ( "https://sportlive.suning.com/slsp-web/cms/competitionschedule/v1/detail/section.do?sectionid=%s&liveFlag=0&app=web&longzhu=0" % vid ) html = common.curl(url) logger.debug("section: " + html + "\r\n") json = common.loads(html) title = json["data"]["sectionInfo"]["title"] return self.compact("query") def parse(self, p): logger = self.logging.getLogger("parse") common = self.common assert p["vid"], self.message.output("vid") vid = p["vid"] url = ( "https://sportlive.suning.com/slsp-web/cms/competitionschedule/v1/detail/section.do?sectionid=%s&liveFlag=0&app=web&longzhu=0" % vid ) html = common.curl(url) logger.debug("section: " + html + "\r\n") json = common.loads(html) title = json["data"]["sectionInfo"]["title"] # assert json["data"]["liveFlag"] == "1", self.message.output("close") if json["data"]["liveFlag"] == "1": cid = json["data"]["sectionInfo"]["lives"][0]["cid"] webplayParams = { "zone": "8", "vvid": "5199ebda-7ce8-6463-97e9-18254ef22e2b", "username": "", "param": "type=web&ahl_ver=1&ahl_random=5c6c25342d512d295f726b3838355827&ahl_signa=b2c418ee1293af26e29e732c1853317813b2b19cc481b993e517ca16d5ff5d41&userType=0&o=m.ppsport.com", "isSports": "1", "vts": "0", "pageUrl": "https://sports.pptv.com/sportslive?sectionid=171471", "o": "m.ppsport.com", "type": "web", "salt": "pv", "sl": "1", "referrer": "https://m.ppsport.com/live/z5D1c9tBse9S0Dg", "version": "6", "appplt": "flp", "appid": "pptv.flashplayer.live", "appver": "2.12.59", "nddp": "1", } webplayUrl = "https://web-play.pptv.com/webplay3-0-{}.xml?{}".format( cid, common.urlencode(webplayParams) ) webplayHtml = common.curl(webplayUrl) logger.debug("xml: " + webplayHtml + "\r\n") dtList = common.matchall("<dt(.*?)<\/dt>", webplayHtml.replace("\n", "")) assert dtList, self.message.output("lists") # common.data函数,列表按hd取一组数据 dt = common.data(dtList, p["hd"]) rid = common.match('rid="(\w+)', dt) ary = ["流畅", "标清", "高清", "超清", "蓝光"] quality = ary[0 : len(dt)] show = common.data(quality, p["hd"]) match = common.matchall( "<(\w+).*?>([^\<]+)<\/\w+>", dt.replace("<ip_serviceid/>", "") ) array = {i[0]: i[1] for i in match} key = kdecrypt( self, array["key"], array["sh"], array["st"], "", array["bh"], array["iv"] ) delay, interval = common.match("delay,(\d+);interval,(\d+)", webplayHtml) m3u8 = "http://%s/live/%s/%s/%s.m3u8?k=%s&type=web" % ( array["sh"], interval, delay, rid, key, ) ext = playback = "m3u8" elif json["data"]["liveFlag"] == "2": self.params["vtype"] = "video" afterCid = json["data"]["sectionInfo"]["lives"][0]["afterCid"] image = "http://s1.pplive.cn/v/cap/%s/w640.jpg" % afterCid imp = importlib.import_module("parse.video.pptv") data = imp.parse(self, {"vid": afterCid, "hd": p["hd"], "from": "pptv"}) for i in data: locals()[i] = data[i] return self.compact("parse") def kdecrypt(self, key, sh, st, id, bh, iv): playAppKey = "V8oo0Or1f047NaiMTxK123LMFuINTNeI" hashkey = self.common.sha256("{}{}{}{}{}{}".format(sh, st, id, bh, iv, playAppKey)) cipher = AES.new(unhexlify(hashkey), AES.MODE_ECB) plaintext = cipher.decrypt(unhexlify(key[0:32])) return "{}{}".format(bytes.decode(hexlify(plaintext)[0:32]), key[32:])
算法差不多是这样,可以当下参考
{ "cid": "505779", "ext": "m3u8", "hd": 5, "multirates": 5, "parse": "http://sports.pptv.com/sportslive/pg_h5live?sectionid=172160&matchid=", "playback": "m3u8", "quality": [ "流畅", "标清", "高清", "超清", "蓝光" ], "show": "蓝光", "site": "PPTV直播(PPTV)", "streams": { "m3u8": "http://27.159.123.226:80/live/5/30/557ce94254c89ce64edeb8d38530d64d.m3u8?k=03b935baf58f785f8adba83e96917eca-5592-1578687462%26bppcataid%3D38&type=web" }, "title": "走进CBA全明星", "type": "pptv", "vid": "172160", "vtype": "live" }
type=mhpptv
网页看还在使用flash,体验不好