Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

有计划支持pp体育直播吗? #385

Open
simonfire007 opened this issue Mar 8, 2019 · 14 comments
Open

有计划支持pp体育直播吗? #385

simonfire007 opened this issue Mar 8, 2019 · 14 comments

Comments

@simonfire007
Copy link
Contributor

网页看还在使用flash,体验不好

@SeaHOH
Copy link
Collaborator

SeaHOH commented Mar 9, 2019

需要破解算法。

@wnpllrzodiac
Copy link

用 ppbox.so 下载了看吧。分段flv比较简单,主要是 下载地址要找到

@wnpllrzodiac
Copy link

http://www.huaren.tv/sports
可以关注下,英超应该是 pptv那里来的源

@bigmangos
Copy link

下载直播?

@airdge
Copy link
Collaborator

airdge commented Dec 18, 2019

算法和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)

图片

@SeaHOH
Copy link
Collaborator

SeaHOH commented Dec 18, 2019

年底比较忙,空闲都用在另一个项目上了。欢迎有人能挤出时间来 PR。

@wnpllrzodiac
Copy link

要当前有直播才能调试,可是都是晚上。有点尴尬。

@airdge
Copy link
Collaborator

airdge commented Jan 10, 2020

#!/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"
}

@wnpllrzodiac
Copy link

very good!

@wnpllrzodiac
Copy link

@airdge 好像失效了。可惜

@airdge
Copy link
Collaborator

airdge commented Jun 8, 2020

@airdge 好像失效了。可惜

type=mhpptv

图片

@wnpllrzodiac
Copy link

@airdge 好像失效了。可惜

type=mhpptv

图片

I will try it!
THX!!!

@die9o
Copy link

die9o commented Dec 5, 2020

#!/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"
}

你好,照着你的代码我也读到了m3u8,http://live2.vcdn.pplive.cn/live/5/30/b2b336baa56db209f24028cdf5248752.m3u8?k=1b4068f4ffa97049072945b5779f5010-e9ac-1607201005%26bppcataid%3D38&type=web,但是读取里面一个分片ts信息返回了403,播放不了,有解决的思路吗。

@airdge
Copy link
Collaborator

airdge commented Dec 5, 2020

#!/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"
}

你好,照着你的代码我也读到了m3u8,http://live2.vcdn.pplive.cn/live/5/30/b2b336baa56db209f24028cdf5248752.m3u8?k=1b4068f4ffa97049072945b5779f5010-e9ac-1607201005%26bppcataid%3D38&type=web,但是读取里面一个分片ts信息返回了403,播放不了,有解决的思路吗。

type=mhpptv

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants