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

Update douyu.py and huya.py #376

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 0 additions & 38 deletions 95xiu.py

This file was deleted.

89 changes: 30 additions & 59 deletions douyu.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
# 获取斗鱼直播间的真实流媒体地址,默认最高画质
# 使用 https://github.com/wbt5/real-url/issues/185 中两位大佬@wjxgzz @4bbu6j5885o3gpv6ss8找到的的CDN,在此感谢!
import hashlib
import re
import time

import execjs
import requests
import json


class DouYu:
"""
可用来替换返回链接中的主机部分
两个阿里的CDN:
dyscdnali1.douyucdn.cn
dyscdnali3.douyucdn.cn
墙外不用带尾巴的akm cdn:
hls3-akm.douyucdn.cn
hlsa-akm.douyucdn.cn
hls1a-akm.douyucdn.cn
"""

def __init__(self, rid):
"""
Expand Down Expand Up @@ -57,12 +46,23 @@ def get_pre(self):
}
res = self.s.post(url, headers=headers, data=data).json()
error = res['error']
data = res['data']
key = ''
if data:
rtmp_live = data['rtmp_live']
key = re.search(r'(\d{1,8}[0-9a-zA-Z]+)_?\d{0,4}(/playlist|.m3u8)', rtmp_live).group(1)
return error, key
return error

def get_did(self):
did = '10000000000000000000000000001501'
url = "https://passport.douyu.com/lapi/did/api/get?client_id=25&_={}&callback=axiosJsonpCallback1".format(self.t13)
headers = {
'referer': 'https://m.douyu.com/'
}
try:
res = self.s.get(url=url,headers=headers).text
result = json.loads(re.search(r"axiosJsonpCallback1\((.*)\)", res).group(1))
if result["error"] == 0:
if "did" in result["data"]:
did = result["data"]["did"]
except Exception as e:
print(e)
return did

def get_js(self):
result = re.search(r'(function ub98484234.*)\s(var.*)', self.res).group()
Expand All @@ -79,59 +79,30 @@ def get_js(self):

js = execjs.compile(func_sign)
params = js.call('sign', self.rid, self.did, self.t10)
params += '&ver=219032101&rid={}&rate=-1'.format(self.rid)
params += '&ver=22107261&rid={}&rate=-1'.format(self.rid)

url = 'https://m.douyu.com/api/room/ratestream'
res = self.s.post(url, params=params).text
key = re.search(r'(\d{1,8}[0-9a-zA-Z]+)_?\d{0,4}(.m3u8|/playlist)', res).group(1)

return key

def get_pc_js(self, cdn='ws-h5', rate=0):
"""
通过PC网页端的接口获取完整直播源。
:param cdn: 主线路ws-h5、备用线路tct-h5
:param rate: 1流畅;2高清;3超清;4蓝光4M;0蓝光8M或10M
:return: JSON格式
"""
res = self.s.get('https://www.douyu.com/' + str(self.rid)).text
result = re.search(r'(vdwdae325w_64we[\s\S]*function ub98484234[\s\S]*?)function', res).group(1)
func_ub9 = re.sub(r'eval.*?;}', 'strc;}', result)
js = execjs.compile(func_ub9)
res = js.call('ub98484234')

v = re.search(r'v=(\d+)', res).group(1)
rb = DouYu.md5(self.rid + self.did + self.t10 + v)

func_sign = re.sub(r'return rt;}\);?', 'return rt;}', res)
func_sign = func_sign.replace('(function (', 'function sign(')
func_sign = func_sign.replace('CryptoJS.MD5(cb).toString()', '"' + rb + '"')

js = execjs.compile(func_sign)
params = js.call('sign', self.rid, self.did, self.t10)

params += '&cdn={}&rate={}'.format(cdn, rate)
url = 'https://www.douyu.com/lapi/live/getH5Play/{}'.format(self.rid)
res = self.s.post(url, params=params).json()

return res

def get_real_url(self):
error, key = self.get_pre()
if error == 0:
pass
elif error == 102:
real_url = {}
error = self.get_pre()
if error == 102:
raise Exception('房间不存在')
elif error == 104:
raise Exception('房间未开播')
else:
key = self.get_js()
real_url = {}
real_url["flv"] = "http://vplay1a.douyucdn.cn/live/{}.flv?uuid=".format(key)
real_url["x-p2p"] = "http://tx2play1.douyucdn.cn/live/{}.xs?uuid=".format(key)
return real_url
try:
data = self.get_js()
real_url["m3u8"] = data["data"]["url"]
except:
pass
return json.dumps(real_url, indent=2, ensure_ascii=False)

if __name__ == '__main__':
r = input('输入斗鱼直播间号:\n')
s = DouYu(r)
s.did = s.get_did()
print(s.get_real_url())

75 changes: 0 additions & 75 deletions huomao.py

This file was deleted.

109 changes: 73 additions & 36 deletions huya.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,67 @@
# 获取虎牙直播的真实流媒体地址。

import json
import requests
import re
import base64
import urllib.parse
import hashlib
import time


def live(e):
i, b = e.split('?')
r = i.split('/')
s = re.sub(r'.(flv|m3u8)', '', r[-1])
c = b.split('&', 3)
c = [i for i in c if i != '']
n = {i.split('=')[0]: i.split('=')[1] for i in c}
fm = urllib.parse.unquote(n['fm'])
u = base64.b64decode(fm).decode('utf-8')
p = u.split('_')[0]
f = str(int(time.time() * 1e7))
l = n['wsTime']
t = '0'
h = '_'.join([p, t, s, f, l])
m = hashlib.md5(h.encode('utf-8')).hexdigest()
y = c[-1]
url = "{}?wsSecret={}&wsTime={}&u={}&seqid={}&{}".format(i, m, l, t, f, y)
return url
from urllib.parse import parse_qs, urlencode
from datetime import datetime
import random


def live(info):
stream_info = dict({'flv': {}, 'hls': {}})
cdn_type = dict({'AL': '阿里', 'TX': '腾讯', 'HW': '华为', 'HS': '火山', 'WS': '网宿'})
uid = get_anonymous_uid()
for s in info["roomInfo"]["tLiveInfo"]["tLiveStreamInfo"]["vStreamInfo"]["value"]:
if s["sFlvUrl"]:
stream_info["flv"][cdn_type[s["sCdnType"]]] = "{}/{}.{}?{}".format(s["sFlvUrl"], s["sStreamName"],
s["sFlvUrlSuffix"],
process_anticode(s["sFlvAntiCode"], uid,
s["sStreamName"]))
if s["sHlsUrl"]:
stream_info["hls"][cdn_type[s["sCdnType"]]] = "{}/{}.{}?{}".format(s["sHlsUrl"], s["sStreamName"],
s["sHlsUrlSuffix"],
process_anticode(s["sHlsAntiCode"], uid,
s["sStreamName"]))
return stream_info


def process_anticode(anticode, uid, streamname):
q = dict(parse_qs(anticode))
q["ver"] = ["1"]
q["sv"] = ["2110211124"]
q["seqid"] = [str(int(uid) + int(datetime.now().timestamp() * 1000))]
q["uid"] = [str(uid)]
q["uuid"] = [str(get_uuid())]
ss = hashlib.md5("{}|{}|{}".format(q["seqid"][0], q["ctype"][0], q["t"][0]).encode("UTF-8")).hexdigest()
q["fm"][0] = base64.b64decode(q["fm"][0]).decode('utf-8').replace("$0", q["uid"][0]).replace("$1",
streamname).replace(
"$2", ss).replace("$3", q["wsTime"][0])
q["wsSecret"][0] = hashlib.md5(q["fm"][0].encode("UTF-8")).hexdigest()
del q["fm"]
if "txyp" in q:
del q["txyp"]
return urlencode({x: y[0] for x, y in q.items()})


def get_anonymous_uid():
url = "https://udblgn.huya.com/web/anonymousLogin"
resp = requests.post(url, json={
"appId": 5002,
"byPass": 3,
"context": "",
"version": "2.4",
"data": {}
})
return resp.json()["data"]["uid"]


def get_uuid():
# Number((Date.now() % 1e10 * 1e3 + (1e3 * Math.random() | 0)) % 4294967295))
now = datetime.now().timestamp() * 1000
rand = random.randint(0, 1000) | 0
return int((now % 10000000000 * 1000 + rand) % 4294967295)


def get_real_url(room_id):
Expand All @@ -37,22 +73,23 @@ def get_real_url(room_id):
'Chrome/75.0.3770.100 Mobile Safari/537.36 '
}
response = requests.get(url=room_url, headers=header).text
liveLineUrl = re.findall(r'"liveLineUrl":"([\s\S]*?)",', response)[0]
liveline = base64.b64decode(liveLineUrl).decode('utf-8')
if liveline:
if 'replay' in liveline:
return '直播录像:' + liveline
else:
liveline = live(liveline)
real_url = ("https:" + liveline).replace("hls", "flv").replace("m3u8", "flv")
room_info_str = re.findall(r'\<script\> window.HNF_GLOBAL_INIT = (.*) \</script\>', response)[0]
room_info = json.loads(room_info_str)
if room_info["roomInfo"]["eLiveStatus"] == 2:
print('该直播间源地址为:')
real_url = json.dumps(live(room_info), indent=2, ensure_ascii=False)
elif room_info["roomInfo"]["eLiveStatus"] == 3:
print('该直播间正在回放历史直播,低清晰度源地址为:')
real_url = "https:{}".format(base64.b64decode(room_info["roomProfile"]["liveLineUrl"]).decode('utf-8'))
else:
real_url = '未开播或直播间不存在'
except:
real_url = '未开播或直播间不存在'
real_url = '未开播'

except Exception as e:
print(e)
real_url = '直播间不存在'
return real_url


rid = input('输入虎牙直播房间号:\n')
real_url = get_real_url(rid)
print('该直播间源地址为:')
print(real_url)
print(real_url)
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ requests==2.26.0
six==1.15.0
typing-extensions==3.7.4.3
urllib3==1.26.5
yarl==1.5.1
yarl==1.8.2