1
0
mirror of https://github.com/wbt5/real-url.git synced 2025-08-01 06:28:02 +08:00

新增网易CC直播弹幕

This commit is contained in:
wbt5 2020-07-11 10:39:39 +08:00
parent 656ddecd96
commit afcd4d3be8
4 changed files with 326 additions and 3 deletions

View File

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

View File

@ -10,6 +10,7 @@ from .huomao import HuoMao
from .egame import eGame from .egame import eGame
from .huajiao import HuaJiao from .huajiao import HuaJiao
from .inke import Inke from .inke import Inke
from .cc import CC
__all__ = ['DanmakuClient'] __all__ = ['DanmakuClient']
@ -34,7 +35,8 @@ class DanmakuClient:
'kuaishou.com': KuaiShou, 'kuaishou.com': KuaiShou,
'egame.qq.com': eGame, 'egame.qq.com': eGame,
'huajiao.com': HuaJiao, 'huajiao.com': HuaJiao,
'inke.cn': Inke}.items(): 'inke.cn': Inke,
'cc.163.com': CC}.items():
if re.match(r'^(?:http[s]?://)?.*?%s/(.+?)$' % u, url): if re.match(r'^(?:http[s]?://)?.*?%s/(.+?)$' % u, url):
self.__site = s self.__site = s
self.__u = u self.__u = u

318
danmu/danmaku/cc.py Normal file
View File

@ -0,0 +1,318 @@
import aiohttp
import time
import uuid
import struct
import math
import zlib
import json
import re
class CC_Init:
def __init__(self):
self.offset = 0
def get_reg(self):
sid = 6144
cid = 2
update_req_info = {
'22': 640,
'23': 360,
'24': "web",
'25': "Linux",
'29': "163_cc",
'30': "",
'31': "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Mobile Safari/537.36"
}
macAdd = device_token = str(uuid.uuid1()) + '@web.cc.163.com'
data = {
'web-cc': int(time.time() * 1e3),
'macAdd': macAdd,
'device_token': device_token,
'page_uuid': str(uuid.uuid1()),
'update_req_info': update_req_info,
'system': 'win',
'memory': 1,
'version': 1,
'webccType': 4253
}
reg_data = struct.pack('<HHI', sid, cid, 0) + self.encode_dict(data)
return reg_data
def get_beat(self):
sid = 6144
cid = 5
data = {}
beat_data = struct.pack('<HHI', sid, cid, 0) + self.encode_dict(data)
return beat_data
def get_join(self, data_cid, data_gametype, data_roomId):
sid = 512
cid = 1
data = {
'cid': data_cid,
'gametype': data_gametype,
'roomId': data_roomId
}
join_data = struct.pack('<HHI', sid, cid, 0) + self.encode_dict(data)
return join_data
def encode_str(self, r):
n = len(r)
i = 5 + 3 * n
s = f = 1 if n < 32 else 2 if n <= 255 else 3 if n <= 65535 else 5
b = 160 + n if s == 1 else 215 + s if s <= 3 else 219
if f == 1:
e = bytes([b])
else:
e = bytes([b, n])
return e + r.encode()
def encode_num(self, e):
if e <= 255:
return struct.pack('!B', e)
if 255 < e <= 65535:
t = struct.pack('!H', e)
return b'\xcd' + t
else:
t = []
r = 9
n = 0
i = 52
o = 8
s = 8 * o - i - 1
c = (1 << s) - 1
h = c >> 1
l = pow(2, -24) - pow(2, -77) if i == 23 else 0
d = 0 if n else o - 1
p = 1 if n else -1
y = 1 if (e < 0 or e == 0 and 1 / e) else 0
while i >= 8:
e = abs(e)
f = math.floor(math.log(e) / math.log(2))
u = pow(2, -1 * f)
if e * u < 1:
f -= 1
u *= 2
if f + h >= 1:
e += l / u
else:
e += l * pow(2, 1 - h)
if e * u >= 2:
f += 1
u /= 2
if f + h >= c:
a = 0
f = c
elif f + h >= 1:
a = (e * u - 1) * pow(2, i)
f += h
else:
a = e * pow(2, h - 1) * pow(2, i)
f = 0
t.append(255 & int(a))
d += p
a /= 256
i -= 8
f = f << i | int(a)
s += i
while s > 0:
t.append(255 & int(f))
d += p
f /= 256
s -= 8
t[-1] |= 128 * y
t.reverse()
return b'\xcb' + bytes(t)
def encode_dict(self, d):
n = len(d)
r = 128 + n if n < 16 else 222 if n <= 65535 else 223
t = bytes([r])
for k, v in d.items():
t += self.encode_str(k)
if isinstance(v, int):
t += self.encode_num(v)
elif isinstance(v, str):
t += self.encode_str(v)
elif isinstance(v, dict):
t += self.encode_dict(v)
return t
def p(self, fmt):
def r(t):
s, = struct.unpack_from(fmt, t, self.offset)
self.offset += struct.calcsize(fmt)
return s
return r
def i(self, t):
return lambda t: int(t[self.offset - 1])
def o(self, t, e):
return lambda r: e(r, t(r))
def f(self, t, e):
return lambda r: e(r, t)
def n(self, e):
if 0 <= e <= 127:
r = self.i(e)
elif 128 <= e <= 143:
r = self.f(e - 128, self.de_dict)
elif 144 <= e <= 159:
r = self.f(e - 144, self.de_list)
elif 160 <= e <= 191:
r = self.f(e - 160, self.de_str)
elif e == 192:
r = self.i(None)
elif e == 193:
r = None
elif e == 194:
r = self.i(False)
elif e == 195:
r = self.i(True)
elif e == 202:
r = self.p('>f')
elif e == 203:
r = self.p('>d')
elif e == 204:
r = self.p('>B')
elif e == 205:
r = self.p('>H')
elif e == 206:
r = self.p('>I')
elif e == 207:
r = self.p('>Q')
elif e == 208:
r = self.p('>b')
elif e == 209:
r = self.p('>h')
elif e == 210:
r = self.p('>i')
elif e == 211:
r = self.p('>q')
elif e == 217:
r = self.o(self.p('>B'), self.de_str)
elif e == 218:
r = self.o(self.p('>H'), self.de_str)
elif e == 219:
r = self.o(self.p('>I'), self.de_str)
elif e == 220:
r = self.o(self.p('>H'), self.de_list)
elif e == 221:
r = self.o(self.p('>I'), self.de_list)
elif e == 222:
r = self.o(self.p('>H'), self.de_dict)
elif e == 223:
r = self.o(self.p('>I'), self.de_dict)
elif 224 <= e <= 256:
r = self.i(e - 256)
return r
def de_init(self, t):
r = int(t[self.offset])
self.offset += 1
n = self.n(r)
return n(t)
def de_str(self, t, e):
s = t[self.offset: self.offset + e].decode('utf-8')
self.offset += e
return s
def de_list(self, t, e):
l = [''] * e
n = self.de_init
for i in range(e):
l[i] = n(t)
return l
def de_dict(self, t, e):
k = [''] * e
v = [''] * e
f = self.de_init
for r in range(e):
k[r] = f(t)
v[r] = f(t)
d = dict(zip(k, v))
return d
class CC:
s = CC_Init()
heartbeatInterval = 30
heartbeats = s.get_beat()
@staticmethod
async def get_ws_info(url):
cid = re.search(r'com/(\d+)/', url).group(1)
url = 'https://api.cc.163.com/v1/activitylives/anchor/lives?anchor_ccid=' + str(cid)
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
res = await resp.text()
data = json.loads(res).get('data').get(cid)
channel_id = data['channel_id']
roomId = data['room_id']
gametype = data['gametype']
reg_data = CC.s.get_reg()
beat_data = CC.s.get_beat()
join_data = CC.s.get_join(channel_id, gametype, roomId)
reg_datas = (reg_data, beat_data, join_data)
return 'wss://weblink.cc.163.com/', reg_datas
@staticmethod
def decode_msg(e):
n, r, p = struct.unpack('<HHI', e[:8])
i = 'tcp-{}-{}'.format(n, r)
studio = {
'tcp-512-32784': 'origin',
'tcp-515-32785': 'chat',
'tcp-535-32769': 'gamechat'
}
# 进场协议tcp-512-32784
# 聊天协议tcp-515-32785
# 游戏聊天tcp-535-32769
msgs = []
if i in studio.keys():
if p:
s, = struct.unpack('<I', e[8:12])
a = e[12:]
if len(a) == s:
o = a
else:
o = e[8:]
o = o if int(o[0]) != 120 else zlib.decompress(o)
CC.s.offset = 0
msg = CC.s.de_init(o)
ms_type = studio[i]
if ms_type == 'origin':
ms = msg['data']['msg_list']
else:
ms = msg['msg']
for m in ms:
if ms_type == 'origin':
name = m['name']
content = '欢迎来到直播间'
elif ms_type == 'chat':
name = m[197]
content = m[4]
elif ms_type == 'gamechat':
name = json.loads(m[7])['nickname']
content = m[4]
msg = {'name': name, 'content': content, 'msg_type': 'danmaku'}
msgs.append(msg.copy())
else:
msgs = [{'name': '', 'content': '', 'msg_type': 'other'}]
return msgs

View File

@ -31,3 +31,4 @@ asyncio.run(main(a))
# 企鹅电竞https://egame.qq.com/383204988 # 企鹅电竞https://egame.qq.com/383204988
# 花椒直播https://www.huajiao.com/l/303344861?qd=hu # 花椒直播https://www.huajiao.com/l/303344861?qd=hu
# 映客直播https://www.inke.cn/liveroom/index.html?uid=87493223&id=1593906372018299 # 映客直播https://www.inke.cn/liveroom/index.html?uid=87493223&id=1593906372018299
# CC直播https://cc.163.com/363936598/