删除 py/西瓜影视.py

This commit is contained in:
2026-08-14 13:23:53 +02:00
parent a67f3d26ed
commit d4c98c8b7d
-336
View File
@@ -1,336 +0,0 @@
# -*- coding: utf-8 -*-
# by @PyramidStore AutoGen
import re
import sys
sys.path.append('..')
import json
from urllib.parse import quote
from base.spider import Spider
class Spider(Spider):
def init(self, extend=""):
self.nav_host = 'https://www.xiguadh.com'
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',
'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',
}
self.host = self._get_host()
def _get_host(self):
"""获取视频站点 URL,失败时从导航页获取"""
default_host = 'https://www.bzzdyy.com'
try:
r = self.fetch(default_host, headers=self.headers, timeout=10, verify=False)
if r.status_code == 200:
return default_host
except Exception:
pass
try:
r = self.fetch(self.nav_host, headers=self.headers, timeout=15, verify=False)
html = r.text
urls = re.findall(r'url:\s*["\']([^"\']+)["\']', html)
for url in urls:
if url.startswith('http') and 'xiguadh' not in url:
return url.rstrip('/')
except Exception:
pass
return default_host
def getName(self):
return '西瓜影院'
def isVideoFormat(self, url):
return False
def manualVideoCheck(self):
return True
def homeContent(self, filter):
try:
r = self.fetch(self.host, headers=self.headers, timeout=15, verify=False)
html = r.text
# 提取主要分类
nav_match = re.search(r'<ul class="stui-header__menu">(.*?)</ul>', html, re.DOTALL)
if nav_match:
nav_html = nav_match.group(1)
categories = re.findall(r'<li[^>]*><a href="/index.php/vod/type/id/(\d+)\.html">([^<]+)</a></li>', nav_html)
else:
categories = []
seen = set()
classes = []
for tid, name in categories:
if tid not in seen:
seen.add(tid)
classes.append({'type_name': name, 'type_id': tid})
if not classes:
raise Exception('No categories found')
# 提取首页推荐视频
videos = self._parse_vodlist(html)
except Exception:
classes = [
{'type_name': '电影', 'type_id': '20'},
{'type_name': '连续剧', 'type_id': '37'},
{'type_name': '动漫', 'type_id': '43'},
{'type_name': '综艺', 'type_id': '45'},
{'type_name': 'B站', 'type_id': '47'},
{'type_name': '人人专区', 'type_id': '60'},
]
videos = []
return {"class": classes, "list": videos}
def _parse_vodlist(self, html):
"""解析视频列表"""
items = re.findall(
r'<a class="stui-vodlist__thumb[^"]*"\s+href="([^"]+)"\s+title="([^"]*)"[^>]*data-original="([^"]*)"',
html
)
videos = []
for href, title, pic in items:
vod_id = re.search(r'/id/(\d+)\.html', href)
if vod_id:
vod_id = vod_id.group(1)
else:
continue
remark_match = re.search(r'<span class="pic-text text-right"><b>([^<]+)</b></span>',
html[html.find(href):html.find(href)+500] if href in html else '')
remark = remark_match.group(1) if remark_match else ''
if pic.startswith('/'):
pic = self.host + pic
videos.append({
'vod_id': vod_id,
'vod_name': title,
'vod_pic': pic,
'vod_remarks': remark,
})
return videos
def homeVideoContent(self):
return ''
def categoryContent(self, tid, pg, filter, extend):
pg = int(pg)
url = f'{self.host}/index.php/vod/type/id/{tid}/page/{pg}.html'
try:
r = self.fetch(url, headers=self.headers, timeout=15, verify=False)
html = r.text
items = re.findall(
r'<a class="stui-vodlist__thumb[^"]*"\s+href="([^"]+)"\s+title="([^"]*)"[^>]*data-original="([^"]*)"',
html
)
videos = []
for href, title, pic in items:
vod_id = re.search(r'/id/(\d+)\.html', href)
if vod_id:
vod_id = vod_id.group(1)
else:
continue
remark_match = re.search(r'<span class="pic-text text-right"><b>([^<]+)</b></span>',
html[html.find(href):html.find(href)+500] if href in html else '')
remark = remark_match.group(1) if remark_match else ''
if pic.startswith('/'):
pic = self.host + pic
videos.append({
'vod_id': vod_id,
'vod_name': title,
'vod_pic': pic,
'vod_remarks': remark,
})
return {
"list": videos,
"page": pg,
"pagecount": 9999,
"limit": 90,
"total": len(videos),
}
except Exception as e:
return {"list": [], "page": pg, "pagecount": 1, "limit": 90, "total": 0}
def detailContent(self, ids):
try:
vod_id = ids[0] if isinstance(ids, list) else ids
url = f'{self.host}/index.php/vod/detail/id/{vod_id}.html'
r = self.fetch(url, headers=self.headers, timeout=15, verify=False)
html = r.text
title_match = re.search(r'<h1 class="title">([^<]+)</h1>', html)
title = title_match.group(1).strip() if title_match else ''
self._vod_name = title
pic_match = re.search(r'<img class="lazyload" data-original="([^"]*)"', html)
pic = pic_match.group(1) if pic_match else ''
if pic.startswith('/'):
pic = self.host + pic
info_match = re.search(r'类型:([^/]+)\s*/\s*地区:([^/]+)\s*/\s*年份:(\d+)', html)
type_name = info_match.group(1).strip() if info_match else ''
area = info_match.group(2).strip() if info_match else ''
year = info_match.group(3) if info_match else ''
remark_match = re.search(r'状态:<span[^>]*>([^<]+)</span>', html)
remark = remark_match.group(1).strip() if remark_match else ''
director_match = re.search(r'导演:(.*?)</p>', html, re.DOTALL)
director = ''
if director_match:
director = re.sub(r'<[^>]+>', '', director_match.group(1)).strip()
actor_match = re.search(r'主演:([^<]+)', html)
actor = actor_match.group(1).strip() if actor_match else ''
desc_match = re.search(r'<span class="detail-content"[^>]*>([^<]+)</span>', html)
desc = desc_match.group(1).strip() if desc_match else ''
play_from = []
play_url = []
source_tabs = re.findall(r'<li><a href="#playlist\d+"[^>]*>([^<]+)</a></li>', html)
for idx, source_name in enumerate(source_tabs):
source_id = idx + 1
episodes_match = re.search(
f'<div id="playlist{source_id}" class="tab-pane[^"]*"[^>]*>.*?<ul class="stui-content__playlist[^"]*"[^>]*>(.*?)</ul>',
html, re.DOTALL
)
if episodes_match:
episodes = re.findall(r'<a href="([^"]+)">([^<]+)</a>', episodes_match.group(1))
episode_list = []
for ep_url, ep_name in episodes:
episode_list.append(f'{ep_name}${self.host}{ep_url}')
play_from.append(source_name)
play_url.append('#'.join(episode_list))
vod_play_from = '$$$'.join(play_from) if play_from else '默认'
vod_play_url = '$$$'.join(play_url) if play_url else ''
vod = {
'vod_id': vod_id,
'vod_name': title,
'vod_pic': pic,
'vod_year': year,
'vod_area': area,
'vod_remarks': remark,
'vod_director': director,
'vod_actor': actor,
'vod_content': desc,
'vod_play_from': vod_play_from,
'vod_play_url': vod_play_url,
}
return {"list": [vod]}
except Exception as e:
return {"list": []}
def searchContent(self, key, quick, pg="1"):
pg = int(pg)
url = f'{self.host}/index.php/vod/search/wd/{quote(key)}.html'
try:
r = self.fetch(url, headers=self.headers, timeout=15, verify=False)
html = r.text
items = re.findall(
r'<a class="stui-vodlist__thumb[^"]*"\s+href="([^"]+)"\s+title="([^"]*)"[^>]*data-original="([^"]*)"',
html
)
videos = []
for href, title, pic in items:
vod_id = re.search(r'/id/(\d+)\.html', href)
if vod_id:
vod_id = vod_id.group(1)
else:
continue
remark_match = re.search(r'<span class="pic-text text-right"><b>([^<]+)</b></span>',
html[html.find(href):html.find(href)+500] if href in html else '')
remark = remark_match.group(1) if remark_match else ''
if pic.startswith('/'):
pic = self.host + pic
videos.append({
'vod_id': vod_id,
'vod_name': title,
'vod_pic': pic,
'vod_remarks': remark,
})
return {
"list": videos,
"page": pg,
"pagecount": 9999,
"limit": 90,
"total": len(videos),
}
except Exception as e:
return {"list": [], "page": pg, "pagecount": 1, "limit": 90, "total": 0}
def _clean_vod_name(self, name):
import re
if not name:
return ''
cleaned = re.sub(r'\s*\d+\s*[集話话章部期]', '', name)
cleaned = re.sub(r'EP\s*\d+', '', cleaned, flags=re.IGNORECASE)
cleaned = re.sub(r'\d+集', '', cleaned)
cleaned = re.sub(r'更新至\d+集', '', cleaned)
cleaned = re.sub(r'\d+集全', '', cleaned)
cleaned = re.sub(r'[(].*?[)]', '', cleaned)
cleaned = re.sub(r'\s*-\s*.*$', '', cleaned)
cleaned = re.sub(r'\s+', ' ', cleaned)
cleaned = re.sub(r'^[\s\-_,.,。、]+|[\s\-_,.,。、]+$', '', cleaned)
return cleaned.strip()
def _build_danmaku_url(self, vod_name, vod_index=''):
import re
idx = 0
if vod_index:
s = str(vod_index).strip()
m = re.search(r'\s*(\d+)\s*[集話话章部期]', s)
if m:
idx = int(m.group(1))
else:
m = re.search(r'(\d+)', s)
if m:
idx = int(m.group(1))
cleaned_name = self._clean_vod_name(vod_name)
params = []
if cleaned_name:
params.append(f'vodName={quote(cleaned_name)}')
params.append(f'vodIndex={idx}')
query = '&'.join(params)
return f'http://127.0.0.1:9978/proxy?do=appdanmu&{query}'
def playerContent(self, flag, id, vipFlags):
try:
ep_name = ''
vod_index = ''
if '$' in id:
parts = id.split('$', 1)
ep_name = parts[0]
url = parts[1] if len(parts) > 1 else ''
else:
url = id if id.startswith('http') else f'{self.host}{id}'
# 从 URL 中提取集数 (nid 参数)
nid_match = re.search(r'nid/(\d+)\.html', url)
if nid_match:
vod_index = nid_match.group(1)
danmaku_url = self._build_danmaku_url(self._vod_name, vod_index)
r = self.fetch(url, headers=self.headers, timeout=15, verify=False)
html = r.text
iframe_match = re.search(r'<iframe[^>]+src="([^"]+)"', html)
if iframe_match:
iframe_url = iframe_match.group(1)
if not iframe_url.startswith('http'):
iframe_url = self.host + iframe_url
return {
"parse": 1,
"url": iframe_url,
"header": self.headers,
"danmaku": danmaku_url
}
src_match = re.search(r'(https?://[^"\'<>\s]+\.m3u8[^"\'<>\s]*)', html)
if src_match:
return {
"parse": 0,
"url": src_match.group(1),
"header": self.headers,
"danmaku": danmaku_url
}
return {
"parse": 1,
"url": url,
"header": self.headers,
"danmaku": danmaku_url
}
except Exception as e:
danmaku_url = self._build_danmaku_url(self._vod_name, '')
return {"parse": 1, "url": id, "header": {}, "danmaku": danmaku_url}
def localProxy(self, param):
return [200, {}, ""]
def destroy(self):
pass