Sync all projects
This commit is contained in:
@@ -0,0 +1,390 @@
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
import hashlib
|
||||
from base64 import b64decode, b64encode
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import requests
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import unpad
|
||||
from pyquery import PyQuery as pq
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider as BaseSpider
|
||||
|
||||
img_cache = {}
|
||||
|
||||
class Spider(BaseSpider):
|
||||
|
||||
def init(self, extend=""):
|
||||
try:
|
||||
self.proxies = json.loads(extend)
|
||||
except:
|
||||
self.proxies = {}
|
||||
self.headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9',
|
||||
'Connection': 'keep-alive',
|
||||
'Cache-Control': 'no-cache',
|
||||
}
|
||||
self.host = self.get_working_host()
|
||||
self.headers.update({'Origin': self.host, 'Referer': f"{self.host}/"})
|
||||
print(f"使用站点: {self.host}")
|
||||
|
||||
def getName(self):
|
||||
return "🌈 91吃瓜中心|终极完美版"
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
return any(ext in (url or '') for ext in ['.m3u8', '.mp4', '.ts'])
|
||||
|
||||
def manualVideoCheck(self):
|
||||
return False
|
||||
|
||||
def destroy(self):
|
||||
global img_cache
|
||||
img_cache.clear()
|
||||
|
||||
def get_working_host(self):
|
||||
dynamic_urls = [
|
||||
'https://but.ybejhul.com/',
|
||||
'https://adopt.ybejhul.com'
|
||||
]
|
||||
for url in dynamic_urls:
|
||||
try:
|
||||
response = requests.get(url, headers=self.headers, proxies=self.proxies, timeout=10)
|
||||
if response.status_code == 200:
|
||||
return url
|
||||
except Exception:
|
||||
continue
|
||||
return dynamic_urls[0]
|
||||
|
||||
def homeContent(self, filter):
|
||||
try:
|
||||
response = requests.get(self.host, headers=self.headers, proxies=self.proxies, timeout=15)
|
||||
if response.status_code != 200: return {'class': [], 'list': []}
|
||||
data = self.getpq(response.text)
|
||||
|
||||
classes = []
|
||||
category_selectors = ['.category-list ul li', '.nav-menu li', '.menu li', 'nav ul li']
|
||||
for selector in category_selectors:
|
||||
for k in data(selector).items():
|
||||
link = k('a')
|
||||
href = (link.attr('href') or '').strip()
|
||||
name = (link.text() or '').strip()
|
||||
if not href or href == '#' or not name: continue
|
||||
classes.append({'type_name': name, 'type_id': href})
|
||||
if classes: break
|
||||
|
||||
if not classes:
|
||||
classes = [{'type_name': '最新', 'type_id': '/latest/'}, {'type_name': '热门', 'type_id': '/hot/'}]
|
||||
|
||||
return {'class': classes, 'list': self.getlist(data('#index article, article'))}
|
||||
except Exception as e:
|
||||
return {'class': [], 'list': []}
|
||||
|
||||
def homeVideoContent(self):
|
||||
try:
|
||||
response = requests.get(self.host, headers=self.headers, proxies=self.proxies, timeout=15)
|
||||
if response.status_code != 200: return {'list': []}
|
||||
data = self.getpq(response.text)
|
||||
return {'list': self.getlist(data('#index article, article'))}
|
||||
except Exception as e:
|
||||
return {'list': []}
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
try:
|
||||
if '@folder' in tid:
|
||||
v = self.getfod(tid.replace('@folder', ''))
|
||||
return {'list': v, 'page': 1, 'pagecount': 1, 'limit': 90, 'total': len(v)}
|
||||
|
||||
pg = int(pg) if pg else 1
|
||||
|
||||
if tid.startswith('http'):
|
||||
base_url = tid.rstrip('/')
|
||||
else:
|
||||
path = tid if tid.startswith('/') else f"/{tid}"
|
||||
base_url = f"{self.host}{path}".rstrip('/')
|
||||
|
||||
if pg == 1:
|
||||
url = f"{base_url}/"
|
||||
else:
|
||||
url = f"{base_url}/{pg}/"
|
||||
|
||||
response = requests.get(url, headers=self.headers, proxies=self.proxies, timeout=15)
|
||||
if response.status_code != 200: return {'list': [], 'page': pg, 'pagecount': 9999, 'limit': 90, 'total': 0}
|
||||
|
||||
data = self.getpq(response.text)
|
||||
videos = self.getlist(data('#archive article, #index article, article'), tid)
|
||||
|
||||
return {'list': videos, 'page': pg, 'pagecount': 9999, 'limit': 90, 'total': 999999}
|
||||
except Exception as e:
|
||||
return {'list': [], 'page': pg, 'pagecount': 9999, 'limit': 90, 'total': 0}
|
||||
|
||||
def detailContent(self, ids):
|
||||
try:
|
||||
url = ids[0] if ids[0].startswith('http') else f"{self.host}{ids[0]}"
|
||||
response = requests.get(url, headers=self.headers, proxies=self.proxies, timeout=15)
|
||||
data = self.getpq(response.text)
|
||||
|
||||
plist = []
|
||||
used_names = set()
|
||||
if data('.dplayer'):
|
||||
for c, k in enumerate(data('.dplayer').items(), start=1):
|
||||
try:
|
||||
config_attr = k.attr('data-config')
|
||||
if config_attr:
|
||||
config = json.loads(config_attr)
|
||||
video_url = config.get('video', {}).get('url', '')
|
||||
|
||||
if video_url:
|
||||
ep_name = ''
|
||||
parent = k.parents().eq(0)
|
||||
for _ in range(4):
|
||||
if not parent: break
|
||||
heading = parent.find('h2, h3, h4').eq(0).text().strip()
|
||||
if heading:
|
||||
ep_name = heading
|
||||
break
|
||||
parent = parent.parents().eq(0)
|
||||
|
||||
base_name = ep_name if ep_name else f"视频{c}"
|
||||
name = base_name
|
||||
count = 2
|
||||
while name in used_names:
|
||||
name = f"{base_name} {count}"
|
||||
count += 1
|
||||
used_names.add(name)
|
||||
|
||||
plist.append(f"{name}${video_url}")
|
||||
except: continue
|
||||
|
||||
if not plist:
|
||||
content_area = data('.post-content, article')
|
||||
for i, link in enumerate(content_area('a').items(), start=1):
|
||||
link_text = link.text().strip()
|
||||
link_href = link.attr('href')
|
||||
|
||||
if link_href and any(kw in link_text for kw in ['点击观看', '观看', '播放', '视频', '第一弹', '第二弹', '第三弹', '第四弹', '第五弹', '第六弹', '第七弹', '第八弹', '第九弹', '第十弹']):
|
||||
ep_name = link_text.replace('点击观看:', '').replace('点击观看', '').strip()
|
||||
if not ep_name: ep_name = f"视频{i}"
|
||||
|
||||
if not link_href.startswith('http'):
|
||||
link_href = f"{self.host}{link_href}" if link_href.startswith('/') else f"{self.host}/{link_href}"
|
||||
|
||||
plist.append(f"{ep_name}${link_href}")
|
||||
|
||||
play_url = '#'.join(plist) if plist else f"未找到视频源${url}"
|
||||
|
||||
vod_content = ''
|
||||
try:
|
||||
tags = []
|
||||
seen_names = set()
|
||||
seen_ids = set()
|
||||
|
||||
tag_links = data('.tags a, .keywords a, .post-tags a')
|
||||
|
||||
candidates = []
|
||||
for k in tag_links.items():
|
||||
title = k.text().strip()
|
||||
href = k.attr('href')
|
||||
if title and href:
|
||||
candidates.append({'name': title, 'id': href})
|
||||
|
||||
candidates.sort(key=lambda x: len(x['name']), reverse=True)
|
||||
|
||||
for item in candidates:
|
||||
name = item['name']
|
||||
id_ = item['id']
|
||||
|
||||
if id_ in seen_ids: continue
|
||||
|
||||
is_duplicate = False
|
||||
for seen in seen_names:
|
||||
if name in seen:
|
||||
is_duplicate = True
|
||||
break
|
||||
|
||||
if not is_duplicate:
|
||||
target = json.dumps({'id': id_, 'name': name})
|
||||
tags.append(f'[a=cr:{target}/]{name}[/a]')
|
||||
seen_names.add(name)
|
||||
seen_ids.add(id_)
|
||||
|
||||
if tags:
|
||||
vod_content = ' '.join(tags)
|
||||
else:
|
||||
vod_content = data('.post-title').text()
|
||||
except Exception:
|
||||
vod_content = '获取标签失败'
|
||||
|
||||
if not vod_content:
|
||||
vod_content = data('h1').text() or '91吃瓜中心'
|
||||
|
||||
return {'list': [{'vod_play_from': '91吃瓜中心', 'vod_play_url': play_url, 'vod_content': vod_content}]}
|
||||
except:
|
||||
return {'list': [{'vod_play_from': '91吃瓜中心', 'vod_play_url': '获取失败'}]}
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
try:
|
||||
pg = int(pg) if pg else 1
|
||||
|
||||
if pg == 1:
|
||||
url = f"{self.host}/search/{key}/"
|
||||
else:
|
||||
url = f"{self.host}/search/{key}/{pg}/"
|
||||
|
||||
response = requests.get(url, headers=self.headers, proxies=self.proxies, timeout=15)
|
||||
return {'list': self.getlist(self.getpq(response.text)('article')), 'page': pg, 'pagecount': 9999}
|
||||
except:
|
||||
return {'list': [], 'page': pg, 'pagecount': 9999}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
parse = 0 if self.isVideoFormat(id) else 1
|
||||
url = self.proxy(id) if '.m3u8' in id else id
|
||||
return {'parse': parse, 'url': url, 'header': self.headers}
|
||||
|
||||
def localProxy(self, param):
|
||||
try:
|
||||
type_ = param.get('type')
|
||||
url = param.get('url')
|
||||
if type_ == 'cache':
|
||||
key = param.get('key')
|
||||
if content := img_cache.get(key):
|
||||
return [200, 'image/jpeg', content]
|
||||
return [404, 'text/plain', b'Expired']
|
||||
elif type_ == 'img':
|
||||
real_url = self.d64(url) if not url.startswith('http') else url
|
||||
res = requests.get(real_url, headers=self.headers, proxies=self.proxies, timeout=10)
|
||||
content = self.aesimg(res.content)
|
||||
return [200, 'image/jpeg', content]
|
||||
elif type_ == 'm3u8':
|
||||
return self.m3Proxy(url)
|
||||
else:
|
||||
return self.tsProxy(url)
|
||||
except:
|
||||
return [404, 'text/plain', b'']
|
||||
|
||||
def proxy(self, data, type='m3u8'):
|
||||
if data and self.proxies: return f"{self.getProxyUrl()}&url={self.e64(data)}&type={type}"
|
||||
return data
|
||||
|
||||
def m3Proxy(self, url):
|
||||
url = self.d64(url)
|
||||
res = requests.get(url, headers=self.headers, proxies=self.proxies)
|
||||
data = res.text
|
||||
base = res.url.rsplit('/', 1)[0]
|
||||
lines = []
|
||||
for line in data.split('\n'):
|
||||
if '#EXT' not in line and line.strip():
|
||||
if not line.startswith('http'):
|
||||
line = f"{base}/{line}"
|
||||
lines.append(self.proxy(line, 'ts'))
|
||||
else:
|
||||
lines.append(line)
|
||||
return [200, "application/vnd.apple.mpegurl", '\n'.join(lines)]
|
||||
|
||||
def tsProxy(self, url):
|
||||
return [200, 'video/mp2t', requests.get(self.d64(url), headers=self.headers, proxies=self.proxies).content]
|
||||
|
||||
def e64(self, text):
|
||||
return b64encode(str(text).encode()).decode()
|
||||
|
||||
def d64(self, text):
|
||||
return b64decode(str(text).encode()).decode()
|
||||
|
||||
def aesimg(self, data):
|
||||
if len(data) < 16: return data
|
||||
keys = [(b'f5d965df75336270', b'97b60394abc2fbe1'), (b'75336270f5d965df', b'abc2fbe197b60394')]
|
||||
for k, v in keys:
|
||||
try:
|
||||
dec = unpad(AES.new(k, AES.MODE_CBC, v).decrypt(data), 16)
|
||||
if dec.startswith(b'\xff\xd8') or dec.startswith(b'\x89PNG'): return dec
|
||||
except: pass
|
||||
try:
|
||||
dec = unpad(AES.new(k, AES.MODE_ECB).decrypt(data), 16)
|
||||
if dec.startswith(b'\xff\xd8'): return dec
|
||||
except: pass
|
||||
return data
|
||||
|
||||
def getlist(self, data, tid=''):
|
||||
videos = []
|
||||
is_folder = '/mrdg' in (tid or '')
|
||||
for k in data.items():
|
||||
card_html = k.outer_html() if hasattr(k, 'outer_html') else str(k)
|
||||
a = k if k.is_('a') else k('a').eq(0)
|
||||
href = a.attr('href')
|
||||
title = k('h2').text() or k('.entry-title').text() or k('.post-title').text()
|
||||
if not title and k.is_('a'): title = k.text()
|
||||
|
||||
if href and title:
|
||||
img = self.getimg(k('script').text(), k, card_html)
|
||||
videos.append({
|
||||
'vod_id': f"{href}{'@folder' if is_folder else ''}",
|
||||
'vod_name': title.strip(),
|
||||
'vod_pic': img,
|
||||
'vod_remarks': k('time').text() or '',
|
||||
'vod_tag': 'folder' if is_folder else '',
|
||||
'style': {"type": "rect", "ratio": 1.33}
|
||||
})
|
||||
return videos
|
||||
|
||||
def getfod(self, id):
|
||||
url = f"{self.host}{id}"
|
||||
data = self.getpq(requests.get(url, headers=self.headers, proxies=self.proxies).text)
|
||||
videos = []
|
||||
for i, h2 in enumerate(data('.post-content h2').items()):
|
||||
p_txt = data('.post-content p').eq(i * 2)
|
||||
p_img = data('.post-content p').eq(i * 2 + 1)
|
||||
p_html = p_img.outer_html() if hasattr(p_img, 'outer_html') else str(p_img)
|
||||
videos.append({
|
||||
'vod_id': p_txt('a').attr('href'),
|
||||
'vod_name': p_txt.text().strip(),
|
||||
'vod_pic': self.getimg('', p_img, p_html),
|
||||
'vod_remarks': h2.text().strip()
|
||||
})
|
||||
return videos
|
||||
|
||||
def getimg(self, text, elem=None, html_content=None):
|
||||
if m := re.search(r"loadBannerDirect\('([^']+)'", text or ''):
|
||||
return self._proc_url(m.group(1))
|
||||
|
||||
if html_content is None and elem is not None:
|
||||
html_content = elem.outer_html() if hasattr(elem, 'outer_html') else str(elem)
|
||||
if not html_content: return ''
|
||||
|
||||
html_content = html_content.replace('"', '"').replace(''', "'").replace('&', '&')
|
||||
|
||||
if 'data:image' in html_content:
|
||||
m = re.search(r'(data:image/[a-zA-Z0-9+/=;,]+)', html_content)
|
||||
if m: return self._proc_url(m.group(1))
|
||||
|
||||
m = re.search(r'(https?://[^"\'\s)]+\.(?:jpg|png|jpeg|webp))', html_content, re.I)
|
||||
if m: return self._proc_url(m.group(1))
|
||||
|
||||
if 'url(' in html_content:
|
||||
m = re.search(r'url\s*\(\s*[\'"]?([^"\'\)]+)[\'"]?\s*\)', html_content, re.I)
|
||||
if m: return self._proc_url(m.group(1))
|
||||
|
||||
return ''
|
||||
|
||||
def _proc_url(self, url):
|
||||
if not url: return ''
|
||||
url = url.strip('\'" ')
|
||||
if url.startswith('data:'):
|
||||
try:
|
||||
_, b64_str = url.split(',', 1)
|
||||
raw = b64decode(b64_str)
|
||||
if not (raw.startswith(b'\xff\xd8') or raw.startswith(b'\x89PNG') or raw.startswith(b'GIF8')):
|
||||
raw = self.aesimg(raw)
|
||||
key = hashlib.md5(raw).hexdigest()
|
||||
img_cache[key] = raw
|
||||
return f"{self.getProxyUrl()}&type=cache&key={key}"
|
||||
except: return ""
|
||||
if not url.startswith('http'):
|
||||
url = f"{self.host}{url}" if url.startswith('/') else f"{self.host}/{url}"
|
||||
return f"{self.getProxyUrl()}&url={self.e64(url)}&type=img"
|
||||
|
||||
def getpq(self, data):
|
||||
try: return pq(data)
|
||||
except: return pq(data.encode('utf-8'))
|
||||
@@ -0,0 +1,236 @@
|
||||
# coding=utf-8
|
||||
# !/python
|
||||
import sys
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
import re
|
||||
from urllib.parse import urljoin
|
||||
from base.spider import Spider
|
||||
import time
|
||||
|
||||
sys.path.append('..')
|
||||
|
||||
# 全局配置
|
||||
xurl = "https://barely.vmwzzqom.cc/"
|
||||
backup_urls = ["https://hlj.fun", "https://911bl16.com"]
|
||||
headerx = {
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1",
|
||||
"Referer": "https://911blw.com",
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8"
|
||||
}
|
||||
IMAGE_FILTER = ["/usr/themes/ads-close.png", "close", "icon", "logo"]
|
||||
|
||||
class Spider(Spider):
|
||||
def getName(self):
|
||||
return "911爆料网"
|
||||
|
||||
def init(self, extend):
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def fetch_page(self, url, use_backup=False):
|
||||
global xurl
|
||||
original_url = url
|
||||
if use_backup:
|
||||
for backup in backup_urls:
|
||||
test_url = url.replace(xurl, backup)
|
||||
try:
|
||||
time.sleep(1)
|
||||
res = requests.get(test_url, headers=headerx, timeout=10)
|
||||
res.raise_for_status()
|
||||
res.encoding = "utf-8"
|
||||
text = res.text
|
||||
if len(text) > 1000:
|
||||
print(f"[DEBUG] 使用备用 {backup}: {test_url}")
|
||||
return text
|
||||
except:
|
||||
continue
|
||||
print(f"[ERROR] 所有备用失败,回退原 URL")
|
||||
|
||||
try:
|
||||
time.sleep(1)
|
||||
res = requests.get(original_url, headers=headerx, timeout=10)
|
||||
res.raise_for_status()
|
||||
res.encoding = "utf-8"
|
||||
text = res.text
|
||||
doc = BeautifulSoup(text, "html.parser")
|
||||
title = doc.title.string if doc.title else "无标题"
|
||||
print(f"[DEBUG] 页面 {original_url}: 长度={len(text)}, 标题={title}")
|
||||
if len(text) < 1000:
|
||||
print(f"[DEBUG] 内容过短,尝试备用域名")
|
||||
return self.fetch_page(original_url, use_backup=True)
|
||||
return text
|
||||
except Exception as e:
|
||||
print(f"[ERROR] 请求失败 {original_url}: {e}")
|
||||
return None
|
||||
|
||||
def extract_content(self, html, url):
|
||||
videos = []
|
||||
if not html:
|
||||
return videos
|
||||
|
||||
doc = BeautifulSoup(html, "html.parser")
|
||||
containers = doc.select("ul.row li, div.article-item, article, .post-item, div[class*='item']")
|
||||
print(f"[DEBUG] 找到 {len(containers)} 个容器")
|
||||
|
||||
for i, vod in enumerate(containers[:20], 1):
|
||||
try:
|
||||
# 标题
|
||||
title_elem = vod.select_one("h2.headline, .headline, a[title]")
|
||||
name = title_elem.get("title") or title_elem.get_text(strip=True) if title_elem else ""
|
||||
if not name:
|
||||
name_match = re.search(r'headline">(.+?)<', str(vod))
|
||||
name = name_match.group(1).strip() if name_match else ""
|
||||
|
||||
# 链接
|
||||
link_elem = vod.select_one("a")
|
||||
id = urljoin(xurl, link_elem["href"]) if link_elem else ""
|
||||
|
||||
# 备注
|
||||
remarks_elem = vod.select_one("span.small, time, .date")
|
||||
remarks = remarks_elem.get_text(strip=True) if remarks_elem else ""
|
||||
if not remarks:
|
||||
remarks_match = re.search(r'datePublished[^>]*>(.+?)<', str(vod))
|
||||
remarks = remarks_match.group(1).strip() if remarks_match else ""
|
||||
|
||||
# 图片 - 扩展属性
|
||||
img = vod.select_one("img")
|
||||
pic = None
|
||||
if img:
|
||||
# 检查多种图片属性
|
||||
for attr in ["data-lazy-src", "data-original", "data-src", "src"]:
|
||||
pic = img.get(attr)
|
||||
if pic:
|
||||
break
|
||||
# 检查背景图片
|
||||
if not pic:
|
||||
bg_div = vod.select_one("div[style*='background-image']")
|
||||
if bg_div and "background-image" in bg_div.get("style", ""):
|
||||
bg_match = re.search(r'url\([\'"]?(.+?)[\'"]?\)', bg_div["style"])
|
||||
pic = bg_match.group(1) if bg_match else None
|
||||
if pic:
|
||||
pic = urljoin(xurl, pic)
|
||||
alt = img.get("alt", "").lower() if img else ""
|
||||
if any(f in pic.lower() or f in alt for f in IMAGE_FILTER):
|
||||
pic = None
|
||||
print(f"[DEBUG] 项 {i} 图片: {pic}, 属性={img.attrs if img else '无img'}")
|
||||
|
||||
# 简介
|
||||
desc_match = re.search(r'og:description" content="(.+?)"', html)
|
||||
description = desc_match.group(1) if desc_match else ""
|
||||
|
||||
if name and id:
|
||||
video = {
|
||||
"vod_id": id,
|
||||
"vod_name": name[:100],
|
||||
"vod_pic": pic,
|
||||
"vod_remarks": remarks,
|
||||
"vod_content": description
|
||||
}
|
||||
videos.append(video)
|
||||
print(f"[DEBUG] 项 {i}: 标题={name[:50]}..., 链接={id}, 图片={pic}")
|
||||
except Exception as e:
|
||||
print(f"[DEBUG] 项 {i} 错误: {e}")
|
||||
continue
|
||||
|
||||
print(f"[DEBUG] 提取 {len(videos)} 个项")
|
||||
return videos
|
||||
|
||||
def homeVideoContent(self):
|
||||
url = f"{xurl}/category/jrgb/1/"
|
||||
html = self.fetch_page(url)
|
||||
videos = self.extract_content(html, url)
|
||||
return {'list': videos}
|
||||
|
||||
def homeContent(self, filter):
|
||||
result = {'class': []}
|
||||
categories = [
|
||||
{"type_id": "/category/jrgb/", "type_name": "最新爆料"},
|
||||
{"type_id": "/category/rmgb/", "type_name": "精选大瓜"},
|
||||
{"type_id": "/category/blqw/", "type_name": "猎奇吃瓜"},
|
||||
{"type_id": "/category/rlph/", "type_name": "TOP5大瓜"},
|
||||
{"type_id": "/category/ssdbl/", "type_name": "社会热点"},
|
||||
{"type_id": "/category/hjsq/", "type_name": "海角社区"},
|
||||
{"type_id": "/category/mrds/", "type_name": "每日大赛"},
|
||||
{"type_id": "/category/xyss/", "type_name": "校园吃瓜"},
|
||||
{"type_id": "/category/mxhl/", "type_name": "明星吃瓜"},
|
||||
{"type_id": "/category/whbl/", "type_name": "网红爆料"},
|
||||
{"type_id": "/category/bgzq/", "type_name": "反差爆料"},
|
||||
{"type_id": "/category/fljq/", "type_name": "网黄福利"},
|
||||
{"type_id": "/category/crfys/", "type_name": "午夜剧场"},
|
||||
{"type_id": "/category/thjx/", "type_name": "探花经典"},
|
||||
{"type_id": "/category/dmhv/", "type_name": "禁漫天堂"},
|
||||
{"type_id": "/category/slec/", "type_name": "吃瓜精选"},
|
||||
{"type_id": "/category/zksr/", "type_name": "重口调教"},
|
||||
{"type_id": "/category/crlz/", "type_name": "精选连载"}
|
||||
]
|
||||
result['class'] = categories
|
||||
return result
|
||||
|
||||
def categoryContent(self, cid, pg, filter, ext):
|
||||
url = f"{xurl}{cid}{pg}/" if pg != "1" else f"{xurl}{cid}"
|
||||
html = self.fetch_page(url)
|
||||
videos = self.extract_content(html, url)
|
||||
return {
|
||||
'list': videos,
|
||||
'page': pg,
|
||||
'pagecount': 9999,
|
||||
'limit': 90,
|
||||
'total': 999999
|
||||
}
|
||||
|
||||
def detailContent(self, ids):
|
||||
videos = []
|
||||
did = ids[0]
|
||||
html = self.fetch_page(did)
|
||||
if html:
|
||||
source_match = re.search(r'"url":"(.*?)"', html)
|
||||
purl = source_match.group(1).replace("\\", "") if source_match else ""
|
||||
videos.append({
|
||||
"vod_id": did,
|
||||
"vod_play_from": "爆料",
|
||||
"vod_play_url": purl,
|
||||
"vod_content": re.search(r'og:description" content="(.+?)"', html).group(1) if re.search(r'og:description" content="(.+?)"', html) else ""
|
||||
})
|
||||
return {'list': videos}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
return {"parse": 0, "playUrl": "", "url": id, "header": headerx}
|
||||
|
||||
def searchContent(self, key, quick):
|
||||
return self.searchContentPage(key, quick, "1")
|
||||
|
||||
def searchContentPage(self, key, quick, page):
|
||||
url = f"{xurl}/search/{key}/{page}/"
|
||||
html = self.fetch_page(url)
|
||||
videos = self.extract_content(html, url)
|
||||
return {'list': videos, 'page': page, 'pagecount': 9999, 'limit': 90, 'total': 999999}
|
||||
|
||||
def localProxy(self, params):
|
||||
if params['type'] == "m3u8":
|
||||
return self.proxyM3u8(params)
|
||||
elif params['type'] == "media":
|
||||
return self.proxyMedia(params)
|
||||
elif params['type'] == "ts":
|
||||
return self.proxyTs(params)
|
||||
return None
|
||||
|
||||
if __name__ == "__main__":
|
||||
spider = Spider()
|
||||
# 测试首页推荐
|
||||
result = spider.homeVideoContent()
|
||||
print(f"测试首页推荐: {len(result['list'])} 个项")
|
||||
for item in result['list'][:3]:
|
||||
print(item)
|
||||
# 测试分类
|
||||
for cate in ["jrgb", "rmgb", "blqw"]:
|
||||
result = spider.categoryContent(f"/category/{cate}/", "1", False, {})
|
||||
print(f"测试分类 {cate}: {len(result['list'])} 个项")
|
||||
for item in result['list'][:2]:
|
||||
print(item)
|
||||
@@ -0,0 +1,260 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# by @嗷呜
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from pyquery import PyQuery as pq
|
||||
from base64 import b64decode, b64encode
|
||||
from requests import Session
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
|
||||
|
||||
class Spider(Spider):
|
||||
def init(self, extend=""):
|
||||
self.headers['referer']=f'{self.host}/'
|
||||
self.session = Session()
|
||||
self.session.headers.update(self.headers)
|
||||
pass
|
||||
|
||||
def getName(self):
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
host = "https://www.xvideos.com"
|
||||
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
||||
'sec-ch-ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-full-version': '"133.0.6943.98"',
|
||||
'sec-ch-ua-arch': '"x86"',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
'sec-ch-ua-platform-version': '"19.0.0"',
|
||||
'sec-ch-ua-model': '""',
|
||||
'sec-ch-ua-full-version-list': '"Not(A:Brand";v="99.0.0.0", "Google Chrome";v="133.0.6943.98", "Chromium";v="133.0.6943.98"',
|
||||
'dnt': '1',
|
||||
'upgrade-insecure-requests': '1',
|
||||
'sec-fetch-site': 'none',
|
||||
'sec-fetch-mode': 'navigate',
|
||||
'sec-fetch-user': '?1',
|
||||
'sec-fetch-dest': 'document',
|
||||
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
|
||||
'priority': 'u=0, i'
|
||||
}
|
||||
|
||||
def homeContent(self, filter):
|
||||
result = {}
|
||||
cateManual = {
|
||||
"最新": "/new",
|
||||
"最佳": "/best",
|
||||
"频道": "/channels-index",
|
||||
"标签": "/tags",
|
||||
"明星": "/pornstars-index"
|
||||
}
|
||||
classes = []
|
||||
for k in cateManual:
|
||||
classes.append({
|
||||
'type_name': k,
|
||||
'type_id': cateManual[k]
|
||||
})
|
||||
result['class'] = classes
|
||||
return result
|
||||
|
||||
def homeVideoContent(self):
|
||||
data = self.getpq()
|
||||
return {'list':self.getlist(data(".mozaique .frame-block"))}
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
vdata = []
|
||||
result = {}
|
||||
page = f"/{int(pg) - 1}" if pg != '1' else ''
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 9999
|
||||
result['limit'] = 90
|
||||
result['total'] = 999999
|
||||
if tid=='/new' or 'tags_click' in tid:
|
||||
if 'tags_click' in tid:tid=tid.split('click_')[-1]
|
||||
data=self.getpq(f'{tid}/{pg}')
|
||||
vdata=self.getlist(data(".mozaique .frame-block"))
|
||||
elif tid=='/best':
|
||||
if pg=='1':
|
||||
self.path=self.session.get(f'{self.host}{tid}',headers=self.headers,allow_redirects=False).headers['Location']
|
||||
data=self.getpq(f'{self.path}{page}')
|
||||
vdata=self.getlist(data(".mozaique .frame-block"))
|
||||
elif tid=='/channels-index' or tid=='/pornstars-index':
|
||||
data = self.getpq(f'{tid}{page}')
|
||||
vhtml=data(".mozaique .thumb-block")
|
||||
for i in vhtml.items():
|
||||
a = i('.thumb-inside .thumb a')
|
||||
match = re.search(r'src="([^"]+)"', a('script').text())
|
||||
img=''
|
||||
if match:
|
||||
img = match.group(1).strip()
|
||||
vdata.append({
|
||||
'vod_id': f"channels_click_{'/channels'if tid=='/channels-index' else ''}"+a.attr('href'),
|
||||
'vod_name': a('.profile-name').text() or i('.profile-name').text().replace('\xa0','/'),
|
||||
'vod_pic': img,
|
||||
'vod_tag': 'folder',
|
||||
'vod_remarks': i('.thumb-under .profile-counts').text(),
|
||||
'style': {'ratio': 1.33, 'type': 'rect'}
|
||||
})
|
||||
elif tid=='/tags':
|
||||
result['pagecount'] = pg
|
||||
vhtml = self.getpq(tid)
|
||||
vhtml = vhtml('.tags-list')
|
||||
for d in vhtml.items():
|
||||
for i in d('li a').items():
|
||||
vdata.append({
|
||||
'vod_id': "tags_click_"+i.attr('href'),
|
||||
'vod_name': i.attr('title') or i('b').text(),
|
||||
'vod_pic': '',
|
||||
'vod_tag': 'folder',
|
||||
'vod_remarks': i('.navbadge').text(),
|
||||
'style': {'ratio': 1.33, 'type': 'rect'}
|
||||
})
|
||||
elif 'channels_click' in tid:
|
||||
tid=tid.split('click_')[-1]
|
||||
headers=self.session.headers.copy()
|
||||
headers.update({'Accept': 'application/json, text/javascript, */*; q=0.01'})
|
||||
vhtml=self.post(f'{self.host}{tid}/videos/best/{int(pg)-1}',headers=headers).json()
|
||||
for i in vhtml['videos']:
|
||||
vdata.append({
|
||||
'vod_id': i.get('u'),
|
||||
'vod_name': i.get('tf'),
|
||||
'vod_pic': i.get('il'),
|
||||
'vod_year': i.get('n'),
|
||||
'vod_remarks': i.get('d'),
|
||||
'style': {'ratio': 1.33, 'type': 'rect'}
|
||||
})
|
||||
result['list'] = vdata
|
||||
return result
|
||||
|
||||
def detailContent(self, ids):
|
||||
url = f"{self.host}{ids[0]}"
|
||||
data = self.getpq(ids[0])
|
||||
vn=data('meta[property="og:title"]').attr('content')
|
||||
dtext=data('.main-uploader a')
|
||||
href=dtext.attr('href')
|
||||
pdtitle=''
|
||||
if href and href.count('/') < 2:
|
||||
href=f'/channels{href}'
|
||||
pdtitle = '[a=cr:' + json.dumps({'id': 'channels_click_'+href, 'name': dtext('.name').text()}) + '/]' + dtext('.name').text() + '[/a]'
|
||||
vod = {
|
||||
'vod_name': vn,
|
||||
'vod_director':pdtitle,
|
||||
'vod_remarks': data('.page-title').text().replace(vn,''),
|
||||
'vod_play_from': '老僧酿酒',
|
||||
'vod_play_url': ''
|
||||
}
|
||||
js_content = data("#video-player-bg script")
|
||||
jstr=''
|
||||
for script in js_content.items():
|
||||
content = script.text()
|
||||
if 'setVideoUrlLow' in content and 'html5player' in content:
|
||||
jstr = content
|
||||
break
|
||||
plist = [f"{vn}${self.e64(f'{1}@@@@{url}')}"]
|
||||
def extract_video_urls(js_content):
|
||||
try:
|
||||
low = re.search(r'setVideoUrlLow\([\'"]([^\'"]+)[\'"]\)', js_content)
|
||||
high = re.search(r'setVideoUrlHigh\([\'"]([^\'"]+)[\'"]\)', js_content)
|
||||
hls = re.search(r'setVideoHLS\([\'"]([^\'"]+)[\'"]\)', js_content)
|
||||
|
||||
return {
|
||||
'hls': hls.group(1) if hls else None,
|
||||
'high': high.group(1) if high else None,
|
||||
'low': low.group(1) if low else None
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"提取视频URL失败: {str(e)}")
|
||||
return {}
|
||||
if jstr:
|
||||
try:
|
||||
urls = extract_video_urls(jstr)
|
||||
plist = [
|
||||
f"{quality}${self.e64(f'{0}@@@@{url}')}"
|
||||
for quality, url in urls.items()
|
||||
if url
|
||||
]
|
||||
except Exception as e:
|
||||
print(f"提取url失败: {str(e)}")
|
||||
vod['vod_play_url'] = '#'.join(plist)
|
||||
return {'list':[vod]}
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
data=self.getpq(f'/?k={key}&p={int(pg)-1}')
|
||||
return {'list':self.getlist(data(".mozaique .frame-block")),'page':pg}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5410.0 Safari/537.36',
|
||||
'pragma': 'no-cache',
|
||||
'cache-control': 'no-cache',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
'sec-ch-ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
|
||||
'dnt': '1',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'origin': self.host,
|
||||
'sec-fetch-site': 'cross-site',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'referer': f'{self.host}/',
|
||||
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
|
||||
'priority': 'u=1, i',
|
||||
}
|
||||
ids=self.d64(id).split('@@@@')
|
||||
return {'parse': int(ids[0]), 'url': ids[1], 'header': headers}
|
||||
|
||||
def localProxy(self, param):
|
||||
pass
|
||||
|
||||
def e64(self, text):
|
||||
try:
|
||||
text_bytes = text.encode('utf-8')
|
||||
encoded_bytes = b64encode(text_bytes)
|
||||
return encoded_bytes.decode('utf-8')
|
||||
except Exception as e:
|
||||
print(f"Base64编码错误: {str(e)}")
|
||||
return ""
|
||||
|
||||
def d64(self,encoded_text):
|
||||
try:
|
||||
encoded_bytes = encoded_text.encode('utf-8')
|
||||
decoded_bytes = b64decode(encoded_bytes)
|
||||
return decoded_bytes.decode('utf-8')
|
||||
except Exception as e:
|
||||
print(f"Base64解码错误: {str(e)}")
|
||||
return ""
|
||||
|
||||
def getlist(self, data):
|
||||
vlist=[]
|
||||
for i in data.items():
|
||||
a=i('.thumb-inside .thumb a')
|
||||
b=i('.thumb-under .title a')
|
||||
vlist.append({
|
||||
'vod_id': a.attr('href'),
|
||||
'vod_name': b('a').attr('title'),
|
||||
'vod_pic': a('img').attr('data-src'),
|
||||
'vod_year': a('.video-hd-mark').text(),
|
||||
'vod_remarks': b('.duration').text(),
|
||||
'style': {'ratio': 1.33, 'type': 'rect'}
|
||||
})
|
||||
return vlist
|
||||
|
||||
def getpq(self, path=''):
|
||||
response = self.session.get(f'{self.host}{path}').text
|
||||
try:
|
||||
return pq(response)
|
||||
except Exception as e:
|
||||
print(f"{str(e)}")
|
||||
return pq(response.encode('utf-8'))
|
||||
@@ -0,0 +1,258 @@
|
||||
# coding=utf-8
|
||||
# !/usr/bin/python
|
||||
import sys
|
||||
import base64
|
||||
import hashlib
|
||||
import requests
|
||||
from typing import Tuple
|
||||
from base.spider import Spider
|
||||
from datetime import datetime, timedelta
|
||||
from urllib.parse import quote, unquote
|
||||
from requests.adapters import HTTPAdapter
|
||||
from urllib3.util.retry import Retry
|
||||
sys.path.append('..')
|
||||
|
||||
# 搜索用户名,关键词格式为“类别+空格+关键词”
|
||||
# 类别在标签上已注明,比如“女主播g”,则搜索类别为“g”
|
||||
# 搜索“g per”,则在“女主播”中搜索“per”, 关键词不区分大小写,但至少3位,否则空结果
|
||||
|
||||
class Spider(Spider):
|
||||
|
||||
def init(self, extend="{}"):
|
||||
origin = 'https://zh.stripchat.com'
|
||||
self.host = origin
|
||||
self.headers = {
|
||||
'Origin': origin,
|
||||
'Referer': f"{origin}/",
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:144.0) Gecko/20100101 Firefox/144.0'
|
||||
}
|
||||
self.stripchat_key = self.decode_key_compact()
|
||||
# 缓存字典
|
||||
self._hash_cache = {}
|
||||
self.create_session_with_retry()
|
||||
|
||||
def getName(self):
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
def homeContent(self, filter):
|
||||
result = {}
|
||||
classes = [{'type_name': '女主播g', 'type_id': 'girls'}, {'type_name': '情侣c', 'type_id': 'couples'}, {'type_name': '男主播m', 'type_id': 'men'}, {'type_name': '跨性别t', 'type_id': 'trans'}]
|
||||
filters = {}
|
||||
value = [{'n': '中国', 'v': 'tagLanguageChinese'}, {'n': '亚洲', 'v': 'ethnicityAsian'}, {'n': '白人', 'v': 'ethnicityWhite'}, {'n': '拉丁', 'v': 'ethnicityLatino'}, {'n': '混血', 'v': 'ethnicityMultiracial'}, {'n': '印度', 'v': 'ethnicityIndian'}, {'n': '阿拉伯', 'v': 'ethnicityMiddleEastern'}, {'n': '黑人', 'v': 'ethnicityEbony'}]
|
||||
value_gay = [{'n': '情侣', 'v': 'sexGayCouples'}, {'n': '直男', 'v': 'orientationStraight'}]
|
||||
for tid in ['girls', 'couples', 'men', 'trans']:
|
||||
c_value = value[:]
|
||||
if tid == 'men':
|
||||
c_value += value_gay
|
||||
filters[tid] = [{'key': 'tag', 'value': c_value}]
|
||||
result['class'] = classes
|
||||
result['filters'] = filters
|
||||
return result
|
||||
|
||||
def homeVideoContent(self):
|
||||
pass
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
limit = 60
|
||||
offset = limit * (int(pg) - 1)
|
||||
domain = f"{self.host}/api/front/models?improveTs=false&removeShows=false&limit={limit}&offset={offset}&primaryTag={tid}&sortBy=stripRanking&rcmGrp=A&rbCnGr=true&prxCnGr=false&nic=false"
|
||||
if 'tag' in extend:
|
||||
domain += "&filterGroupTags=%5B%5B%22" + extend['tag'] + "%22%5D%5D"
|
||||
rsp = requests.get(domain, headers=self.headers).json()
|
||||
vodList = rsp['models']
|
||||
videos = []
|
||||
for vod in vodList:
|
||||
id = str(vod['id'])
|
||||
name = str(vod['username']).strip()
|
||||
stamp = vod['snapshotTimestamp']
|
||||
country = str(vod['country']).strip()
|
||||
flag = self.country_code_to_flag(country)
|
||||
remark = "🎫" if vod['status'] == "groupShow" else ""
|
||||
videos.append({
|
||||
"vod_id": name,
|
||||
"vod_name": f"{flag}{name}",
|
||||
"vod_pic": f"https://img.doppiocdn.net/thumbs/{stamp}/{id}",
|
||||
"vod_remarks": remark
|
||||
})
|
||||
total = int(rsp['filteredCount'])
|
||||
result = {}
|
||||
result['list'] = videos
|
||||
result['page'] = pg
|
||||
result['pagecount'] = (total + limit - 1) // limit
|
||||
result['limit'] = limit
|
||||
result['total'] = total
|
||||
return result
|
||||
|
||||
def detailContent(self, array):
|
||||
username = array[0]
|
||||
domain = f"{self.host}/api/front/v2/models/username/{username}/cam"
|
||||
rsp = requests.get(domain, headers=self.headers).json()
|
||||
info = rsp['cam']
|
||||
user = rsp['user']['user']
|
||||
id = str(user['id'])
|
||||
country = str(user['country']).strip()
|
||||
isLive = "" if user['isLive'] else " 已下播"
|
||||
flag = self.country_code_to_flag(country)
|
||||
remark = ''
|
||||
if info['show']:
|
||||
show = info['show']['details']['groupShow']
|
||||
BJtime = (datetime.strptime(show["startAt"], "%Y-%m-%dT%H:%M:%SZ") + timedelta(hours=8)).strftime("%m月%d日 %H:%M")
|
||||
remark = f"🎫 始于 {BJtime}"
|
||||
vod = [{
|
||||
"vod_id": id,
|
||||
"vod_name": str(info['topic']).strip(),
|
||||
"vod_pic": str(user['avatarUrl']),
|
||||
"vod_director": f"{flag}{username}{isLive}",
|
||||
"vod_remarks": remark,
|
||||
'vod_play_from': 'StripChat',
|
||||
'vod_play_url': f"{id}${id}"
|
||||
}]
|
||||
result = {}
|
||||
result['list'] = vod
|
||||
return result
|
||||
|
||||
def process_key(self, key: str) -> Tuple[str, str]:
|
||||
tags = {'G': 'girls', 'C': 'couples', 'M': 'men', 'T': 'trans'}
|
||||
parts = key.split(maxsplit=1) # 仅分割第一个空格
|
||||
if len(parts) > 1 and tags.get(parts[0].upper(), ''):
|
||||
return tags[parts[0].upper()], parts[1].strip()
|
||||
return 'girls', key.strip()
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
result = {}
|
||||
if int(pg) > 1:
|
||||
return result
|
||||
tag, key = self.process_key(key)
|
||||
domain = f"{self.host}/api/front/v4/models/search/group/username?query={key}&limit=900&primaryTag={tag}"
|
||||
rsp = requests.get(domain, headers=self.headers).json()
|
||||
users = rsp['models']
|
||||
videos = []
|
||||
for user in users:
|
||||
if not user['isLive']:
|
||||
continue
|
||||
id = str(user['id'])
|
||||
name = str(user['username']).strip()
|
||||
stamp = user['snapshotTimestamp']
|
||||
country = str(user['country']).strip()
|
||||
flag = self.country_code_to_flag(country)
|
||||
remark = "🎫" if user['status'] == "groupShow" else ""
|
||||
videos.append({
|
||||
"vod_id": name,
|
||||
"vod_name": f"{flag}{name}",
|
||||
"vod_pic": f"https://img.doppiocdn.net/thumbs/{stamp}/{id}",
|
||||
"vod_remarks": remark
|
||||
})
|
||||
result['list'] = videos
|
||||
return result
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
domain = f"https://edge-hls.doppiocdn.net/hls/{id}/master/{id}_auto.m3u8?playlistType=lowLatency"
|
||||
rsp = requests.get(domain, headers=self.headers).text
|
||||
lines = rsp.strip().split('\n')
|
||||
psch = ''
|
||||
pkey = ''
|
||||
url = []
|
||||
for i, line in enumerate(lines):
|
||||
if line.startswith('#EXT-X-MOUFLON:'):
|
||||
parts = line.split(':')
|
||||
if len(parts) >= 4:
|
||||
psch = parts[2]
|
||||
pkey = parts[3]
|
||||
if '#EXT-X-STREAM-INF' in line:
|
||||
name_start = line.find('NAME="') + 6
|
||||
name_end = line.find('"', name_start)
|
||||
qn = line[name_start:name_end]
|
||||
# URL在下一行
|
||||
url_base = lines[i + 1]
|
||||
# 组合最终的URL,并加上psch和pkey参数
|
||||
full_url = f"{url_base}&psch={psch}&pkey={pkey}"
|
||||
proxy_url = f"{self.getProxyUrl()}&url={quote(full_url)}"
|
||||
# 将画质和URL添加到列表中
|
||||
url.append(qn)
|
||||
url.append(proxy_url)
|
||||
result = {}
|
||||
result["url"] = url
|
||||
result["parse"] = '0'
|
||||
result["contentType"] = ''
|
||||
result["header"] = self.headers
|
||||
return result
|
||||
|
||||
def localProxy(self, param):
|
||||
url = unquote(param['url'])
|
||||
data = self.session.get(url, headers=self.headers, timeout=10)
|
||||
if data.status_code != 200:
|
||||
return [404, "text/plain", ""]
|
||||
data = data.text
|
||||
if "#EXT-X-MOUFLON:FILE" in data:
|
||||
data = self.process_m3u8_content_v2(data)
|
||||
return [200, "application/vnd.apple.mpegur", data]
|
||||
|
||||
def process_m3u8_content_v2(self, m3u8_content):
|
||||
lines = m3u8_content.strip().split('\n')
|
||||
for i, line in enumerate(lines):
|
||||
if (line.startswith('#EXT-X-MOUFLON:FILE:') and 'media.mp4' in lines[i + 1]):
|
||||
encrypted_data = line.split(':', 2)[2].strip()
|
||||
try:
|
||||
decrypted_data = self.decrypt(encrypted_data, self.stripchat_key)
|
||||
except Exception as e:
|
||||
decrypted_data = self.decrypt(encrypted_data, "Zokee2OhPh9kugh4")
|
||||
lines[i + 1] = lines[i + 1].replace('media.mp4', decrypted_data)
|
||||
return '\n'.join(lines)
|
||||
|
||||
def country_code_to_flag(self, country_code):
|
||||
if len(country_code) != 2 or not country_code.isalpha():
|
||||
return country_code
|
||||
flag_emoji = ''.join([chr(ord(c.upper()) - ord('A') + 0x1F1E6) for c in country_code])
|
||||
return flag_emoji
|
||||
|
||||
def decode_key_compact(self):
|
||||
base64_str = "NTEgNzUgNjUgNjEgNmUgMzQgNjMgNjEgNjkgMzkgNjIgNmYgNGEgNjEgMzUgNjE="
|
||||
decoded = base64.b64decode(base64_str).decode('utf-8')
|
||||
key_bytes = bytes(int(hex_str, 16) for hex_str in decoded.split(" "))
|
||||
return key_bytes.decode('utf-8')
|
||||
|
||||
def compute_hash(self, key: str) -> bytes:
|
||||
"""计算并缓存SHA-256哈希"""
|
||||
if key not in self._hash_cache:
|
||||
sha256 = hashlib.sha256()
|
||||
sha256.update(key.encode('utf-8'))
|
||||
self._hash_cache[key] = sha256.digest()
|
||||
return self._hash_cache[key]
|
||||
|
||||
def decrypt(self, encrypted_b64: str, key: str) -> str:
|
||||
"""解密Base64编码的密文"""
|
||||
# 修复Base64填充
|
||||
padding = len(encrypted_b64) % 4
|
||||
if padding:
|
||||
encrypted_b64 += '=' * (4 - padding)
|
||||
|
||||
# 计算哈希并解密
|
||||
hash_bytes = self.compute_hash(key)
|
||||
encrypted_data = base64.b64decode(encrypted_b64)
|
||||
|
||||
# 异或解密
|
||||
decrypted_bytes = bytearray()
|
||||
for i, cipher_byte in enumerate(encrypted_data):
|
||||
key_byte = hash_bytes[i % len(hash_bytes)]
|
||||
decrypted_bytes.append(cipher_byte ^ key_byte)
|
||||
return decrypted_bytes.decode('utf-8')
|
||||
|
||||
def create_session_with_retry(self, retries=3, backoff_factor=0.3):
|
||||
self.session = requests.Session()
|
||||
retry_strategy = Retry(
|
||||
total=retries,
|
||||
backoff_factor=backoff_factor,
|
||||
status_forcelist=[429, 500, 502, 503, 504] # 需要重试的状态码
|
||||
)
|
||||
adapter = HTTPAdapter(max_retries=retry_strategy)
|
||||
self.session.mount("http://", adapter)
|
||||
self.session.mount("https://", adapter)
|
||||
+2
-2
@@ -8,7 +8,7 @@ from base.spider import Spider as BaseSpider
|
||||
|
||||
class Spider(BaseSpider):
|
||||
def init(self, extend=""):
|
||||
self.host = "https://www.ht10010.com"
|
||||
self.host = "https://maihaolian.com"
|
||||
self.headers = {
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||
@@ -23,11 +23,11 @@ class Spider(BaseSpider):
|
||||
{'type_id': "/label/qq", 'type_name': "腾讯VIP精选"},
|
||||
{'type_id': "/label/bli", 'type_name': "B站VIP精选"},
|
||||
{'type_id': "/label/youku", 'type_name': "优酷VIP精选"},
|
||||
{"type_id": "5", "type_name": "红果短剧"},
|
||||
{"type_id": "2", "type_name": "电视剧"},
|
||||
{"type_id": "1", "type_name": "电影"},
|
||||
{"type_id": "4", "type_name": "动漫"},
|
||||
{"type_id": "3", "type_name": "综艺"},
|
||||
{"type_id": "5", "type_name": "热门短剧"},
|
||||
], "filters": self._build_filters()}
|
||||
|
||||
def _build_filters(self):
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# by @嗷呜
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
import requests
|
||||
from base64 import b64decode, b64encode
|
||||
from Crypto.Hash import MD5
|
||||
from pyquery import PyQuery as pq
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
|
||||
class Spider(Spider):
|
||||
|
||||
def init(self, extend=""):
|
||||
pass
|
||||
|
||||
def getName(self):
|
||||
pass
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
host='http://v.rbotv.cn'
|
||||
|
||||
headers = {
|
||||
'User-Agent': 'okhttp-okgo/jeasonlzy',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.8'
|
||||
}
|
||||
|
||||
def homeContent(self, filter):
|
||||
data=requests.post(f'{self.host}/v3/type/top_type',headers=self.headers,files=self.getfiles({'': (None, '')})).json()
|
||||
result = {}
|
||||
classes = []
|
||||
filters = {}
|
||||
for k in data['data']['list']:
|
||||
classes.append({
|
||||
'type_name': k['type_name'],
|
||||
'type_id': k['type_id']
|
||||
})
|
||||
fts = []
|
||||
for i,x in k.items():
|
||||
if isinstance(x, list) and len(x)>2:
|
||||
fts.append({
|
||||
'name': i,
|
||||
'key': i,
|
||||
'value': [{'n': j, 'v': j} for j in x if j and j!= '全部']
|
||||
})
|
||||
if len(fts):filters[k['type_id']] = fts
|
||||
result['class'] = classes
|
||||
result['filters'] = filters
|
||||
return result
|
||||
|
||||
def homeVideoContent(self):
|
||||
data=requests.post(f'{self.host}/v3/type/tj_vod',headers=self.headers,files=self.getfiles({'': (None, '')})).json()
|
||||
return {'list':self.getv(data['data']['cai']+data['data']['loop'])}
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
files = {
|
||||
'type_id': (None, tid),
|
||||
'limit': (None, '12'),
|
||||
'page': (None, pg)
|
||||
}
|
||||
for k,v in extend.items():
|
||||
if k=='extend':k='class'
|
||||
files[k] = (None, v)
|
||||
data=requests.post(f'{self.host}/v3/home/type_search',headers=self.headers,files=self.getfiles(files)).json()
|
||||
result = {}
|
||||
result['list'] = self.getv(data['data']['list'])
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 9999
|
||||
result['limit'] = 90
|
||||
result['total'] = 999999
|
||||
return result
|
||||
|
||||
def detailContent(self, ids):
|
||||
data=requests.post(f'{self.host}/v3/home/vod_details',headers=self.headers,files=self.getfiles({'vod_id': (None, ids[0])})).json()
|
||||
v=data['data']
|
||||
vod = {
|
||||
'vod_name': v.get('vod_name'),
|
||||
'type_name': v.get('type_name'),
|
||||
'vod_year': v.get('vod_year'),
|
||||
'vod_area': v.get('vod_area'),
|
||||
'vod_remarks': v.get('vod_remarks'),
|
||||
'vod_actor': v.get('vod_actor'),
|
||||
'vod_director': v.get('vod_director'),
|
||||
'vod_content': pq(pq(v.get('vod_content','无') or '无').text()).text()
|
||||
}
|
||||
n,p=[],[]
|
||||
for o,i in enumerate(v['vod_play_list']):
|
||||
n.append(f"线路{o+1}({i.get('flag')})")
|
||||
c=[]
|
||||
for j in i.get('urls'):
|
||||
d={'url':j.get('url'),'p':i.get('parse_urls'),'r':i.get('referer'),'u':i.get('ua')}
|
||||
c.append(f"{j.get('name')}${self.e64(json.dumps(d))}")
|
||||
p.append('#'.join(c))
|
||||
vod.update({'vod_play_from':'$$$'.join(n),'vod_play_url':'$$$'.join(p)})
|
||||
return {'list':[vod]}
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
files = {
|
||||
'limit': (None, '12'),
|
||||
'page': (None, pg),
|
||||
'keyword': (None, key),
|
||||
}
|
||||
data=requests.post(f'{self.host}/v3/home/search',headers=self.headers,files=self.getfiles(files)).json()
|
||||
return {'list':self.getv(data['data']['list']),'page':pg}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
ids=json.loads(self.d64(id))
|
||||
url=ids['url']
|
||||
if isinstance(ids['p'],list) and len(ids['p']):
|
||||
url=[]
|
||||
for i,x in enumerate(ids['p']):
|
||||
up={'url':ids['url'],'p':x,'r':ids['r'],'u':ids['u']}
|
||||
url.extend([f"解析{i+1}",f"{self.getProxyUrl()}&data={self.e64(json.dumps(up))}"])
|
||||
h={}
|
||||
if ids.get('r'):
|
||||
h['Referer'] = ids['r']
|
||||
if ids.get('u'):
|
||||
h['User-Agent'] = ids['u']
|
||||
return {'parse': 0, 'url': url, 'header': h}
|
||||
|
||||
def localProxy(self, param):
|
||||
data=json.loads(self.d64(param['data']))
|
||||
h = {}
|
||||
if data.get('r'):
|
||||
h['Referer'] = data['r']
|
||||
if data.get('u'):
|
||||
h['User-Agent'] = data['u']
|
||||
res=self.fetch(f"{data['p']}{data['url']}",headers=h).json()
|
||||
url=res.get('url') or res['data'].get('url')
|
||||
return [302,'video/MP2T',None,{'Location':url}]
|
||||
|
||||
def liveContent(self, url):
|
||||
pass
|
||||
|
||||
def getfiles(self, p=None):
|
||||
if p is None:p = {}
|
||||
t=str(int(time.time()))
|
||||
h = MD5.new()
|
||||
h.update(f"7gp0bnd2sr85ydii2j32pcypscoc4w6c7g5spl{t}".encode('utf-8'))
|
||||
s = h.hexdigest()
|
||||
files = {
|
||||
'sign': (None, s),
|
||||
'timestamp': (None, t)
|
||||
}
|
||||
p.update(files)
|
||||
return p
|
||||
|
||||
def getv(self,data):
|
||||
videos = []
|
||||
for i in data:
|
||||
if i.get('vod_id') and str(i['vod_id']) != '0':
|
||||
videos.append({
|
||||
'vod_id': i['vod_id'],
|
||||
'vod_name': i.get('vod_name'),
|
||||
'vod_pic': i.get('vod_pic') or i.get('vod_pic_thumb'),
|
||||
'vod_year': i.get('tag'),
|
||||
'vod_remarks': i.get('vod_remarks')
|
||||
})
|
||||
return videos
|
||||
|
||||
def e64(self, text):
|
||||
try:
|
||||
text_bytes = text.encode('utf-8')
|
||||
encoded_bytes = b64encode(text_bytes)
|
||||
return encoded_bytes.decode('utf-8')
|
||||
except Exception as e:
|
||||
return ""
|
||||
|
||||
def d64(self,encoded_text):
|
||||
try:
|
||||
encoded_bytes = encoded_text.encode('utf-8')
|
||||
decoded_bytes = b64decode(encoded_bytes)
|
||||
return decoded_bytes.decode('utf-8')
|
||||
except Exception as e:
|
||||
return ""
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
{
|
||||
"spider": "./tvbox.jar",
|
||||
"logo": "https://img.freepik.com/free-vector/cute-dolphin-swimming-cartoon-vector-icon-illustration-animal-nature-icon-isolated-flat-vector_138676-12582.jpg?semt=ais_hybrid&w=740&q=80",
|
||||
@@ -82,6 +83,12 @@
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/枫叶影院.py"
|
||||
},
|
||||
{
|
||||
"key": "rb",
|
||||
"name": "🐬热播APP.py",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/热播APP.py"
|
||||
},
|
||||
{
|
||||
"key": "kf",
|
||||
"name": "🐬咖啡体育直播.py",
|
||||
@@ -393,6 +400,12 @@
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/色播聚合.py"
|
||||
},
|
||||
{
|
||||
"key": "stripchat",
|
||||
"name": "🐬stripchat直播.py|🔞",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/stripchat.py"
|
||||
},
|
||||
{
|
||||
"key": "007qg",
|
||||
"name": "🐬007吃瓜.py|🔞",
|
||||
@@ -417,6 +430,18 @@
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/51爆料.py"
|
||||
},
|
||||
{
|
||||
"key": "91bl",
|
||||
"name": "🐬91爆料.py|🔞",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/91爆料.py"
|
||||
},
|
||||
{
|
||||
"key": "91qgzx",
|
||||
"name": "🐬91吃瓜中心.py|🔞",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/91吃瓜中心.py"
|
||||
},
|
||||
{
|
||||
"key": "scpd",
|
||||
"name": "🐬香肠派对.py|🔞",
|
||||
@@ -435,6 +460,12 @@
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/123AV.py"
|
||||
},
|
||||
{
|
||||
"key": "Xvideos",
|
||||
"name": "🐬Xvideos.py|🔞",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/Xvideos.py"
|
||||
},
|
||||
{
|
||||
"key": "JAV36",
|
||||
"name": "🐬JAV36.py|🔞",
|
||||
|
||||
@@ -75,6 +75,12 @@
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/枫叶影院.py"
|
||||
},
|
||||
{
|
||||
"key": "rb",
|
||||
"name": "🐬热播APP.py",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/热播APP.py"
|
||||
},
|
||||
{
|
||||
"key": "kf",
|
||||
"name": "🐬咖啡体育直播.py",
|
||||
|
||||
+164
-145
@@ -12,33 +12,33 @@
|
||||
},
|
||||
{
|
||||
"key": "Nostr",
|
||||
"name": "🐬Nostr推荐",
|
||||
"name": "🐬Nostr推荐[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Nostr",
|
||||
"homePage": "https://www.252035.xyz/xs/tvbox/nostr.html"
|
||||
},
|
||||
{
|
||||
"key":"AQY",
|
||||
"name":"🐬爱奇艺 海豚影视完全免费,如有收费的都是骗子",
|
||||
"name":"🐬爱奇艺 海豚影视完全免费,如有收费的都是骗子[追剧]",
|
||||
"type":3,
|
||||
"api":"https://file.icve.com.cn/file_doc/249/899/3E7E0C8A023B624CEC6BDCC200F06F02.js",
|
||||
"ext":"https://cdn.waimaimingtang.com/file/images/bwc/20251023002031-6064033c16.js"
|
||||
},
|
||||
{"key":"YK",
|
||||
"name":"🐬优酷视频 海豚影视交流群 TG:@hshsjk9",
|
||||
"name":"🐬优酷视频 海豚影视交流群 TG:@hshsjk9[追剧]",
|
||||
"type":3,
|
||||
"api":"https://file.icve.com.cn/file_doc/249/899/3E7E0C8A023B624CEC6BDCC200F06F02.js",
|
||||
"ext":"https://cdn.waimaimingtang.com/file/images/bwc/20251023002200-507c3e8aae.js"
|
||||
},
|
||||
{"key":"TX",
|
||||
"name":"🐬腾讯视频",
|
||||
"name":"🐬腾讯视频[追剧]",
|
||||
"type":3,
|
||||
"api":"https://file.icve.com.cn/file_doc/249/899/3E7E0C8A023B624CEC6BDCC200F06F02.js",
|
||||
"ext":"https://cdn.waimaimingtang.com/file/images/bwc/20251023002144-0e40887294.js"
|
||||
},
|
||||
{
|
||||
"key": "hajim-腾讯备",
|
||||
"name": "🐬腾讯4K",
|
||||
"name": "🐬腾讯4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/IY-CPU/IY/main/lib/drpy2.min.js",
|
||||
"searchable": 1,
|
||||
@@ -46,14 +46,14 @@
|
||||
"ext": "https://fastlink.cokey.xyz/f/1MOEc5/%E8%85%BE%E8%85%BE.js"
|
||||
},
|
||||
{"key":"MG",
|
||||
"name":"🐬芒果TV",
|
||||
"name":"🐬芒果TV[追剧]",
|
||||
"type":3,
|
||||
"api":"https://file.icve.com.cn/file_doc/249/899/3E7E0C8A023B624CEC6BDCC200F06F02.js",
|
||||
"ext":"https://cdn.waimaimingtang.com/file/images/bwc/20251023002108-a4795930ec.js"
|
||||
},
|
||||
{
|
||||
"key": "茫茫",
|
||||
"name": "🐬芒果4K",
|
||||
"name": "🐬芒果4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/IY-CPU/IY/main/lib/drpy2.min.js",
|
||||
"ext": "https://ghfast.top/https://raw.githubusercontent.com/IY-CPU/IY/main/lib/茫茫.png"
|
||||
@@ -97,83 +97,89 @@
|
||||
|
||||
{
|
||||
"key": "ppx",
|
||||
"name": "🐬皮皮虾.py",
|
||||
"name": "🐬皮皮虾.py[追剧]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/皮皮虾.py",
|
||||
"ext": "http://43.248.117.123:4680"
|
||||
},
|
||||
{
|
||||
"key": "rb",
|
||||
"name": "🐬热播APP.py[追剧]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/热播APP.py"
|
||||
},
|
||||
{
|
||||
"key": "fY",
|
||||
"name": "🐬枫叶影院.py(关梯子使用)",
|
||||
"name": "🐬枫叶影院.py(关梯子使用)[追剧]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/枫叶影院.py"
|
||||
},
|
||||
{
|
||||
"key":"FY",
|
||||
"name":"🐬枫叶影院(关梯子使用)",
|
||||
"name":"🐬枫叶影院(关梯子使用)[追剧]",
|
||||
"type":3,
|
||||
"api":"csp_fy",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/枫叶🍁.html"
|
||||
},
|
||||
{
|
||||
"key":"6v",
|
||||
"name":"🐬6V影视",
|
||||
"name":"🐬6V影视[追剧]",
|
||||
"type":3,
|
||||
"api":"csp_6v",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/6v.html"
|
||||
},
|
||||
{
|
||||
"key":"CZ",
|
||||
"name":"🐬厂长资源(关梯子使用)",
|
||||
"name":"🐬厂长资源(关梯子使用)[追剧]",
|
||||
"type":3,
|
||||
"api":"csp_czjy",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/厂长.html"
|
||||
},
|
||||
{
|
||||
"key":"WB",
|
||||
"name":"🐬歪比巴卜影视",
|
||||
"name":"🐬歪比巴卜影视[追剧]",
|
||||
"type":3,
|
||||
"api":"csp_wbbb",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/歪比巴卜.html"
|
||||
},
|
||||
{
|
||||
"key":"PTT",
|
||||
"name":"🐬PTT视频",
|
||||
"name":"🐬PTT视频[追剧]",
|
||||
"type":3,
|
||||
"api":"csp_ptt",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/ptt.html"
|
||||
},
|
||||
{
|
||||
"key":"LIBVIO",
|
||||
"name":"🐬LIBVIO影视",
|
||||
"name":"🐬LIBVIO影视[追剧]",
|
||||
"type":3,
|
||||
"api":"csp_libvio",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/libvio.html"
|
||||
},
|
||||
{
|
||||
"key":"PPN",
|
||||
"name":"🐬ppnix影视",
|
||||
"name":"🐬ppnix影视[追剧]",
|
||||
"type":3,
|
||||
"api":"csp_ppnix",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/ppnix.html"
|
||||
},
|
||||
{
|
||||
"key":"360JH",
|
||||
"name":"🐬360影视(关梯子使用)",
|
||||
"name":"🐬360影视(关梯子使用)[追剧]",
|
||||
"type":3,
|
||||
"api":"csp_360jh",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/360聚合.html"
|
||||
},
|
||||
{
|
||||
"key":"WOJH",
|
||||
"name":"🐬玩偶聚合(关梯子使用)",
|
||||
"name":"🐬玩偶聚合(关梯子使用)[追剧]",
|
||||
"type":3,
|
||||
"api":"csp_wojh",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/玩偶聚合.html"
|
||||
},
|
||||
{
|
||||
"key":"GY",
|
||||
"name":"🐬观影(关梯子使用)",
|
||||
"name":"🐬观影(关梯子使用)[追剧]",
|
||||
"type":3,
|
||||
"api":"csp_gy",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/观影.html"
|
||||
@@ -198,7 +204,7 @@
|
||||
},
|
||||
{
|
||||
"key": "华人so",
|
||||
"name": "🐬华人影视",
|
||||
"name": "🐬华人影视[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Hua",
|
||||
"jar": "https://files.catbox.moe/hmml4f.txt",
|
||||
@@ -207,14 +213,14 @@
|
||||
"filterable": 1
|
||||
|
||||
},
|
||||
{"key": "aidan", "name": "🐬艾旦影视(聚)(有三级片)🔞", "type": 1, "api": "https://lovedan.net/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "ikun", "name": "🐬爱坤┃影视(有三级片)", "type": 1, "api": "https://ikunzyapi.com/api.php/provide/vod/from/ikm3u8/at/json", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "U酷資源", "name": "🐬U酷資源(有三级片)", "type": 1, "api": "https://api.ukuapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "虎牙资源", "name": "🐬虎牙资源(有三级片)", "type": 1, "api": "https://www.huyaapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "ttzy", "name": "🐬天天┃影视(有三级片)🔞", "type": 1, "api": "https://api.1080zyku.com/inc/apijson.php", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "aidan", "name": "🐬艾旦影视(聚)(有三级片)🔞[追剧]", "type": 1, "api": "https://lovedan.net/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "ikun", "name": "🐬爱坤┃影视(有三级片)[追剧]", "type": 1, "api": "https://ikunzyapi.com/api.php/provide/vod/from/ikm3u8/at/json", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "U酷資源", "name": "🐬U酷資源(有三级片)[追剧]", "type": 1, "api": "https://api.ukuapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "虎牙资源", "name": "🐬虎牙资源(有三级片)[追剧]", "type": 1, "api": "https://www.huyaapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "ttzy", "name": "🐬天天┃影视(有三级片)🔞[追剧]", "type": 1, "api": "https://api.1080zyku.com/inc/apijson.php", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{
|
||||
"key": "非凡",
|
||||
"name": "🐬非凡影视",
|
||||
"name": "🐬非凡影视[追剧]",
|
||||
"type": 1,
|
||||
"api": "http://cj.ffzyapi.com/api.php/provide/vod/",
|
||||
"searchable": 1,
|
||||
@@ -251,9 +257,9 @@
|
||||
"海外动漫"
|
||||
]
|
||||
},
|
||||
{
|
||||
{
|
||||
"key": "天涯资源",
|
||||
"name": "🐬天涯资源(有三级片)",
|
||||
"name": "🐬天涯资源(有三级片)[追剧]",
|
||||
"type": 0,
|
||||
"api": "https://tyyszyapi.com/api.php/provide/vod/at/xml/?ac=list",
|
||||
"searchable": 1,
|
||||
@@ -261,7 +267,7 @@
|
||||
},
|
||||
{
|
||||
"key": "iKun资源",
|
||||
"name": "🐬iKun资源(有三级片)",
|
||||
"name": "🐬iKun资源(有三级片)[追剧]",
|
||||
"type": 0,
|
||||
"api": "https://ikunzyapi.com/api.php/provide/vod/at/xml",
|
||||
"searchable": 1,
|
||||
@@ -269,7 +275,7 @@
|
||||
},
|
||||
{
|
||||
"key": "闪电影视",
|
||||
"name": "🐬闪电影视|追剧",
|
||||
"name": "🐬闪电影视[追剧]",
|
||||
"type": 1,
|
||||
"api": "http://sdzyapi.com/api.php/provide/vod/",
|
||||
"searchable": 1,
|
||||
@@ -308,7 +314,7 @@
|
||||
},
|
||||
{
|
||||
"key": "牛牛影视",
|
||||
"name": "🐬牛牛影视|追剧",
|
||||
"name": "🐬牛牛影视[追剧]",
|
||||
"type": 0,
|
||||
"api": "https://api.niuniuzy.me/api.php/provide/vod/at/xml",
|
||||
"searchable": 1,
|
||||
@@ -359,7 +365,7 @@
|
||||
},
|
||||
{
|
||||
"key": "雲飛影视",
|
||||
"name": "🐬雲飛影视|追剧",
|
||||
"name": "🐬雲飛影视[追剧]",
|
||||
"type": 1,
|
||||
"api": "http://cj.lziapi.com/api.php/provide/vod/",
|
||||
"searchable": 1,
|
||||
@@ -383,11 +389,11 @@
|
||||
"喜剧片"
|
||||
]
|
||||
},
|
||||
{"key": "火狐","name": "🐬火狐影视🦊|追剧","type": 1,"api": "https://hhzyapi.com/api.php/provide/vod/","searchable": 1,"quickSearch": 0,"filterable": 1,"categories": [ "内地剧", "动作片", "科幻片", "战争片", "喜剧片", "爱情片", "恐怖片", "犯罪片", "剧情片", "冒险片", "记录片", "韩剧", "香港剧", "台湾剧", "欧美剧", "日剧", "马泰剧", "体育赛事", "综艺", "动画片", "中国动漫", "日本动漫", "欧美动漫"]
|
||||
{"key": "火狐","name": "🐬火狐影视🦊[追剧]","type": 1,"api": "https://hhzyapi.com/api.php/provide/vod/","searchable": 1,"quickSearch": 0,"filterable": 1,"categories": [ "内地剧", "动作片", "科幻片", "战争片", "喜剧片", "爱情片", "恐怖片", "犯罪片", "剧情片", "冒险片", "记录片", "韩剧", "香港剧", "台湾剧", "欧美剧", "日剧", "马泰剧", "体育赛事", "综艺", "动画片", "中国动漫", "日本动漫", "欧美动漫"]
|
||||
},
|
||||
{
|
||||
"key": "量子2k",
|
||||
"name": "🐬量子影视|追剧",
|
||||
"name": "🐬量子影视[追剧]",
|
||||
"type": 1,
|
||||
"api": "http://cj.lziapi.com/api.php/provide/vod/",
|
||||
"searchable": 1,
|
||||
@@ -413,7 +419,7 @@
|
||||
},
|
||||
{
|
||||
"key": "API_如意",
|
||||
"name": "🐬如意影视|追剧",
|
||||
"name": "🐬如意影视[追剧]",
|
||||
"type": 1,
|
||||
"api": "https://cj.rycjapi.com/api.php/provide/vod",
|
||||
"ext": "",
|
||||
@@ -459,7 +465,7 @@
|
||||
},
|
||||
{
|
||||
"key": "cj_360资源",
|
||||
"name": "🐬360丨短剧",
|
||||
"name": "🐬360[短剧]",
|
||||
"type": 1,
|
||||
"searchable": 0,
|
||||
"quickSearch": 1,
|
||||
@@ -478,13 +484,13 @@
|
||||
},
|
||||
{
|
||||
"key": "smdj",
|
||||
"name": "🐬星芽短剧.py",
|
||||
"name": "🐬星芽短剧.py[短剧]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/星芽短剧.py"
|
||||
},
|
||||
{
|
||||
"key": "hmjc",
|
||||
"name": "🐬河马剧场.py",
|
||||
"name": "🐬河马剧场.py[短剧]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/河马剧场.py"
|
||||
},
|
||||
@@ -502,101 +508,125 @@
|
||||
},
|
||||
{
|
||||
"key": "shjb",
|
||||
"name": "🐬色播聚合.py|🔞",
|
||||
"name": "🐬色播聚合.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/色播聚合.py"
|
||||
},
|
||||
{
|
||||
"key": "stripchat",
|
||||
"name": "🐬stripchat直播.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/stripchat.py"
|
||||
},
|
||||
{
|
||||
"key": "007qg",
|
||||
"name": "🐬007吃瓜.py|🔞",
|
||||
"name": "🐬007吃瓜.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/007吃瓜.py"
|
||||
},
|
||||
{
|
||||
"key": "51qg",
|
||||
"name": "🐬51吃瓜.py|🔞",
|
||||
"name": "🐬51吃瓜.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/51吃瓜.py"
|
||||
},
|
||||
{
|
||||
"key": "51dc",
|
||||
"name": "🐬51大赛.py|🔞",
|
||||
"name": "🐬51大赛.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/51大赛.py"
|
||||
},
|
||||
{
|
||||
"key": "51bl",
|
||||
"name": "🐬51爆料.py|🔞",
|
||||
"name": "🐬51爆料.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/51爆料.py"
|
||||
},
|
||||
{
|
||||
"key": "91bl",
|
||||
"name": "🐬91爆料.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/91爆料.py"
|
||||
},
|
||||
{
|
||||
"key": "91qgzx",
|
||||
"name": "🐬91吃瓜中心.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/91吃瓜中心.py"
|
||||
},
|
||||
{
|
||||
"key": "scpd",
|
||||
"name": "🐬香肠派对.py|🔞",
|
||||
"name": "🐬香肠派对.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/香肠派对.py"
|
||||
},
|
||||
{
|
||||
"key": "llav",
|
||||
"name": "🐬萝莉AV.py|🔞",
|
||||
"name": "🐬萝莉AV.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/萝莉AV.py"
|
||||
},
|
||||
{
|
||||
"key": "123av",
|
||||
"name": "🐬123AV.py|🔞",
|
||||
"name": "🐬123AV.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/123AV.py"
|
||||
},
|
||||
{
|
||||
"key": "Xvideos",
|
||||
"name": "🐬Xvideos.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/Xvideos.py"
|
||||
},
|
||||
{
|
||||
"key": "JAV36",
|
||||
"name": "🐬JAV36.py|🔞",
|
||||
"name": "🐬JAV36.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/JAV36.py"
|
||||
},
|
||||
{
|
||||
"key": "ggsp",
|
||||
"name": "🐬久久視頻.py|🔞",
|
||||
"name": "🐬久久視頻.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/久久視頻.py"
|
||||
},
|
||||
{
|
||||
"key": "TOPTV",
|
||||
"name": "🐬TOPTV.py|🔞",
|
||||
"name": "🐬TOPTV.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/TOPTV.py"
|
||||
},
|
||||
{
|
||||
"key": "VHUB",
|
||||
"name": "🐬VHUB.py|🔞",
|
||||
"name": "🐬VHUB.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/VHUB[成人].py"
|
||||
},
|
||||
{
|
||||
"key": "MD",
|
||||
"name": "🐬麻豆免费在线播放.py|🔞",
|
||||
"name": "🐬麻豆免费在线播放.py|🔞[成人]",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/麻豆免费在线播放.py"
|
||||
},
|
||||
{"key": "slyzy", "name": "🐬湿乐园|🔞", "type": 1, "api": "https://xxavs.com/api.php/provide/vod", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "nxxzy", "name": "🐬奶香香|🔞", "type": 1, "api": "https://naixxzy.com/api.php/provide/vod", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "无尽资源", "name": "🐬无尽资源|🔞", "type": 1, "api": "https://api.wujinapi.net/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "玉兔资源", "name": "🐬玉兔資源|🔞", "type": 1, "api": "https://apiyutu.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "精品资源", "name": "🐬精品資源|🔞", "type": 1, "api": "https://www.jingpinx.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "夜色资源", "name": "🐬越南資源|🔞", "type": 1, "api": "https://www.vnzyz.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "辣椒資源", "name": "🐬辣椒資源|🔞", "type": 1, "api": "http://apilj.com/api.php/provide/vod/at/json/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "鯊魚資源", "name": "🐬鯊魚資源|🔞", "type": 1, "api": "https://shayuapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "155資源", "name": "🐬155資源|🔞", "type": 1, "api": "https://155api.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 0},
|
||||
{"key": "滴滴资源", "name": "🐬滴滴资源|🔞", "type": 1, "api": "https://api.ddapi.cc/api.php/provide/vod/at/json", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "蕃茄", "name": "🐬18+蕃茄|🔞", "type": 1, "api": "https://fqzy.me//api.php/provide/vod/", "searchable": 1, "quickSearch": 0, "filterable": 1},
|
||||
{"key": "红桃🍑", "name": "🐬红桃视频🍑|🔞", "type": 1, "api": "https://apidanaizi.com/api.php/provide/vod/?ac=list", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "jkun资源", "name": "🐬jkun资源|🔞", "type": 1, "api": "https://jkunzyapi.com/api.php/provide/vod", "searchable": 1, "quickSearch": 1, "filterable": 0},
|
||||
{"key": "精品X资源", "name": "🐬精品X资源|🔞", "type": 1, "api": "https://www.jingpinx.com/api.php/provide/vod", "searchable": 1, "quickSearch": 1, "filterable": 0},
|
||||
{"key": "CK资源", "name": "🐬CK资源|🔞", "type": 1, "api": "https://ckzy.me/api.php/provide/vod", "searchable": 1, "quickSearch": 1, "filterable": 0},
|
||||
{"key": "🔞七天资源🌈", "name": "🐬七天资源🌈|🔞", "type": 1, "api": "https://8day.icu/api.php/provide/vod/at/json", "searchable": 1, "quickSearch": 1, "filterable": 0},
|
||||
{"key": "slyzy", "name": "🐬湿乐园|🔞[成人]", "type": 1, "api": "https://xxavs.com/api.php/provide/vod", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "nxxzy", "name": "🐬奶香香|🔞[成人]", "type": 1, "api": "https://naixxzy.com/api.php/provide/vod", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "无尽资源", "name": "🐬无尽资源|🔞[成人]", "type": 1, "api": "https://api.wujinapi.net/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "玉兔资源", "name": "🐬玉兔資源|🔞[成人]", "type": 1, "api": "https://apiyutu.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "精品资源", "name": "🐬精品資源|🔞[成人]", "type": 1, "api": "https://www.jingpinx.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "夜色资源", "name": "🐬越南資源|🔞[成人]", "type": 1, "api": "https://www.vnzyz.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "辣椒資源", "name": "🐬辣椒資源|🔞[成人]", "type": 1, "api": "http://apilj.com/api.php/provide/vod/at/json/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "鯊魚資源", "name": "🐬鯊魚資源|🔞[成人]", "type": 1, "api": "https://shayuapi.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "155資源", "name": "🐬155資源|🔞[成人]", "type": 1, "api": "https://155api.com/api.php/provide/vod/", "searchable": 1, "quickSearch": 1, "filterable": 0},
|
||||
{"key": "滴滴资源", "name": "🐬滴滴资源|🔞[成人]", "type": 1, "api": "https://api.ddapi.cc/api.php/provide/vod/at/json", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "蕃茄", "name": "🐬18+蕃茄|🔞[成人]", "type": 1, "api": "https://fqzy.me//api.php/provide/vod/", "searchable": 1, "quickSearch": 0, "filterable": 1},
|
||||
{"key": "红桃🍑", "name": "🐬红桃视频🍑|🔞[成人]", "type": 1, "api": "https://apidanaizi.com/api.php/provide/vod/?ac=list", "searchable": 1, "quickSearch": 1, "filterable": 1},
|
||||
{"key": "jkun资源", "name": "🐬jkun资源|🔞[成人]", "type": 1, "api": "https://jkunzyapi.com/api.php/provide/vod", "searchable": 1, "quickSearch": 1, "filterable": 0},
|
||||
{"key": "精品X资源", "name": "🐬精品X资源|🔞[成人]", "type": 1, "api": "https://www.jingpinx.com/api.php/provide/vod", "searchable": 1, "quickSearch": 1, "filterable": 0},
|
||||
{"key": "CK资源", "name": "🐬CK资源|🔞[成人]", "type": 1, "api": "https://ckzy.me/api.php/provide/vod", "searchable": 1, "quickSearch": 1, "filterable": 0},
|
||||
{"key": "🔞七天资源🌈", "name": "🐬七天资源🌈|🔞[成人]", "type": 1, "api": "https://8day.icu/api.php/provide/vod/at/json", "searchable": 1, "quickSearch": 1, "filterable": 0},
|
||||
{
|
||||
"key": "百万",
|
||||
"name": "🐬百万|🔞",
|
||||
"name": "🐬百万|🔞[成人]",
|
||||
"type": 1,
|
||||
"api": "https://api.bwzyz.com/api.php/provide/vod/at/json",
|
||||
"quickSearch": 1,
|
||||
@@ -605,7 +635,7 @@
|
||||
},
|
||||
{
|
||||
"key": "鸡坤",
|
||||
"name": "🐬鸡坤|🔞",
|
||||
"name": "🐬鸡坤|🔞[成人]",
|
||||
"type": 1,
|
||||
"api": "https://jkunzyapi.com/api.php/provide/vod/",
|
||||
"quickSearch": 1,
|
||||
@@ -614,27 +644,27 @@
|
||||
},
|
||||
{
|
||||
"key":"MissAV",
|
||||
"name":"🐬MissAV🔞",
|
||||
"name":"🐬MissAV🔞[成人]",
|
||||
"type":3,
|
||||
"api":"csp_MissAV",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/missav.html"
|
||||
},
|
||||
{
|
||||
"key":"WhosTV",
|
||||
"name":"🐬WhosTV┃番号🔞",
|
||||
"name":"🐬WhosTV┃番号🔞[成人]",
|
||||
"type":3,
|
||||
"api":"csp_MissAV",
|
||||
"homePage":"https://fgblh.github.io/uhuj.github.io/WhosTV.html"
|
||||
},
|
||||
{
|
||||
"key": "*AIvin",
|
||||
"name": "🐬AIvin|🔞",
|
||||
"name": "🐬AIvin|🔞[成人]",
|
||||
"type": 0,
|
||||
"api": "http://lbapiby.com/api.php/provide/vod/at/xml"
|
||||
},
|
||||
{
|
||||
"key": "香蕉资源",
|
||||
"name": "🐬香蕉资源🔞",
|
||||
"name": "🐬香蕉资源🔞[成人]",
|
||||
"type": 0,
|
||||
"api": "https://www.xiangjiaozyw.com/api.php/provide/vod/at/xml/",
|
||||
"searchable": 1,
|
||||
@@ -642,7 +672,7 @@
|
||||
},
|
||||
{
|
||||
"key": "大地采集",
|
||||
"name": "🐬大地av|🔞",
|
||||
"name": "🐬大地av|🔞[成人]",
|
||||
"type": 0,
|
||||
"api": "https://dadiapi.com/apple_m3u8.php",
|
||||
"playUrl": "https://play.dadiapi.com/watch?url=",
|
||||
@@ -652,7 +682,7 @@
|
||||
},
|
||||
{
|
||||
"key": "*番号资源",
|
||||
"name": "🐬番号资源|🔞",
|
||||
"name": "🐬番号资源|🔞[成人]",
|
||||
"type": 1,
|
||||
"api": "http://fhapi9.com/api.php/provide/vod/",
|
||||
"searchable": 0,
|
||||
@@ -661,7 +691,7 @@
|
||||
},
|
||||
{
|
||||
"key": "黄色仓库|AV",
|
||||
"name": "🐬黄色仓库(旧)|🔞",
|
||||
"name": "🐬黄色仓库(旧)|🔞[成人]",
|
||||
"type": 1,
|
||||
"api": "https://hsckzy.vip/api.php/provide/vod/",
|
||||
"quickSearch": 1,
|
||||
@@ -670,7 +700,7 @@
|
||||
},
|
||||
{
|
||||
"key": "桃花资源|AV",
|
||||
"name": "🐬桃花资源|🔞",
|
||||
"name": "🐬桃花资源|🔞[成人]",
|
||||
"type": 1,
|
||||
"api": "https://thzy1.me/api.php/provide/vod/",
|
||||
"quickSearch": 1,
|
||||
@@ -679,7 +709,7 @@
|
||||
},
|
||||
{
|
||||
"key": "乐播资源|AV",
|
||||
"name": "🐬乐播资源|🔞",
|
||||
"name": "🐬乐播资源|🔞[成人]",
|
||||
"type": 1,
|
||||
"api": "https://lbapi9.com/api.php/provide/vod/",
|
||||
"quickSearch": 1,
|
||||
@@ -688,7 +718,7 @@
|
||||
},
|
||||
{
|
||||
"key": "fqzy资源",
|
||||
"name": "🐬国产资源|🔞",
|
||||
"name": "🐬国产资源|🔞[成人]",
|
||||
"type": 1,
|
||||
"api": "https://fqzy.me//api.php/provide/vod/?ac=list",
|
||||
"searchable": 1,
|
||||
@@ -709,7 +739,7 @@
|
||||
},
|
||||
{
|
||||
"key": "lsb资源|AV",
|
||||
"name": "🐬lsb资源|🔞",
|
||||
"name": "🐬lsb资源|🔞[成人]",
|
||||
"type": 1,
|
||||
"api": "https://apilsbzy1.com/api.php/provide/vod/",
|
||||
"quickSearch": 1,
|
||||
@@ -718,7 +748,7 @@
|
||||
},
|
||||
{
|
||||
"key": "91",
|
||||
"name": "🐬传媒系列|🔞(梯子)",
|
||||
"name": "🐬传媒系列|🔞[成人](梯子)",
|
||||
"type": 1,
|
||||
"api": "https://91md.me/api.php/provide/vod/",
|
||||
"searchable": 1,
|
||||
@@ -726,7 +756,7 @@
|
||||
},
|
||||
{
|
||||
"key": "豆瓣",
|
||||
"name": "豆瓣|首页",
|
||||
"name": "豆瓣|首页[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Douban",
|
||||
"searchable": 0
|
||||
@@ -752,7 +782,7 @@
|
||||
},
|
||||
{
|
||||
"key": "热播影视",
|
||||
"name": "热播|APP",
|
||||
"name": "热播|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppRJ",
|
||||
"searchable": 1,
|
||||
@@ -764,13 +794,13 @@
|
||||
},
|
||||
{
|
||||
"key": "三秋影视",
|
||||
"name": "三秋|APP",
|
||||
"name": "三秋|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_App3Q"
|
||||
},
|
||||
{
|
||||
"key": "无极99",
|
||||
"name": "无极丨APP",
|
||||
"name": "无极丨APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_App99",
|
||||
"ext": {
|
||||
@@ -787,7 +817,7 @@
|
||||
},
|
||||
{
|
||||
"key": "听心99",
|
||||
"name": "听心|APP",
|
||||
"name": "听心|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_App99",
|
||||
"ext": {
|
||||
@@ -803,7 +833,7 @@
|
||||
},
|
||||
{
|
||||
"key": "橙子99",
|
||||
"name": "橙子丨APP",
|
||||
"name": "橙子丨APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_App99",
|
||||
"ext": {
|
||||
@@ -819,7 +849,7 @@
|
||||
},
|
||||
{
|
||||
"key": "咕噜99",
|
||||
"name": "咕噜丨APP",
|
||||
"name": "咕噜丨APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_App99",
|
||||
"ext": {
|
||||
@@ -835,7 +865,7 @@
|
||||
},
|
||||
{
|
||||
"key": "剧圈99",
|
||||
"name": "剧圈丨APP",
|
||||
"name": "剧圈丨APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_App99",
|
||||
"ext": {
|
||||
@@ -866,7 +896,7 @@
|
||||
},
|
||||
{
|
||||
"key": "天堂",
|
||||
"name": "天堂|APP",
|
||||
"name": "天堂|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppDrama",
|
||||
"searchable": 1,
|
||||
@@ -886,7 +916,7 @@
|
||||
},
|
||||
{
|
||||
"key": "橘汁",
|
||||
"name": "橘汁|APP",
|
||||
"name": "橘汁|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppDrama",
|
||||
"searchable": 1,
|
||||
@@ -906,7 +936,7 @@
|
||||
},
|
||||
{
|
||||
"key": "华谊",
|
||||
"name": "华谊|APP",
|
||||
"name": "华谊|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppDrama",
|
||||
"searchable": 1,
|
||||
@@ -926,7 +956,7 @@
|
||||
},
|
||||
{
|
||||
"key": "苹果",
|
||||
"name": "苹果|APP",
|
||||
"name": "苹果|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppDrama",
|
||||
"searchable": 1,
|
||||
@@ -946,7 +976,7 @@
|
||||
},
|
||||
{
|
||||
"key": "薯条",
|
||||
"name": "薯条|APP",
|
||||
"name": "薯条|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppDrama",
|
||||
"searchable": 1,
|
||||
@@ -966,7 +996,7 @@
|
||||
},
|
||||
{
|
||||
"key": "久久",
|
||||
"name": "久久|APP",
|
||||
"name": "久久|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppYsV2",
|
||||
"searchable": 1,
|
||||
@@ -976,7 +1006,7 @@
|
||||
},
|
||||
{
|
||||
"key": "闪影",
|
||||
"name": "闪影|APP",
|
||||
"name": "闪影|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppYsV2",
|
||||
"searchable": 1,
|
||||
@@ -986,7 +1016,7 @@
|
||||
},
|
||||
{
|
||||
"key": "飞飞",
|
||||
"name": "飞飞丨APP",
|
||||
"name": "飞飞丨APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppYsV2",
|
||||
"searchable": 1,
|
||||
@@ -996,7 +1026,7 @@
|
||||
},
|
||||
{
|
||||
"key": "金牌",
|
||||
"name": "金牌|APP",
|
||||
"name": "金牌|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppQi",
|
||||
"searchable": 1,
|
||||
@@ -1012,7 +1042,7 @@
|
||||
},
|
||||
{
|
||||
"key": "老鹰",
|
||||
"name": "老鹰|APP",
|
||||
"name": "老鹰|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppQi",
|
||||
"searchable": 1,
|
||||
@@ -1026,7 +1056,7 @@
|
||||
},
|
||||
{
|
||||
"key": "蓝鹰",
|
||||
"name": "蓝鹰|APP",
|
||||
"name": "蓝鹰|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppQi",
|
||||
"searchable": 1,
|
||||
@@ -1041,7 +1071,7 @@
|
||||
},
|
||||
{
|
||||
"key": "猎豹",
|
||||
"name": "猎豹|APP",
|
||||
"name": "猎豹|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppGet",
|
||||
"searchable": 1,
|
||||
@@ -1054,7 +1084,7 @@
|
||||
},
|
||||
{
|
||||
"key": "王子",
|
||||
"name": "王子|APP",
|
||||
"name": "王子|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppGet",
|
||||
"searchable": 1,
|
||||
@@ -1067,7 +1097,7 @@
|
||||
},
|
||||
{
|
||||
"key": "茉莉",
|
||||
"name": "茉莉|APP",
|
||||
"name": "茉莉|APP[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_AppGet",
|
||||
"searchable": 1,
|
||||
@@ -1080,7 +1110,7 @@
|
||||
},
|
||||
{
|
||||
"key": "哔哩视频",
|
||||
"name": "哔哩|视频",
|
||||
"name": "哔哩|视频[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_BiliYS",
|
||||
"searchable": 1,
|
||||
@@ -1097,13 +1127,13 @@
|
||||
},
|
||||
{
|
||||
"key": "三六零",
|
||||
"name": "三六零|视频",
|
||||
"name": "三六零|视频[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_SP360"
|
||||
},
|
||||
{
|
||||
"key": "玩偶",
|
||||
"name": "玩偶|4K",
|
||||
"name": "玩偶|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Wogg",
|
||||
"searchable": 1,
|
||||
@@ -1121,7 +1151,7 @@
|
||||
},
|
||||
{
|
||||
"key": "快映",
|
||||
"name": "快映|4K",
|
||||
"name": "快映|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_PanWebShare",
|
||||
"searchable": 1,
|
||||
@@ -1137,7 +1167,7 @@
|
||||
},
|
||||
{
|
||||
"key": "木偶",
|
||||
"name": "木偶|4K",
|
||||
"name": "木偶|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_PanWebShare",
|
||||
"searchable": 1,
|
||||
@@ -1156,7 +1186,7 @@
|
||||
},
|
||||
{
|
||||
"key": "蜡笔",
|
||||
"name": "蜡笔|4K",
|
||||
"name": "蜡笔|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_PanWebShare",
|
||||
"searchable": 1,
|
||||
@@ -1175,7 +1205,7 @@
|
||||
},
|
||||
{
|
||||
"key": "至臻",
|
||||
"name": "至臻|4K",
|
||||
"name": "至臻|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_PanWebShare",
|
||||
"searchable": 1,
|
||||
@@ -1193,7 +1223,7 @@
|
||||
},
|
||||
{
|
||||
"key": "多多",
|
||||
"name": "多多|4K",
|
||||
"name": "多多|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_PanWebShare",
|
||||
"searchable": 1,
|
||||
@@ -1211,7 +1241,7 @@
|
||||
},
|
||||
{
|
||||
"key": "欧哥",
|
||||
"name": "欧哥|4K",
|
||||
"name": "欧哥|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_PanWebShare",
|
||||
"searchable": 1,
|
||||
@@ -1230,7 +1260,7 @@
|
||||
},
|
||||
{
|
||||
"key": "二小",
|
||||
"name": "二小|4K",
|
||||
"name": "二小|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_PanWebShare",
|
||||
"searchable": 1,
|
||||
@@ -1248,7 +1278,7 @@
|
||||
},
|
||||
{
|
||||
"key": "虎斑",
|
||||
"name": "虎斑|4K",
|
||||
"name": "虎斑|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_PanWebShare",
|
||||
"searchable": 1,
|
||||
@@ -1264,7 +1294,7 @@
|
||||
},
|
||||
{
|
||||
"key": "夸父",
|
||||
"name": "夸父|4K",
|
||||
"name": "夸父|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_PanWebShareKF",
|
||||
"searchable": 1,
|
||||
@@ -1284,7 +1314,7 @@
|
||||
},
|
||||
{
|
||||
"key": "盘它",
|
||||
"name": "盘它|4K",
|
||||
"name": "盘它|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_PanWebSharePT",
|
||||
"searchable": 1,
|
||||
@@ -1297,7 +1327,7 @@
|
||||
},
|
||||
{
|
||||
"key": "123",
|
||||
"name": "123|4K",
|
||||
"name": "123|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_PanWebShare123",
|
||||
"searchable": 1,
|
||||
@@ -1317,7 +1347,7 @@
|
||||
},
|
||||
{
|
||||
"key": "指南",
|
||||
"name": "指南|4K",
|
||||
"name": "指南|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_4KZhinan",
|
||||
"searchable": 1,
|
||||
@@ -1327,7 +1357,7 @@
|
||||
},
|
||||
{
|
||||
"key": "人人",
|
||||
"name": "人人|4K",
|
||||
"name": "人人|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_RenRen",
|
||||
"searchable": 1,
|
||||
@@ -1337,7 +1367,7 @@
|
||||
},
|
||||
{
|
||||
"key": "即刻",
|
||||
"name": "即刻|4K",
|
||||
"name": "即刻|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Jike",
|
||||
"searchable": 1,
|
||||
@@ -1350,7 +1380,7 @@
|
||||
},
|
||||
{
|
||||
"key": "双星",
|
||||
"name": "双星|4K",
|
||||
"name": "双星|4K[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_ShuangXing",
|
||||
"searchable": 1,
|
||||
@@ -1363,7 +1393,7 @@
|
||||
},
|
||||
{
|
||||
"key": "围观短剧",
|
||||
"name": "围观|短剧",
|
||||
"name": "围观[短剧]",
|
||||
"type": 3,
|
||||
"api": "csp_WeiguanDJ",
|
||||
"searchable": 1,
|
||||
@@ -1372,26 +1402,15 @@
|
||||
"filterable": 1,
|
||||
"genre": "shortdrama"
|
||||
},
|
||||
{
|
||||
"key": "星芽短剧",
|
||||
"name": "星芽|短剧",
|
||||
"type": 3,
|
||||
"api": "https://cnb.cool/fish2018/xs/-/git/raw/main/py/星芽短剧.py",
|
||||
"searchable": 1,
|
||||
"changeable": 1,
|
||||
"quickSearch": 1,
|
||||
"filterable": 1,
|
||||
"genre": "shortdrama"
|
||||
},
|
||||
{
|
||||
"key": "独播影视",
|
||||
"name": "独播|影视",
|
||||
"name": "独播[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Duboku"
|
||||
},
|
||||
{
|
||||
"key": "厂长影视",
|
||||
"name": "厂长|影视",
|
||||
"name": "厂长[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Czsapp",
|
||||
"searchable": 1,
|
||||
@@ -1401,34 +1420,34 @@
|
||||
},
|
||||
{
|
||||
"key": "金牌影视",
|
||||
"name": "金牌|影视",
|
||||
"name": "金牌[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Jpys",
|
||||
"ext": "https://y2s52n7.com,https://m.hkybqufgh.com,https://m.sizhengxt.com,https://m.9zhoukj.com,https://m.sizhengxt.com,https://m.jiabaide.cn"
|
||||
},
|
||||
{
|
||||
"key": "瓜子影视",
|
||||
"name": "瓜子|影视",
|
||||
"name": "瓜子[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Gz360"
|
||||
},
|
||||
{
|
||||
"key": "骚火影视",
|
||||
"name": "骚火|影视",
|
||||
"name": "骚火[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_SaoHuo",
|
||||
"ext": "https://shdy5.us"
|
||||
},
|
||||
{
|
||||
"key": "农民影视",
|
||||
"name": "农民|影视",
|
||||
"name": "农民[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Wwys",
|
||||
"ext": "https://vip.wwgz.cn:5200"
|
||||
},
|
||||
{
|
||||
"key": "爱看机器人",
|
||||
"name": "爱看|影视",
|
||||
"name": "爱看[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Ikanbot",
|
||||
"searchable": 1,
|
||||
@@ -1437,35 +1456,35 @@
|
||||
},
|
||||
{
|
||||
"key": "小镇影视",
|
||||
"name": "小镇|影视",
|
||||
"name": "小镇[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_XBPQ",
|
||||
"ext": "https://cnb.cool/fish2018/xs/-/git/raw/main/XBPQ/小镇影视.json"
|
||||
},
|
||||
{
|
||||
"key": "面包影视",
|
||||
"name": "面包|影视",
|
||||
"name": "面包[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_XBPQ",
|
||||
"ext": "https://cnb.cool/fish2018/xs/-/git/raw/main/XBPQ/面包影视.json"
|
||||
},
|
||||
{
|
||||
"key": "永乐影视",
|
||||
"name": "永乐|影视",
|
||||
"name": "永乐[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_XBPQ",
|
||||
"ext": "https://cnb.cool/fish2018/xs/-/git/raw/main/XBPQ/永乐影视.json"
|
||||
},
|
||||
{
|
||||
"key": "剧圈影视",
|
||||
"name": "剧圈|影视",
|
||||
"name": "剧圈[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_XYQHiker",
|
||||
"ext": "https://cnb.cool/fish2018/xs/-/git/raw/main/XYQHiker/剧圈影视.json"
|
||||
},
|
||||
{
|
||||
"key": "1905",
|
||||
"name": "1905|影视",
|
||||
"name": "1905[追剧]",
|
||||
"type": 3,
|
||||
"api": "csp_Web1905",
|
||||
"searchable": 1,
|
||||
|
||||
@@ -100,6 +100,12 @@
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/枫叶影院.py"
|
||||
},
|
||||
{
|
||||
"key": "rb",
|
||||
"name": "🐬热播APP.py",
|
||||
"type": 3,
|
||||
"api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/GHK/refs/heads/main/py/热播APP.py"
|
||||
},
|
||||
{
|
||||
"key":"FY",
|
||||
"name":"🐬枫叶影院(关梯子使用)",
|
||||
|
||||
Reference in New Issue
Block a user