1
0
mirror of https://github.com/wbt5/real-url.git synced 2025-07-28 12:15:52 +08:00

Compare commits

...

13 Commits

Author SHA1 Message Date
乌帮图
f24c64ca4b
Merge pull request #48 from BlancRay/master
修复虎牙直播录像地址
2020-07-18 15:40:24 +08:00
wbt5
b06ec4ca96 新增战旗直播弹幕 2020-07-18 15:04:06 +08:00
wbt5
0f40b42d76 新增搜狐千帆直播弹幕 2020-07-18 15:03:47 +08:00
wbt5
fe41cd305d 新增pps奇秀直播弹幕 2020-07-18 15:03:21 +08:00
wbt5
a36b9aae75 新增龙珠直播弹幕 2020-07-18 15:02:54 +08:00
wbt5
7ad608a279 新增酷狗直播弹幕 2020-07-18 15:02:24 +08:00
wbt5
071a83cd3a 新增酷狗直播弹幕 2020-07-18 15:02:13 +08:00
wbt5
155c47a67a 新增酷狗直播弹幕 2020-07-18 15:02:07 +08:00
wbt5
3312118315 新增5个平台弹幕功能 2020-07-18 14:58:18 +08:00
wbt5
aad15f17b1 新增5个平台弹幕功能 2020-07-18 14:54:57 +08:00
wbt5
022929fef3 新增弹幕功能 2020-07-18 14:53:58 +08:00
wbt5
0235aa6f77 更新映客弹幕 2020-07-17 16:25:04 +08:00
Blanc Ray
9a3fdbbddc
修复虎牙直播录像地址
虎牙直播录像地址缺少https
2020-07-17 10:38:20 +08:00
12 changed files with 2801 additions and 19 deletions

View File

@ -8,7 +8,7 @@
**26** 个直播平台的直播源获取:斗鱼直播、虎牙直播、哔哩哔哩直播、战旗直播、网易 CC 直播、火猫直播、企鹅电竞、YY 直播、一直播、快手直播、花椒直播、映客直播、西瓜直播、触手直播、NOW 直播、抖音直播爱奇艺直播、酷狗直播、龙珠直播、PPS 奇秀直播、六间房、17 直播、来疯直播、优酷轮播台、网易 look 直播、千帆直播。
**9** 个直播平台的弹幕获取斗鱼直播、虎牙直播、哔哩哔哩直播、快手直播、火猫直播、企鹅电竞、花椒直播、映客直播、网易CC直播。
**14** 个直播平台的弹幕获取斗鱼直播、虎牙直播、哔哩哔哩直播、快手直播、火猫直播、企鹅电竞、花椒直播、映客直播、网易CC直播、酷狗直播、龙珠直播、PPS奇秀、搜狐千帆、战旗直播。
## 运行
@ -23,7 +23,9 @@
## 更新
### 2020.07.11新增网易CC直播弹幕获取
### 2020.07.18新增酷狗、龙珠、PPS奇秀、搜狐千帆、战旗直播等5个平台的弹幕获取
2020.07.11新增网易CC直播弹幕获取
2020.07.05:新增花椒直播、映客直播弹幕获取;更新虎牙直播源

View File

@ -11,6 +11,11 @@ from .egame import eGame
from .huajiao import HuaJiao
from .inke import Inke
from .cc import CC
from .kugou import KuGou
from .zhanqi import ZhanQi
from .longzhu import LongZhu
from .pps import QiXiu
from .qf import QF
__all__ = ['DanmakuClient']
@ -36,7 +41,12 @@ class DanmakuClient:
'egame.qq.com': eGame,
'huajiao.com': HuaJiao,
'inke.cn': Inke,
'cc.163.com': CC}.items():
'cc.163.com': CC,
'fanxing.kugou.com': KuGou,
'zhanqi.tv': ZhanQi,
'longzhu.com': LongZhu,
'pps.tv': QiXiu,
'qf.56.com': QF}.items():
if re.match(r'^(?:http[s]?://)?.*?%s/(.+?)$' % u, url):
self.__site = s
self.__u = u
@ -49,14 +59,21 @@ class DanmakuClient:
async def init_ws(self):
ws_url, reg_datas = await self.__site.get_ws_info(self.__url)
self.__ws = await self.__hs.ws_connect(ws_url)
for reg_data in reg_datas:
await self.__ws.send_bytes(reg_data)
if reg_datas:
for reg_data in reg_datas:
if self.__u == 'qf.56.com':
await self.__ws.send_str(reg_data)
else:
await self.__ws.send_bytes(reg_data)
async def heartbeats(self):
while not self.__stop:
while not self.__stop and self.__site.heartbeat:
await asyncio.sleep(self.__site.heartbeatInterval)
try:
await self.__ws.send_bytes(self.__site.heartbeat)
if self.__u == 'qf.56.com':
await self.__ws.send_str(self.__site.heartbeat)
else:
await self.__ws.send_bytes(self.__site.heartbeat)
except:
pass
@ -70,7 +87,7 @@ class DanmakuClient:
await asyncio.sleep(1)
await self.init_ws()
await asyncio.sleep(1)
async def init_ws_huajiao(self):
rid = re.search(r'\d+', self.__url).group(0)
s = self.__site(rid)
@ -88,17 +105,10 @@ class DanmakuClient:
await self.__dm_queue.put(m)
count += 1
await self.heartbeats()
async def init_ws_inke(self):
ws_url = await self.__site.get_ws_info(self.__url)
self.__ws = await self.__hs.ws_connect(ws_url)
await self.fetch_danmaku()
async def start(self):
if self.__u == 'huajiao.com':
await self.init_ws_huajiao()
elif self.__u == 'inke.cn':
await self.init_ws_inke()
else:
await self.init_ws()
await asyncio.gather(

View File

@ -5,6 +5,7 @@ import json
class Inke:
heartbeat = None
@staticmethod
async def get_ws_info(url):
@ -16,7 +17,7 @@ class Inke:
async with session.get(cr) as resp:
res = await resp.text()
wss_url = json.loads(res).get('url')
return wss_url
return wss_url, None
@staticmethod
def decode_msg(data):

250
danmu/danmaku/kugou.proto Normal file
View File

@ -0,0 +1,250 @@
syntax = "proto2";
package KuGouPack;
message LoginRequest {
optional int32 cmd = 1;
optional int32 roomid = 2;
optional int64 kugouid = 3;
optional string token = 4;
optional string key = 5;
optional int32 appid = 6;
optional int32 platid = 7;
optional int32 subplatid = 8;
optional string version = 9;
optional string deviceNo = 10;
optional string imei = 11;
optional int32 v = 12;
optional int32 referer = 13;
optional int32 clientid = 14;
optional string soctoken = 15;
optional string offset = 16;
optional int32 appChannel = 17;
optional string sid = 18;
optional int32 source = 19;
optional string uuid = 20;
optional string systemVersion = 21;
optional string entryid = 22;
optional string socsid = 23;
optional string deviceid = 24;
}
message LoginResponse {
optional string nickname = 1;
optional int32 richlevel = 2;
optional int64 userid = 3;
optional int64 kugouid = 4;
optional int32 fanstags = 5;
optional int32 v = 6;
optional int32 referer = 7;
optional string wellcomes = 8;
optional string img = 9;
}
message ErrorResponse {
optional int32 cmd = 1;
optional int32 type = 2;
optional int64 seq = 3;
optional int32 status = 4;
optional int32 errorno = 5;
optional string msg = 6;
optional string socsid = 7;
}
message ChatResponse {
optional string chatmsg = 1;
optional int64 senderid = 2;
optional int64 senderkugouid = 3;
optional string sendername = 4;
optional int32 senderrichlevel = 5;
optional int64 receiverid = 6;
optional int64 receiverkugouid = 7;
optional string receivername = 8;
optional int32 receiverrichlevel = 9;
optional int32 issecrect = 10;
optional AdditionalInfo additionalInfo = 11;
optional int32 v = 12;
optional int64 seq = 13;
optional int32 isa = 14;
optional int32 rlight = 15;
optional int32 rdiffExp = 16;
optional int32 rsvip = 17;
optional int32 rsvipl = 18;
optional string mac = 19;
optional Complain complain = 20;
}
message AdditionalInfo {
optional int32 fanstags = 1;
}
message Complain {
optional string msg = 1;
optional string url = 2;
}
message Message {
optional string offset = 1;
optional int32 ack = 2;
optional int32 rpt = 3;
optional string msgId = 4;
optional MCompression compression = 5;
optional MCodec codec = 6;
optional bytes content = 7;
}
message ContentMessage {
optional int32 cmd = 1;
optional bytes content = 2;
optional int32 roomid = 3;
optional int64 receiverid = 4;
optional int64 receiverkugouid = 5;
optional int64 senderid = 6;
optional int64 sendkugouid = 7;
optional int32 appId = 8;
optional int64 gid = 9;
optional int32 rpt = 10;
optional int64 time = 11;
optional int64 plev = 12;
optional int64 pvalue = 13;
optional bytes ext = 14;
optional Sinfo sinfo = 15;
optional MCodec codec = 16;
optional Risk risk = 17;
}
message Risk {
optional string m = 1;
optional string l = 2;
optional int32 t = 3;
}
message Sinfo {
optional int32 light = 1;
optional int32 de = 2;
optional int32 svip = 3;
optional int32 svipl = 4;
optional int32 ck = 5;
optional string ckname = 6;
optional string skname = 7;
optional string ckid = 8;
optional string ckimg = 9;
optional string logo = 10;
optional int32 sex = 11;
optional int32 bt = 12;
}
enum MCompression {
M_NONE = 0;
M_GZIP = 1;
M_LZ4 = 2;
M_SNAPPY = 3;
M_ZSTD = 4;
}
enum MCodec {
M_JSON = 0;
M_PROTOBUF = 1;
}
message Extension {
optional int32 ui = 1;
optional int32 isSpRoom = 2;
optional StliVo stli = 3;
optional VipDataVo vipData = 4;
optional UsingMountVo usingMount = 5;
optional UsingMedalVo usingMedal = 6;
optional HonorMedalVo honorMedal = 7;
optional UserGuardVo userGuard = 8;
optional LittleGuardVo littleGuard = 9;
optional WoreUserPlateVo defaultPlate = 10;
optional string plateName = 11;
optional int32 starCard = 12;
optional int32 external = 13;
optional string exMemo = 14;
optional bool p = 15;
optional int32 worship = 16;
optional BubbleVo bubble = 17;
optional int32 z = 18;
optional int32 isGoldFans = 19;
optional string token = 20;
optional int64 kugouId = 21;
optional StarFollowerVo starFollower = 22;
optional int32 v_tme = 23;
optional int32 v_kg = 24;
optional string ar = 25;
optional int32 isAndroid = 26;
optional int32 clientPlat = 27;
optional int32 blackCard = 28;
optional int32 v_l = 29;
optional BossGroupVo bossGroup = 30;
optional CeremonyVo ceremony = 31;
optional int32 referer = 32;
optional int32 isNew = 33;
}
message StliVo {
optional int32 st = 1;
optional int32 sl = 2;
optional int32 isAdmin = 3;
}
message VipDataVo {
optional int32 v = 1;
optional string c = 2;
optional int32 vl = 3;
}
message UsingMountVo {
optional string id = 1;
optional string n = 2;
optional string swf = 3;
optional string bi = 4;
optional string si = 5;
optional string p = 6;
optional int32 s = 7;
}
message UsingMedalVo {
optional string medalList = 1;
}
message HonorMedalVo {
optional string honorList = 1;
}
message UserGuardVo {
optional string g = 1;
optional string i = 2;
}
message LittleGuardVo {
optional int32 l = 1;
optional int32 g = 2;
}
message WoreUserPlateVo {
optional int64 kid = 1;
optional string plateName = 2;
optional int32 type = 3;
optional int32 l = 4;
optional int32 i = 5;
}
message BubbleVo {
optional int32 id = 1;
optional string bg = 2;
}
message StarFollowerVo {
optional int32 l = 1;
}
message BossGroupVo {
optional int64 gid = 1;
optional string gn = 2;
optional int32 gr = 3;
}
message CeremonyVo {
optional int32 pl = 1;
}

229
danmu/danmaku/kugou.py Normal file
View File

@ -0,0 +1,229 @@
from . import kugou_pb2 as pb
import struct
import requests
class InitKugou:
def __init__(self):
self.MAGIC = {
'index': 0,
'length': 1,
'value': 100
}
self.VERSION = {
'index': 1,
'length': 2,
'value': 1
}
self.TYPE = {
'index': 2,
'length': 1,
'value': 1
}
self.HEADER = {
'index': 3,
'length': 2,
'value': 12
}
self.CMD = {
'index': 4,
'length': 4,
'value': 0
}
self.PAYLOAD = {
'index': 5,
'length': 4,
'value': 0
}
self.ATTR = {
'index': 6,
'length': 1,
'value': 0
}
self.CRC = {
'index': 7,
'length': 2,
'value': 0
}
self.SKIP = {
'index': 8,
'length': 1,
'value': 0
}
self.f = [self.MAGIC, self.VERSION, self.TYPE, self.HEADER,
self.CMD, self.PAYLOAD, self.ATTR, self.CRC, self.SKIP]
def reg(self, rid):
url = 'https://fx2.service.kugou.com/socket_scheduler/pc/v2/address.jsonp'
payload = {
'rid': rid,
'_v': '7.0.0',
'_p': 0,
'pv': 20191231,
'at': 102,
'cid': 105
}
with requests.Session() as s:
r = s.get(url, params=payload).json()
soctoken = r['data']['soctoken']
reg_data = {
'appid': 1010,
'clientid': 105,
'cmd': 201,
'deviceNo': '4edc0e89-ccaf-452c-bce4-00f4cb6bb5bb',
'kugouid': 0,
'platid': 18,
'referer': 0,
'roomid': rid,
'sid': '8b9b79a7-a742-4397-fcc0-94efa3a1c920',
'soctoken': soctoken,
'v': 20191231
}
a = pb.LoginRequest()
for k, v in reg_data.items():
setattr(a, k, v)
b = pb.Message()
b.content = a.SerializeToString()
e = b.SerializeToString()
reg = self.encode_(e, reg_data['cmd'])
return reg
def g(self, *e):
if len(e) > 1 and e[1]:
t = e[1]
else:
t = 12
n = 0
i = 0
e = e[0]
while i < e and i < len(self.f):
n += self.f[i]['length']
i += 1
if e == len(self.f):
return n + t - 12
else:
return n
def encode_(self, e, t):
n = len(self.f)
i = len(e)
# r = self.g(n) + i
self.PAYLOAD['value'] = i
self.CMD['value'] = t
buf = b''
for s in self.f:
# offset = self.g(s['index'])
value = s['value']
if s['length'] == 1:
fmt = '!b'
elif s['length'] == 2:
fmt = '!h'
else:
fmt = '!i'
buf += struct.pack(fmt, value)
buf += struct.pack('!i', i)
buf = buf[:self.g(n)] + e
return buf
def v(self, e, t):
if t['length'] == 1:
fmt = '!b'
elif t['length'] == 2:
fmt = '!h'
else:
fmt = '!i'
r, = struct.unpack_from(fmt, e, self.g(t['index']))
return r
# def k(self, e, i, o=False):
# if i == 1:
# a = zlib.decompress(e)
# elif i == 2:
# a = zlib.decompress(e)
# else:
# a = e
# if o:
# return self.r(a)
# else:
# return a
#
# def r(self, e):
# pass
def decode_(self, message):
t = len(message)
n = len(self.f)
if t <= 0:
return {}
if self.v(message, self.TYPE) == 0:
return {}
r = self.v(message, self.HEADER)
cmd = self.v(message, self.CMD) # cmd
a = self.g(n, r)
if t < a:
return {}
o = message[a:] # payloadBuffer
if not o or not cmd:
return
msgs = []
msg = {'name': '', 'content': '', 'msg_type': 'other'}
if cmd == 201 or cmd == 501:
# CMD
# 201:LoginResponse,欢迎信息;
# 501:ChatResponse,聊天信息;
# 602:ContentMessage,礼物信息;
# 901:ErrorResponse;
s = pb.Message()
s.ParseFromString(o)
if s.codec == 1:
# if s.compression:
# s.content = self.k(s.content, s.compression)
s1 = pb.ContentMessage()
s1.ParseFromString(s.content)
if s1.codec == 1:
# if hasattr(s1, 'compression'):
# s1.content = self.k(s1.content, s1.compression)
s2 = pb.ChatResponse()
s2.ParseFromString(s1.content)
if cmd == 201:
msg['name'] = 'SYS'
msg['content'] = s2.receivername.replace('%nick', s2.chatmsg)
msg['msg_type'] = 'danmaku'
elif cmd == 501:
msg['name'] = s2.sendername
msg['content'] = s2.chatmsg
msg['msg_type'] = 'danmaku'
msgs.append(msg.copy())
return msgs
class KuGou:
heartbeat = b'\x64\x00\x01\x00'
wss_url = 'wss://chat1wss.kugou.com/acksocket'
heartbeatInterval = 10
s = InitKugou()
@staticmethod
async def get_ws_info(url):
rid = url.split('/')[-1]
reg_data = KuGou.s.reg(int(rid))
return KuGou.wss_url, [reg_data]
@staticmethod
def decode_msg(data):
msgs = KuGou.s.decode_(data)
return msgs

2047
danmu/danmaku/kugou_pb2.py Normal file

File diff suppressed because one or more lines are too long

37
danmu/danmaku/longzhu.py Normal file
View File

@ -0,0 +1,37 @@
import json
import aiohttp
import re
class LongZhu:
heartbeat = None
@staticmethod
async def get_ws_info(url):
rid = url.split('/')[-1]
async with aiohttp.ClientSession() as session:
async with session.get('http://m.longzhu.com/' + rid) as resp:
res1 = await resp.text()
roomid = re.search(r'var roomId = (\d+);', res1).group(1)
async with session.get('http://idc-gw.longzhu.com/mbidc?roomId=' + roomid) as resp2:
res2 = json.loads(await resp2.text())
ws_url = res2['data']['redirect_to'] + '?room_id=' + roomid
return ws_url, None
@staticmethod
def decode_msg(message):
msgs = []
msg = {'name': '', 'content': '', 'msg_type': 'other'}
message = json.loads(message)
type_ = message['type']
# type_ == 'gift' 礼物
if type_ == 'chat':
msg['name'] = message['msg']['user']['username']
msg['content'] = (message['msg']['content']).strip()
msg['msg_type'] = 'danmaku'
elif type_ == 'commonjoin':
msg['name'] = message['msg']['user']['username']
msg['content'] = message['msg']['userMessage']
msg['msg_type'] = 'danmaku'
msgs.append(msg.copy())
return msgs

73
danmu/danmaku/pps.py Normal file
View File

@ -0,0 +1,73 @@
import hashlib
import urllib.parse
import json
class QiXiu:
heartbeat = None
@staticmethod
async def get_ws_info(url):
rid = url.split('/')[-1]
s = bytes([57, 77, 83, 73, 53, 86, 85, 71, 50, 81, 74, 80, 66, 52, 78, 54, 68, 48, 81,
83, 89, 87, 69, 72, 67, 90, 83, 75, 84, 49, 77, 50, 84, 65, 75, 88]).decode('utf-8')
# ua = 'User-Agent'
# ak = deviceid = md5(str(int(time.time() * 1e3)) + ua + '0000')
ak = deviceid = '118d2ae703e62992263e6741afbb5627'
e = {
'ag': 1,
'ak': ak,
'at': 3,
'd': deviceid,
'n': 1,
'p': 1,
'r': rid,
'v': '1.01.0801'
}
i = ''
for k, v in e.items():
i += '{}={}|'.format(k, str(v))
e['sg'] = hashlib.md5((i + s).encode('utf-8')).hexdigest()
ws_url = 'ws://qx-ws.iqiyi.com/ws?' + urllib.parse.urlencode(e)
return ws_url, None
@staticmethod
def decode_msg(data):
message = json.loads(data)
msgs = []
msg = {'name': '', 'content': '', 'msg_type': 'other'}
for ms in message:
m = ms['ct']
type_ = ms['t']
# 200001进场消息
# 300001聊天信息
# 102001礼物
# 1100002礼物
# 400001人气值
# 5000010升级
# 700095live_score
# 700091排名
# 其他:系统消息
if type_ == 300001:
msg['name'] = m['op_userInfo']['nick_name']
msg['content'] = m['msg']
msg['msg_type'] = 'danmaku'
elif type_ == 102001:
msg['name'] = m['op_userInfo']['nick_name']
num = m['op_info']['num']
gift = m['op_info']['name']
msg['content'] = '送出{}{}'.format(num, gift)
msg['msg_type'] = 'danmaku'
elif type_ in [200001, 1100002, 110001, 3019, 3022, 3002, 3024]:
msg['name'] = 'SYS'
info = m['op_info'].get('public_chat_msg', 0)
if not info:
info = m['op_info']['roll_chat_msg']
content = ''
items = info['items']
for item in items:
content += item.get('content', '')
msg['content'] = content
msg['msg_type'] = 'danmaku'
msgs.append(msg.copy())
return msgs

65
danmu/danmaku/qf.py Normal file
View File

@ -0,0 +1,65 @@
import aiohttp
import json
import time
class QF:
heartbeat = '2::'
heartbeatInterval = 30
@staticmethod
async def get_ws_info(url):
rid = url.split('/')[-1]
async with aiohttp.ClientSession() as session:
async with session.get('https://conn-chat.qf.56.com/socket.io/1/') as resp:
res = await resp.text()
sessid = res.split(':')[0]
ws_url = 'wss://conn-chat.qf.56.com/socket.io/1/websocket/' + sessid
# e = 2
t = 'connector-sio.entryHandler.enter'
s = {
'userId': '',
'aq': 0,
'roomId': rid,
'token': '',
'ip': '',
'recet': 0,
'params': {
'referFrom': '0'
},
'apType': 0,
'timestamp': int(time.time() * 1e3)
}
r = json.dumps(s, separators=(',', ':'))
if len(t) > 255:
raise Exception('route maxlength is overflow')
reg_data = '3:::' + '\x00\x00\x00\x02 ' + t + r
return ws_url, [reg_data]
@staticmethod
def decode_msg(message):
msgs = []
msg = {'name': '', 'content': '', 'msg_type': 'other'}
type_ = message[0]
if type_ == '3':
data = json.loads(message[4:])
route = data.get('route', 0)
body = data['body']
if route == 'onUserLog': # 入场信息
msg['name'] = 'SYS'
msg['content'] = body['userName'] + ' 来了'
msg['msg_type'] = 'danmaku'
elif route == 'onChat': # 弹幕
msg['name'] = body['userName']
msg['content'] = body['content']
msg['msg_type'] = 'danmaku'
elif route == 'onGift': # 弹幕
msg['name'] = 'SYS'
msg['content'] = body['userName'] + ' 送礼物 ' + body['giftName']
msg['msg_type'] = 'danmaku'
elif route == 'onBc': # 弹幕
msg['name'] = 'SYS'
msg['content'] = body['userName'] + '' + body['msg']
msg['msg_type'] = 'danmaku'
msgs.append(msg.copy())
return msgs

63
danmu/danmaku/zhanqi.py Normal file
View File

@ -0,0 +1,63 @@
import json
import struct
import aiohttp
class ZhanQi:
heartbeat = b'\xbb\xcc\x00\x00\x00\x00\x15\x00\x00\x00\x10\'{"cmdid": "keeplive"}'
wss_url = 'wss://gw.zhanqi.tv/'
heartbeatInterval = 30
@staticmethod
async def get_ws_info(url):
reg_datas = []
rid = url.split('/')[-1]
async with aiohttp.ClientSession() as session:
async with session.get('https://m.zhanqi.tv/api/static/v2.1/room/domain/{}.json'.format(rid)) as resp:
info = json.loads(await resp.text())
roomid = info['data']['id']
async with session.get('https://m.zhanqi.tv/api/public/room.viewer') as resp2:
res = json.loads(await resp2.text())
gid = res['data']['gid']
sid = res['data']['sid']
timestamp = res['data']['timestamp']
login = {
'cmdid': 'loginreq',
'roomid': int(roomid),
'chatroomid': 0,
'gid': gid,
'sid': sid,
't': 0,
'r': 0,
'device': 1,
'fhost': 'mzhanqi',
'uid': 0,
'timestamp': timestamp
}
body = json.dumps(login, separators=(',', ':'))
head = struct.pack('<HIIH', 0xCCBB, 0, len(body), 10000)
reg_data = head + body.encode()
reg_datas.append(reg_data)
return ZhanQi.wss_url, reg_datas
@staticmethod
def decode_msg(message):
message = (message[12:])
data = json.loads(message)
msgs = []
msg = {'name': '', 'content': '', 'msg_type': 'other'}
if data['cmdid'] == 'chatmessage': # 聊天信息
msg['name'] = data['fromname']
msg['content'] = data['content']
msg['msg_type'] = 'danmaku'
elif data['cmdid'] == 'Gift.Display': # 礼物信息
pass
elif data['cmdid'] == 'Prop.Display': # 礼物信息
pass
elif data['cmdid'] == 'getuc': # 人气数
pass
elif data['cmdid'] == 'loginresp': # 欢迎信息
pass
msgs.append(msg.copy())
return msgs

View File

@ -21,7 +21,7 @@ async def main(url):
a = input('请输入直播间地址:\n')
asyncio.run(main(a))
asyncio.run(main())
# 虎牙https://www.huya.com/11352915
# 斗鱼https://www.douyu.com/85894
@ -32,3 +32,8 @@ asyncio.run(main(a))
# 花椒直播https://www.huajiao.com/l/303344861?qd=hu
# 映客直播https://www.inke.cn/liveroom/index.html?uid=87493223&id=1593906372018299
# CC直播https://cc.163.com/363936598/
# 酷狗直播https://fanxing.kugou.com/1676290
# 战旗直播
# 龙珠直播http://star.longzhu.com/wsde135864219
# PPS奇秀直播https://x.pps.tv/room/208337
# 搜狐千帆直播https://qf.56.com/520208a

View File

@ -42,7 +42,7 @@ def get_real_url(room_id):
liveLineUrl = re.findall(r'liveLineUrl = "([\s\S]*?)";', response)[0]
if liveLineUrl:
if 'replay' in liveLineUrl:
return '直播录像:' + liveLineUrl
return '直播录像:https:' + liveLineUrl
else:
liveLineUrl = live(liveLineUrl)
real_url = ["https:" + liveLineUrl, "https:" + re.sub(r'_\d{4}.m3u8', '.m3u8', liveLineUrl)]
@ -56,4 +56,4 @@ def get_real_url(room_id):
rid = input('请输入虎牙房间号:\n')
real_url = get_real_url(rid)
print('该直播间源地址为:')
print(real_url)
print(real_url)