Files
sg/xbpq/直播.py
2026-08-14 11:28:22 +02:00

258 lines
8.2 KiB
Python

# -*- coding: utf-8 -*-
import json
import sys
import traceback
sys.path.append('..')
from base.spider import Spider
class Spider(Spider):
primary_host = 'http://api.hclyz.com:81/mf/'
backup_host = 'http://api.maiyoux.com:81/mf/'
host = primary_host
platforms = []
def init(self, extend=""):
if extend:
h = extend.strip()
if not h.endswith('/'):
h += '/'
self.host = h
else:
self.host = self.primary_host
content = None
for base in [self.host, self.backup_host]:
try:
txt = self.fetch(base + 'json.txt').text
data = None
try:
data = json.loads(txt)
except Exception:
data = None
if data is not None:
self.host = base
self.platforms = self._parse_catalog_json(data)
if self.platforms:
return
else:
plats = self._parse_catalog_text(txt)
if plats:
self.host = base
self.platforms = plats
return
except Exception:
continue
def _parse_catalog_json(self, data):
items = []
if isinstance(data, dict):
if 'pingtai' in data and isinstance(data['pingtai'], list):
items = data['pingtai']
else:
if all(isinstance(v, dict) for v in data.values()):
items = list(data.values())
elif isinstance(data, list):
items = data
platforms = []
for it in items:
name = it.get('mc') or it.get('title') or it.get('name') or ''
img = it.get('tp1') or it.get('xinimg') or it.get('img') or ''
file = it.get('dz') or it.get('address') or it.get('file') or ''
count = it.get('sl') or it.get('Number') or it.get('count') or 0
try:
count = int(count)
except Exception:
pass
if name and file:
if not file.endswith('.txt'):
file += '.txt'
if not file.startswith('json'):
file = 'json' + file
platforms.append({
'name': name,
'img': img,
'file': file,
'count': count
})
return platforms
def _parse_catalog_text(self, txt):
plats = []
block = txt.strip()
if not block:
return plats
if block.startswith('{') and block.endswith('}'):
block = block[1:-1]
chunks = [c for c in block.split('|') if c.strip()]
curr = {'mc': '', 'tp1': '', 'dz': '', 'sl': 0}
def flush():
if curr.get('mc') and curr.get('dz'):
try:
sl = int(curr.get('sl') or 0)
except Exception:
sl = curr.get('sl') or 0
fname = curr.get('dz')
if not fname.endswith('.txt'):
fname += '.txt'
if not fname.startswith('json'):
fname = 'json' + fname
plats.append({
'name': curr.get('mc'),
'img': curr.get('tp1'),
'file': fname,
'count': sl
})
for c in chunks:
s = c.strip()
if s.startswith('@mc'):
if curr.get('mc') or curr.get('dz'):
flush()
curr = {'mc': '', 'tp1': '', 'dz': '', 'sl': 0}
curr['mc'] = s.replace('@mc', '', 1)
elif s.startswith('@tp1'):
curr['tp1'] = s.replace('@tp1', '', 1)
elif s.startswith('@dz'):
curr['dz'] = s.replace('@dz', '', 1)
elif s.startswith('@sl'):
curr['sl'] = s.replace('@sl', '', 1)
if curr.get('mc') or curr.get('dz'):
flush()
return plats
def _load_platform_rooms(self, file_path, pg=1):
url_candidates = [
self.host + file_path,
]
alt_path = file_path.replace('json', '', 1)
if alt_path != file_path:
url_candidates.insert(0, self.host + alt_path)
data = None
raw = None
for u in url_candidates:
try:
raw = self.fetch(u).text
data = json.loads(raw)
break
except Exception:
data = None
continue
rooms = []
if isinstance(data, dict):
if 'zhubo' in data and isinstance(data['zhubo'], list):
rooms = data['zhubo']
elif 'list' in data and isinstance(data['list'], list):
rooms = data['list']
elif 'data' in data and isinstance(data['data'], list):
rooms = data['data']
elif 'rooms' in data and isinstance(data['rooms'], list):
rooms = data['rooms']
elif isinstance(data, list):
rooms = data
videos = []
for idx, r in enumerate(rooms or [], 1):
title = r.get('title') or r.get('name') or r.get('nickname') or f'主播{idx}'
address = r.get('address') or r.get('url') or r.get('stream') or ''
img = r.get('img') or r.get('pic') or r.get('avatar') or ''
remarks = r.get('Number') or r.get('online') or r.get('viewers') or ''
if title and address:
videos.append({
'vod_id': address,
'vod_name': title,
'vod_pic': img,
'vod_remarks': str(remarks)
})
total = len(videos)
if pg > 1:
start = (pg - 1) * 20
videos = videos[start:start + 20]
return videos, total
def isVideoFormat(self, url):
return False
def manualVideoCheck(self):
pass
def getName(self):
return 'Leospring直播'
def homeContent(self, filter):
classes = []
for p in self.platforms:
classes.append({
'type_id': p['file'],
'type_name': p['name'],
})
return {'class': classes}
def homeVideoContent(self):
return {'list': []}
def _find_platform(self, tid):
for p in self.platforms:
if p['file'] == tid or p['name'] == tid:
return p
return None
def categoryContent(self, tid, pg, filter, extend):
p = self._find_platform(tid)
if not p:
return {'list': [], 'page': pg, 'pagecount': 0, 'limit': 0, 'total': 0}
videos, total = self._load_platform_rooms(p['file'], int(pg))
pagecount = (total + 19) // 20
result = {
'list': videos,
'page': pg,
'pagecount': pagecount,
'limit': min(len(videos), 20),
'total': total
}
return result
def searchContent(self, key, quick, pg="1"):
key = (key or '').strip().lower()
out = []
if not key:
return {'list': out}
for p in self.platforms:
videos, _ = self._load_platform_rooms(p['file'])
for v in videos:
if key in v['vod_name'].lower():
out.append(v)
if len(out) >= 50:
break
return {'list': out[:50]}
def detailContent(self, ids):
try:
address = ids[0]
if not address:
return {'list': []}
vod = {
'vod_id': address,
'vod_name': '直播源',
'vod_play_from': '每日必修课',
'vod_play_url': address,
'vod_content': '多看少打卡',
}
return {'list': [vod]}
except Exception as e:
traceback.print_exc()
return {'list': []}
def playerContent(self, flag, id, vipFlags):
return {
'parse': 0,
'url': id
}
def localProxy(self, param):
pass