diff --git a/py/Pandalive.py b/py/Pandalive.py deleted file mode 100644 index 049f4fe..0000000 --- a/py/Pandalive.py +++ /dev/null @@ -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 - } \ No newline at end of file