删除 py/Pandalive.py
This commit is contained in:
-232
@@ -1,232 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import requests
|
||||
import urllib.parse
|
||||
import json
|
||||
|
||||
class Spider:
|
||||
def init(self, extend=""):
|
||||
self.host = "https://5721004.xyz"
|
||||
self.headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
||||
'Referer': 'https://www.pandalive.co.kr/',
|
||||
'Origin': 'https://www.pandalive.co.kr'
|
||||
}
|
||||
print("PandaLive 專業版 (僅 PandaTV) 初始化成功")
|
||||
|
||||
def getName(self):
|
||||
return "PandaLive"
|
||||
|
||||
def getDependence(self):
|
||||
return []
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
return False
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
def localProxy(self, param):
|
||||
return None
|
||||
|
||||
def homeContent(self, filter):
|
||||
"""首頁 - 僅保留 PandaTV 分類與對應篩選器"""
|
||||
try:
|
||||
# 只保留 PandaTV
|
||||
classes = [
|
||||
{'type_id': 'pandalive', 'type_name': '🐼 PandaTV'}
|
||||
]
|
||||
|
||||
filters = {
|
||||
"pandalive": [
|
||||
{
|
||||
"key": "type",
|
||||
"name": "類型",
|
||||
"value": [
|
||||
{"n": "全部", "v": "all"},
|
||||
{"n": "🔞 19+", "v": "adult"},
|
||||
{"n": "🔐 密碼房", "v": "pw"},
|
||||
{"n": "💎 粉絲房", "v": "fan"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "sort",
|
||||
"name": "排序",
|
||||
"value": [
|
||||
{"n": "觀眾量 ↓", "v": "user-desc"},
|
||||
{"n": "實時熱度 ↓", "v": "totalScoreCnt-desc"},
|
||||
{"n": "關注量 ↓", "v": "bookmarkCnt-desc"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# 獲取首頁推薦數據 (從 JSON 獲取以保證有圖片)
|
||||
all_data = self._fetch_json_data()
|
||||
return {
|
||||
'class': classes,
|
||||
'list': all_data[:30],
|
||||
'filters': filters
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"homeContent錯誤: {e}")
|
||||
return {'class': [], 'list': []}
|
||||
|
||||
def homeVideoContent(self):
|
||||
try:
|
||||
return {'list': self._fetch_json_data()[:20]}
|
||||
except:
|
||||
return {'list': []}
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
"""分類頁 - 基於 JSON 的篩選排序邏輯"""
|
||||
try:
|
||||
all_list = self._fetch_json_data()
|
||||
filtered = all_list
|
||||
|
||||
# 1. 執行篩選
|
||||
f_type = extend.get('type', 'all')
|
||||
if f_type == 'adult':
|
||||
filtered = [v for v in filtered if v.get('_isAdult')]
|
||||
elif f_type == 'pw':
|
||||
filtered = [v for v in filtered if v.get('_isPw')]
|
||||
elif f_type == 'fan':
|
||||
filtered = [v for v in filtered if v.get('_type') == 'fan']
|
||||
|
||||
# 2. 執行排序
|
||||
sort_type = extend.get('sort', 'user-desc')
|
||||
if sort_type == 'user-desc':
|
||||
filtered.sort(key=lambda x: x.get('_user_count', 0), reverse=True)
|
||||
elif sort_type == 'totalScoreCnt-desc':
|
||||
filtered.sort(key=lambda x: x.get('_score', 0), reverse=True)
|
||||
elif sort_type == 'bookmarkCnt-desc':
|
||||
filtered.sort(key=lambda x: x.get('_bookmark', 0), reverse=True)
|
||||
|
||||
# 3. 分頁
|
||||
pg = int(pg)
|
||||
limit = 30
|
||||
start = (pg - 1) * limit
|
||||
end = start + limit
|
||||
page_list = filtered[start:end] if start < len(filtered) else []
|
||||
|
||||
return {
|
||||
'list': page_list,
|
||||
'page': pg,
|
||||
'pagecount': (len(filtered) + limit - 1) // limit if filtered else 1,
|
||||
'limit': limit,
|
||||
'total': len(filtered)
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"categoryContent錯誤: {e}")
|
||||
return {'list': [], 'page': int(pg)}
|
||||
|
||||
def _fetch_json_data(self):
|
||||
"""抓取 list.json 數據,確保 vod_pic 獲取正確"""
|
||||
try:
|
||||
url = f"{self.host}/player/list.json"
|
||||
res = requests.get(url, headers=self.headers, timeout=10)
|
||||
if res.status_code != 200:
|
||||
return []
|
||||
|
||||
data = res.json()
|
||||
raw_list = data.get('list', [])
|
||||
|
||||
processed = []
|
||||
for item in raw_list:
|
||||
user_id = item.get('userId', '')
|
||||
nick = item.get('userNick', '未知主播')
|
||||
title = item.get('title', '無標題')
|
||||
|
||||
is_adult = item.get('isAdult', False)
|
||||
is_pw = item.get('isPw', False)
|
||||
v_type = item.get('type', '')
|
||||
|
||||
processed.append({
|
||||
'vod_id': f"live_{user_id}",
|
||||
'vod_name': f"📺 {nick}",
|
||||
'vod_pic': item.get('thumbUrl', 'https://tupian.li/images/2024/03/30/660769b1ba623.png'),
|
||||
'vod_remarks': f"👤 {item.get('user', 0)} {'🔞' if is_adult else ''}",
|
||||
'vod_content': title,
|
||||
'vod_actor': user_id,
|
||||
'_isAdult': is_adult,
|
||||
'_isPw': is_pw,
|
||||
'_type': v_type,
|
||||
'_user_count': item.get('user', 0),
|
||||
'_score': item.get('totalScoreCnt', 0),
|
||||
'_bookmark': item.get('bookmarkCnt', 0)
|
||||
})
|
||||
return processed
|
||||
except Exception as e:
|
||||
print(f"JSON抓取失敗: {e}")
|
||||
return []
|
||||
|
||||
def detailContent(self, ids):
|
||||
"""詳情頁 - 保持對接 list.m3u 獲取真實流地址的邏輯"""
|
||||
try:
|
||||
first_id = ids[0] if isinstance(ids, list) else ids
|
||||
user_id = first_id.replace("live_", "")
|
||||
|
||||
stream_url = ""
|
||||
m3u_res = requests.get(f"{self.host}/player/list.m3u", headers=self.headers, timeout=10)
|
||||
if m3u_res.status_code == 200:
|
||||
lines = m3u_res.text.split('\n')
|
||||
for i, line in enumerate(lines):
|
||||
# 匹配格式: #EXTINF:0,主播ID,主播名稱
|
||||
if f",{user_id}," in line and i + 1 < len(lines):
|
||||
stream_url = lines[i+1].strip()
|
||||
break
|
||||
|
||||
if not stream_url:
|
||||
# 如果 M3U 匹配不到,嘗試模糊匹配主播 ID
|
||||
for i, line in enumerate(lines):
|
||||
if user_id in line and i + 1 < len(lines):
|
||||
stream_url = lines[i+1].strip()
|
||||
break
|
||||
|
||||
proxies = [
|
||||
"https://hubu.515355.xyz/proxy/?",
|
||||
"https://flank.515355.xyz/proxy/",
|
||||
"https://uae2.515355.xyz/proxy/",
|
||||
"https://pol.515355.xyz/proxy/",
|
||||
"https://f00.515355.xyz/proxy/",
|
||||
"https://ce2.515355.xyz/proxy/?",
|
||||
]
|
||||
|
||||
# 1. 首先创建列表,并将“直连”作为第一个元素添加进去
|
||||
play_links = [f"直連${stream_url}"]
|
||||
|
||||
# 2. 然后通过 extend() 方法或循环,将生成的代理链接追加到列表中
|
||||
play_links.extend([f"代理{i}${p}{stream_url}" for i, p in enumerate(proxies, 1)])
|
||||
|
||||
|
||||
vod = {
|
||||
'vod_id': first_id,
|
||||
'vod_name': f"PandaTV - {user_id}",
|
||||
'vod_pic': 'https://tupian.li/images/2024/03/30/660769b1ba623.png',
|
||||
'vod_content': f'主播: {user_id}',
|
||||
'vod_play_from': 'PandaLive',
|
||||
'vod_play_url': '#'.join(play_links)
|
||||
}
|
||||
return {'list': [vod]}
|
||||
except Exception as e:
|
||||
print(f"detailContent錯誤: {e}")
|
||||
return {'list': []}
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
"""搜索 - 帶 pg="1" 修復"""
|
||||
try:
|
||||
all_v = self._fetch_json_data()
|
||||
key_l = key.lower()
|
||||
res = [v for v in all_v if key_l in v['vod_name'].lower() or key_l in v['vod_actor'].lower()]
|
||||
return {'list': res[:50], 'page': int(pg)}
|
||||
except:
|
||||
return {'list': [], 'page': int(pg)}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
return {
|
||||
'parse': 0,
|
||||
'url': id,
|
||||
'header': self.headers
|
||||
}
|
||||
Reference in New Issue
Block a user