diff --git a/.版本.png b/.版本.png index 54dbba3..90c3648 100644 Binary files a/.版本.png and b/.版本.png differ diff --git a/PY/偷乐短剧.py b/PY/偷乐短剧.py new file mode 100644 index 0000000..4aeb27b --- /dev/null +++ b/PY/偷乐短剧.py @@ -0,0 +1,790 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# 偷乐短剧爬虫 + +import sys +import json +import re +import time +import urllib.parse +import requests +from bs4 import BeautifulSoup + +# 导入基础类 +sys.path.append('../../') +try: + from base.spider import Spider +except ImportError: + # 本地调试时的替代实现 + class Spider: + def init(self, extend=""): + pass + +class Spider(Spider): + def __init__(self): + # 网站主URL + self.siteUrl = "https://www.toule.top" + + # 根据网站实际结构,分类链接格式为: /index.php/vod/show/class/分类名/id/1.html + # 分类ID映射 - 从网站中提取的分类 + self.cateManual = { + "男频": "/index.php/vod/show/class/%E7%94%B7%E9%A2%91/id/1.html", + "女频": "/index.php/vod/show/class/%E5%A5%B3%E9%A2%91/id/1.html", + "都市": "/index.php/vod/show/class/%E9%83%BD%E5%B8%82/id/1.html", + "赘婿": "/index.php/vod/show/class/%E8%B5%98%E5%A9%BF/id/1.html", + "战神": "/index.php/vod/show/class/%E6%88%98%E7%A5%9E/id/1.html", + "古代言情": "/index.php/vod/show/class/%E5%8F%A4%E4%BB%A3%E8%A8%80%E6%83%85/id/1.html", + "现代言情": "/index.php/vod/show/class/%E7%8E%B0%E4%BB%A3%E8%A8%80%E6%83%85/id/1.html", + "历史": "/index.php/vod/show/class/%E5%8E%86%E5%8F%B2/id/1.html", + "玄幻": "/index.php/vod/show/class/%E7%8E%84%E5%B9%BB/id/1.html", + "搞笑": "/index.php/vod/show/class/%E6%90%9E%E7%AC%91/id/1.html", + "甜宠": "/index.php/vod/show/class/%E7%94%9C%E5%AE%A0/id/1.html", + "励志": "/index.php/vod/show/class/%E5%8A%B1%E5%BF%97/id/1.html", + "逆袭": "/index.php/vod/show/class/%E9%80%86%E8%A2%AD/id/1.html", + "穿越": "/index.php/vod/show/class/%E7%A9%BF%E8%B6%8A/id/1.html", + "古装": "/index.php/vod/show/class/%E5%8F%A4%E8%A3%85/id/1.html" + } + + # 请求头 + self.headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", + "Referer": "https://www.toule.top/", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", + "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", + "Accept-Encoding": "gzip, deflate, br", + "Connection": "keep-alive", + } + + + # 缓存 + self.cache = {} + self.cache_timeout = {} + + def getName(self): + return "偷乐短剧" + + def init(self, extend=""): + # 初始化方法,可以留空 + return + + def isVideoFormat(self, url): + """判断是否为视频格式""" + video_formats = ['.mp4', '.m3u8', '.ts', '.flv', '.avi', '.mkv', '.mov', '.rmvb', '.3gp'] + for format in video_formats: + if format in url.lower(): + return True + return False + + def manualVideoCheck(self): + """是否需要手动检查视频""" + return False + + # 工具方法 - 网络请求 + def fetch(self, url, headers=None, data=None, method="GET"): + """统一的网络请求方法""" + try: + if headers is None: + headers = self.headers.copy() + + if method.upper() == "GET": + response = requests.get(url, headers=headers, params=data, timeout=10,verify=False) + else: # POST + response = requests.post(url, headers=headers, data=data, timeout=10,verify=False) + + response.raise_for_status() + response.encoding = response.apparent_encoding or 'utf-8' + return response + except Exception as e: + self.log(f"请求失败: {url}, 错误: {str(e)}", "ERROR") + return None + + # 缓存方法 + def getCache(self, key, timeout=3600): + """获取缓存数据""" + if key in self.cache and key in self.cache_timeout: + if time.time() < self.cache_timeout[key]: + return self.cache[key] + else: + del self.cache[key] + del self.cache_timeout[key] + return None + + def setCache(self, key, value, timeout=3600): + """设置缓存数据""" + self.cache[key] = value + self.cache_timeout[key] = time.time() + timeout + + # 日志方法 + def log(self, msg, level='INFO'): + """记录日志""" + levels = { + 'DEBUG': 0, + 'INFO': 1, + 'WARNING': 2, + 'ERROR': 3 + } + + current_level = 'INFO' # 可以设置为DEBUG以获取更多信息 + + if levels.get(level, 4) >= levels.get(current_level, 1): + print(f"[{level}] {time.strftime('%Y-%m-%d %H:%M:%S')} - {msg}") + + # 辅助方法 - 从URL中提取视频ID + def extractVodId(self, url): + """从URL中提取视频ID""" + # 路径格式: /index.php/vod/play/id/9024/sid/1/nid/1.html + match = re.search(r'/id/(\d+)/', url) + if match: + return match.group(1) + return "" + + # 辅助方法 - 从网页内容中提取分类 + def extractCategories(self, text): + """从网页内容中提取分类标签""" + cats = [] + # 匹配标签字符串,例如: "男频,逆袭,亲情,短剧" + if "," in text: + parts = text.split(",") + for part in parts: + part = part.strip() + if part and part != "短剧": + cats.append(part) + return cats + + # 主要接口实现 + def homeContent(self, filter): + """获取首页分类及内容""" + result = {} + classes = [] + + # 从缓存获取 + cache_key = 'home_classes' + cached_classes = self.getCache(cache_key) + if cached_classes: + classes = cached_classes + else: + # 使用预定义的分类 + for k, v in self.cateManual.items(): + classes.append({ + 'type_id': v, # 使用完整URL路径作为type_id + 'type_name': k + }) + + # 保存到缓存 + self.setCache(cache_key, classes, 24*3600) # 缓存24小时 + + result['class'] = classes + + # 获取首页推荐视频 + videos = self.homeVideoContent().get('list', []) + result['list'] = videos + + return result + + def homeVideoContent(self): + """获取首页推荐视频内容""" + result = {'list': []} + videos = [] + + # 从缓存获取 + cache_key = 'home_videos' + cached_videos = self.getCache(cache_key) + if cached_videos: + return {'list': cached_videos} + + try: + response = self.fetch(self.siteUrl) + if response and response.status_code == 200: + html = response.text + soup = BeautifulSoup(html, 'html.parser') + + # 查找最新更新区域 + latest_section = soup.find('h2', text=lambda t: t and '最新更新' in t) + if latest_section: + container = latest_section.parent # 获取容器 + if container: + # 查找所有 li.item 元素 + items = container.find_all('li', class_='item') + + for item in items: + try: + # 获取链接和标题 + title_link = item.find('h3') + if not title_link: + continue + + title = title_link.text.strip() + + # 获取第一个链接作为详情页链接 + link_tag = item.find('a') + if not link_tag: + continue + + link = link_tag.get('href', '') + if not link.startswith('http'): + link = urllib.parse.urljoin(self.siteUrl, link) + + # 提取ID + vid = self.extractVodId(link) + if not vid: + continue + + # 获取图片 + img_tag = item.find('img') + img_url = "" + if img_tag: + img_url = img_tag.get('src', img_tag.get('data-src', '')) + if img_url and not img_url.startswith('http'): + img_url = urllib.parse.urljoin(self.siteUrl, img_url) + + # 获取备注信息 + remarks = "" + remarks_tag = item.find('span', class_='remarks') + if remarks_tag: + remarks = remarks_tag.text.strip() + + # 获取标签信息 + tags = "" + tags_tag = item.find('span', class_='tags') + if tags_tag: + tags = tags_tag.text.strip() + + # 合并备注和标签 + if remarks and tags: + remarks = f"{remarks} | {tags}" + elif tags: + remarks = tags + + # 构建视频项 + videos.append({ + 'vod_id': vid, + 'vod_name': title, + 'vod_pic': img_url, + 'vod_remarks': remarks + }) + except Exception as e: + self.log(f"处理视频项时出错: {str(e)}", "ERROR") + continue + + # 保存到缓存 + self.setCache(cache_key, videos, 3600) # 缓存1小时 + except Exception as e: + self.log(f"获取首页视频内容发生错误: {str(e)}", "ERROR") + + result['list'] = videos + return result + + def categoryContent(self, tid, pg, filter, extend): + """获取分类内容""" + result = {} + videos = [] + + # 处理页码 + if pg is None: + pg = 1 + else: + pg = int(pg) + + # 构建分类URL - tid是完整的URL路径 + if tid.startswith("/"): + # 替换页码,URL格式可能像: /index.php/vod/show/class/男频/id/1.html + if pg > 1: + if "html" in tid: + category_url = tid.replace(".html", f"/page/{pg}.html") + else: + category_url = f"{tid}/page/{pg}.html" + else: + category_url = tid + + full_url = urllib.parse.urljoin(self.siteUrl, category_url) + else: + # 如果tid不是URL路径,可能是旧版分类ID,尝试查找对应URL + category_url = "" + for name, url in self.cateManual.items(): + if name == tid: + category_url = url + break + + if not category_url: + self.log(f"未找到分类ID对应的URL: {tid}", "ERROR") + result['list'] = [] + result['page'] = pg + result['pagecount'] = 1 + result['limit'] = 0 + result['total'] = 0 + return result + + # 处理页码 + if pg > 1: + if "html" in category_url: + category_url = category_url.replace(".html", f"/page/{pg}.html") + else: + category_url = f"{category_url}/page/{pg}.html" + + full_url = urllib.parse.urljoin(self.siteUrl, category_url) + + # 请求分类页 + try: + response = self.fetch(full_url) + if response and response.status_code == 200: + html = response.text + soup = BeautifulSoup(html, 'html.parser') + + # 查找视频项,根据实际HTML结构调整 + items = soup.find_all('li', class_='item') + + for item in items: + try: + # 获取链接和标题 + title_tag = item.find('h3') + if not title_tag: + continue + + title = title_tag.text.strip() + + # 获取链接 + link_tag = item.find('a') + if not link_tag: + continue + + link = link_tag.get('href', '') + if not link.startswith('http'): + link = urllib.parse.urljoin(self.siteUrl, link) + + # 提取ID + vid = self.extractVodId(link) + if not vid: + continue + + # 获取图片 + img_tag = item.find('img') + img_url = "" + if img_tag: + img_url = img_tag.get('src', img_tag.get('data-src', '')) + if img_url and not img_url.startswith('http'): + img_url = urllib.parse.urljoin(self.siteUrl, img_url) + + # 获取备注信息 + remarks = "" + remarks_tag = item.find('span', class_='remarks') + if remarks_tag: + remarks = remarks_tag.text.strip() + + # 获取标签信息 + tags = "" + tags_tag = item.find('span', class_='tags') + if tags_tag: + tags = tags_tag.text.strip() + + # 合并备注和标签 + if remarks and tags: + remarks = f"{remarks} | {tags}" + elif tags: + remarks = tags + + # 构建视频项 + videos.append({ + 'vod_id': vid, + 'vod_name': title, + 'vod_pic': img_url, + 'vod_remarks': remarks + }) + except Exception as e: + self.log(f"处理分类视频项时出错: {str(e)}", "ERROR") + continue + + # 查找分页信息 + # 默认值 + total = len(videos) + pagecount = 1 + limit = 20 + + # 尝试查找分页元素 + pagination = soup.find('ul', class_='page') + if pagination: + # 查找最后一页的链接 + last_page_links = pagination.find_all('a') + for link in last_page_links: + page_text = link.text.strip() + if page_text.isdigit(): + pagecount = max(pagecount, int(page_text)) + except Exception as e: + self.log(f"获取分类内容发生错误: {str(e)}", "ERROR") + + result['list'] = videos + result['page'] = pg + result['pagecount'] = pagecount + result['limit'] = limit + result['total'] = total + + return result + + def detailContent(self, ids): + """获取详情内容""" + result = {} + + if not ids or len(ids) == 0: + return result + + # 视频ID + vid = ids[0] + + # 构建播放页URL + play_url = f"{self.siteUrl}/index.php/vod/play/id/{vid}/sid/1/nid/1.html" + + try: + response = self.fetch(play_url) + if not response or response.status_code != 200: + return result + + html = response.text + soup = BeautifulSoup(html, 'html.parser') + + # 提取视频基本信息 + # 标题 + title = "" + title_tag = soup.find('h1', class_='items-title') + if title_tag: + title = title_tag.text.strip() + + # 图片 + pic = "" + pic_tag = soup.find('img', class_='thumb') + if pic_tag: + pic = pic_tag.get('src', '') + if pic and not pic.startswith('http'): + pic = urllib.parse.urljoin(self.siteUrl, pic) + + # 简介 + desc = "" + desc_tag = soup.find('div', class_='text-content') + if desc_tag: + desc = desc_tag.text.strip() + + # 标签/分类 + tags = [] + tags_container = soup.find('span', class_='items-tags') + if tags_container: + tag_links = tags_container.find_all('a') + for tag in tag_links: + tag_text = tag.text.strip() + if tag_text: + tags.append(tag_text) + + # 提取播放列表 + play_from = "偷乐短剧" + play_list = [] + + # 查找播放列表区域 + play_area = soup.find('div', class_='swiper-wrapper') + if play_area: + # 查找所有剧集链接 + episode_links = play_area.find_all('a') + for ep in episode_links: + ep_title = ep.text.strip() + ep_url = ep.get('href', '') + + if ep_url: + # 直接使用URL作为ID + if not ep_url.startswith('http'): + ep_url = urllib.parse.urljoin(self.siteUrl, ep_url) + + # 提取集数信息 + ep_num = ep_title + if ep_num.isdigit(): + ep_num = f"第{ep_num}集" + + play_list.append(f"{ep_num}${ep_url}") + + # 如果没有找到播放列表,查找播放按钮 + if not play_list: + play_btn = soup.find('a', class_='btn-play') + if play_btn: + play_url = play_btn.get('href', '') + if play_url: + if not play_url.startswith('http'): + play_url = urllib.parse.urljoin(self.siteUrl, play_url) + + play_list.append(f"播放${play_url}") + + # 如果仍然没有找到播放链接,使用播放页URL + if not play_list: + play_url = f"{self.siteUrl}/index.php/vod/play/id/{vid}/sid/1/nid/1.html" + play_list.append(f"播放${play_url}") + + # 提取更多信息(导演、演员等) + director = "" + actor = "" + year = "" + area = "" + remarks = "" + + # 查找备注信息 + meta_items = soup.find_all('div', class_='meta-item') + for item in meta_items: + item_title = item.find('span', class_='item-title') + item_content = item.find('span', class_='item-content') + + if item_title and item_content: + title_text = item_title.text.strip() + content_text = item_content.text.strip() + + if "导演" in title_text: + director = content_text + elif "主演" in title_text: + actor = content_text + elif "年份" in title_text: + year = content_text + elif "地区" in title_text: + area = content_text + elif "简介" in title_text: + if not desc: + desc = content_text + elif "状态" in title_text: + remarks = content_text + + # 如果没有从meta-item中获取到remarks + if not remarks: + remarks_tag = soup.find('span', class_='remarks') + if remarks_tag: + remarks = remarks_tag.text.strip() + + # 构建标准数据结构 + vod = { + "vod_id": vid, + "vod_name": title, + "vod_pic": pic, + "vod_year": year, + "vod_area": area, + "vod_remarks": remarks, + "vod_actor": actor, + "vod_director": director, + "vod_content": desc, + "type_name": ",".join(tags), + "vod_play_from": play_from, + "vod_play_url": "#".join(play_list) + } + + result = { + 'list': [vod] + } + except Exception as e: + self.log(f"获取详情内容时出错: {str(e)}", "ERROR") + + return result + + def searchContent(self, key, quick, pg=1): + """搜索功能""" + result = {} + videos = [] + + # 构建搜索URL和参数 + search_url = f"{self.siteUrl}/index.php/vod/search.html" + params = {"wd": key} + + try: + response = self.fetch(search_url, data=params) + if response and response.status_code == 200: + html = response.text + soup = BeautifulSoup(html, 'html.parser') + + # 查找搜索结果项 + search_items = soup.find_all('li', class_='item') + + for item in search_items: + try: + # 获取标题 + title_tag = item.find('h3') + if not title_tag: + continue + + title = title_tag.text.strip() + + # 获取链接 + link_tag = item.find('a') + if not link_tag: + continue + + link = link_tag.get('href', '') + if not link.startswith('http'): + link = urllib.parse.urljoin(self.siteUrl, link) + + # 提取视频ID + vid = self.extractVodId(link) + if not vid: + continue + + # 获取图片 + img_tag = item.find('img') + img_url = "" + if img_tag: + img_url = img_tag.get('src', img_tag.get('data-src', '')) + if img_url and not img_url.startswith('http'): + img_url = urllib.parse.urljoin(self.siteUrl, img_url) + + # 获取备注信息 + remarks = "" + remarks_tag = item.find('span', class_='remarks') + if remarks_tag: + remarks = remarks_tag.text.strip() + + # 获取标签信息 + tags = "" + tags_tag = item.find('span', class_='tags') + if tags_tag: + tags = tags_tag.text.strip() + + # 合并备注和标签 + if remarks and tags: + remarks = f"{remarks} | {tags}" + elif tags: + remarks = tags + + # 构建视频项 + videos.append({ + 'vod_id': vid, + 'vod_name': title, + 'vod_pic': img_url, + 'vod_remarks': remarks + }) + except Exception as e: + self.log(f"处理搜索结果时出错: {str(e)}", "ERROR") + continue + except Exception as e: + self.log(f"搜索功能发生错误: {str(e)}", "ERROR") + + result['list'] = videos + return result + + def searchContentPage(self, key, quick, pg=1): + return self.searchContent(key, quick, pg) + + def playerContent(self, flag, id, vipFlags): + """获取播放内容""" + result = {} + + try: + # 判断是否已经是视频URL + if self.isVideoFormat(id): + result["parse"] = 0 + result["url"] = id + result["playUrl"] = "" + result["header"] = json.dumps(self.headers) + return result + + # 判断是否是完整的页面URL + if id.startswith(('http://', 'https://')): + play_url = id + # 尝试作为相对路径处理 + elif id.startswith('/'): + play_url = urllib.parse.urljoin(self.siteUrl, id) + # 假设是视频ID,构建播放页面URL + else: + # 检查是否是"视频ID_集数"格式 + parts = id.split('_') + if len(parts) > 1 and parts[0].isdigit(): + vid = parts[0] + nid = parts[1] + play_url = f"{self.siteUrl}/index.php/vod/play/id/{vid}/sid/1/nid/{nid}.html" + else: + # 直接当作视频ID处理 + play_url = f"{self.siteUrl}/index.php/vod/play/id/{id}/sid/1/nid/1.html" + + # 访问播放页获取真实播放地址 + try: + self.log(f"正在解析播放页面: {play_url}") + response = self.fetch(play_url) + if response and response.status_code == 200: + html = response.text + + # 查找player_aaaa变量 + player_match = re.search(r'var\s+player_aaaa\s*=\s*({.*?});', html, re.DOTALL) + if player_match: + try: + player_data = json.loads(player_match.group(1)) + if 'url' in player_data: + video_url = player_data['url'] + if not video_url.startswith('http'): + video_url = urllib.parse.urljoin(self.siteUrl, video_url) + + self.log(f"从player_aaaa获取到视频地址: {video_url}") + result["parse"] = 0 + result["url"] = video_url + result["playUrl"] = "" + result["header"] = json.dumps(self.headers) + return result + except json.JSONDecodeError as e: + self.log(f"解析player_aaaa JSON出错: {str(e)}", "ERROR") + + # 如果player_aaaa解析失败,尝试其他方式 + # 1. 查找video标签 + video_match = re.search(r']*src=["\'](.*?)["\']', html) + if video_match: + video_url = video_match.group(1) + if not video_url.startswith('http'): + video_url = urllib.parse.urljoin(self.siteUrl, video_url) + + self.log(f"从video标签找到视频地址: {video_url}") + result["parse"] = 0 + result["url"] = video_url + result["playUrl"] = "" + result["header"] = json.dumps(self.headers) + return result + + # 2. 查找iframe + iframe_match = re.search(r']*src=["\'](.*?)["\']', html) + if iframe_match: + iframe_url = iframe_match.group(1) + if not iframe_url.startswith('http'): + iframe_url = urllib.parse.urljoin(self.siteUrl, iframe_url) + + self.log(f"找到iframe,正在解析: {iframe_url}") + # 访问iframe内容 + iframe_response = self.fetch(iframe_url) + if iframe_response and iframe_response.status_code == 200: + iframe_html = iframe_response.text + + # 在iframe内容中查找视频地址 + iframe_video_match = re.search(r'(https?://[^\'"]+\.(mp4|m3u8|ts))', iframe_html) + if iframe_video_match: + video_url = iframe_video_match.group(1) + + self.log(f"从iframe中找到视频地址: {video_url}") + result["parse"] = 0 + result["url"] = video_url + result["playUrl"] = "" + result["header"] = json.dumps({ + "User-Agent": self.headers["User-Agent"], + "Referer": iframe_url + }) + return result + + # 3. 查找任何可能的视频URL + url_match = re.search(r'(https?://[^\'"]+\.(mp4|m3u8|ts))', html) + if url_match: + video_url = url_match.group(1) + + self.log(f"找到可能的视频地址: {video_url}") + result["parse"] = 0 + result["url"] = video_url + result["playUrl"] = "" + result["header"] = json.dumps(self.headers) + return result + except Exception as e: + self.log(f"解析播放地址时出错: {str(e)}", "ERROR") + + # 如果所有方式都失败,返回外部解析标志 + self.log("未找到直接可用的视频地址,需要外部解析", "WARNING") + result["parse"] = 1 # 表示需要外部解析 + result["url"] = play_url # 返回播放页面URL + result["playUrl"] = "" + result["header"] = json.dumps(self.headers) + + except Exception as e: + self.log(f"获取播放内容时出错: {str(e)}", "ERROR") + + return result + + def localProxy(self, param): + """本地代理""" + return [404, "text/plain", {}, "Not Found"] diff --git a/PY/河马短剧.py b/PY/河马短剧.py new file mode 100644 index 0000000..eeee8ba --- /dev/null +++ b/PY/河马短剧.py @@ -0,0 +1,581 @@ +# -*- coding: utf-8 -*- +import requests +import re +import json +import traceback +import sys + +sys.path.append('../../') +try: + from base.spider import Spider +except ImportError: + # 定义一个基础接口类,用于本地测试 + class Spider: + def init(self, extend=""): + pass + +class Spider(Spider): + def __init__(self): + self.siteUrl = "https://www.kuaikaw.cn" + self.nextData = None # 缓存NEXT_DATA数据 + self.cateManual = { + "甜宠": "462", + "古装仙侠": "1102", + "现代言情": "1145", + "青春": "1170", + "豪门恩怨": "585", + "逆袭": "417-464", + "重生": "439-465", + "系统": "1159", + "总裁": "1147", + "职场商战": "943" + } + + def getName(self): + # 返回爬虫名称 + return "河马短剧" + + def init(self, extend=""): + return + + def fetch(self, url, headers=None): + """统一的网络请求接口""" + if headers is None: + 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 Edg/120.0.0.0", + "Referer": self.siteUrl, + "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,en;q=0.8" + } + + try: + response = requests.get(url, headers=headers, timeout=10, allow_redirects=True) + response.raise_for_status() + return response + except Exception as e: + print(f"请求异常: {url}, 错误: {str(e)}") + return None + + def isVideoFormat(self, url): + # 检查是否为视频格式 + video_formats = ['.mp4', '.mkv', '.avi', '.wmv', '.m3u8', '.flv', '.rmvb'] + for format in video_formats: + if format in url.lower(): + return True + return False + + def manualVideoCheck(self): + # 不需要手动检查 + return False + + def homeContent(self, filter): + """获取首页分类及筛选""" + result = {} + # 分类列表,使用已初始化的cateManual + classes = [] + for k in self.cateManual: + classes.append({ + 'type_name': k, + 'type_id': self.cateManual[k] + }) + result['class'] = classes + # 获取首页推荐视频 + try: + result['list'] = self.homeVideoContent()['list'] + except: + result['list'] = [] + + return result + + def homeVideoContent(self): + """获取首页推荐视频内容""" + videos = [] + try: + response = self.fetch(self.siteUrl) + html_content = response.text + # 提取NEXT_DATA JSON数据 + next_data_pattern = r'' + next_data_match = re.search(next_data_pattern, html_content, re.DOTALL) + if next_data_match: + next_data_json = json.loads(next_data_match.group(1)) + page_props = next_data_json.get("props", {}).get("pageProps", {}) + # 获取轮播图数据 - 这些通常是推荐内容 + if "bannerList" in page_props and isinstance(page_props["bannerList"], list): + banner_list = page_props["bannerList"] + for banner in banner_list: + book_id = banner.get("bookId", "") + book_name = banner.get("bookName", "") + cover_url = banner.get("coverWap", banner.get("wapUrl", "")) + # 获取状态和章节数 + status = banner.get("statusDesc", "") + total_chapters = banner.get("totalChapterNum", "") + if book_id and book_name: + videos.append({ + "vod_id": f"/drama/{book_id}", + "vod_name": book_name, + "vod_pic": cover_url, + "vod_remarks": f"{status} {total_chapters}集" if total_chapters else status + }) + + # SEO分类下的推荐 + if "seoColumnVos" in page_props and isinstance(page_props["seoColumnVos"], list): + for column in page_props["seoColumnVos"]: + book_infos = column.get("bookInfos", []) + for book in book_infos: + book_id = book.get("bookId", "") + book_name = book.get("bookName", "") + cover_url = book.get("coverWap", "") + status = book.get("statusDesc", "") + total_chapters = book.get("totalChapterNum", "") + + if book_id and book_name: + videos.append({ + "vod_id": f"/drama/{book_id}", + "vod_name": book_name, + "vod_pic": cover_url, + "vod_remarks": f"{status} {total_chapters}集" if total_chapters else status + }) + + # # 去重 + # seen = set() + # unique_videos = [] + # for video in videos: + # if video["vod_id"] not in seen: + # seen.add(video["vod_id"]) + # unique_videos.append(video) + # videos = unique_videos + + except Exception as e: + print(f"获取首页推荐内容出错: {e}") + + result = { + "list": videos + } + return result + + def categoryContent(self, tid, pg, filter, extend): + """获取分类内容""" + result = {} + videos = [] + url = f"{self.siteUrl}/browse/{tid}/{pg}" + response = self.fetch(url) + html_content = response.text + # 提取NEXT_DATA JSON数据 + next_data_pattern = r'' + next_data_match = re.search(next_data_pattern, html_content, re.DOTALL) + if next_data_match: + next_data_json = json.loads(next_data_match.group(1)) + page_props = next_data_json.get("props", {}).get("pageProps", {}) + # 获取总页数和当前页 + current_page = page_props.get("page", 1) + total_pages = page_props.get("pages", 1) + # 获取书籍列表 + book_list = page_props.get("bookList", []) + # 转换为通用格式 + for book in book_list: + book_id = book.get("bookId", "") + book_name = book.get("bookName", "") + cover_url = book.get("coverWap", "") + status_desc = book.get("statusDesc", "") + total_chapters = book.get("totalChapterNum", "") + if book_id and book_name: + videos.append({ + "vod_id": f"/drama/{book_id}", + "vod_name": book_name, + "vod_pic": cover_url, + "vod_remarks": f"{status_desc} {total_chapters}集" if total_chapters else status_desc + }) + # 构建返回结果 + result = { + "list": videos, + "page": int(current_page), + "pagecount": total_pages, + "limit": len(videos), + "total": total_pages * len(videos) if videos else 0 + } + return result + + def switch(self, key, pg): + # 搜索功能 + search_results = [] + # 获取第一页结果,并检查总页数 + url = f"{self.siteUrl}/search?searchValue={key}&page={pg}" + response = self.fetch(url) + html_content = response.text + # 提取NEXT_DATA JSON数据 + next_data_pattern = r'' + next_data_match = re.search(next_data_pattern, html_content, re.DOTALL) + if next_data_match: + next_data_json = json.loads(next_data_match.group(1)) + page_props = next_data_json.get("props", {}).get("pageProps", {}) + # 获取总页数 + total_pages = page_props.get("pages", 1) + # 处理所有页的数据 + all_book_list = [] + # 添加第一页的书籍列表 + book_list = page_props.get("bookList", []) + all_book_list.extend(book_list) + # 如果有多页,获取其他页的数据 + if total_pages > 1 : # quick模式只获取第一页 + for page in range(2, total_pages + 1): + next_page_url = f"{self.siteUrl}/search?searchValue={key}&page={page}" + next_page_response = self.fetch(next_page_url) + next_page_html = next_page_response.text + next_page_match = re.search(next_data_pattern, next_page_html, re.DOTALL) + if next_page_match: + next_page_json = json.loads(next_page_match.group(1)) + next_page_props = next_page_json.get("props", {}).get("pageProps", {}) + next_page_books = next_page_props.get("bookList", []) + all_book_list.extend(next_page_books) + # 转换为统一的搜索结果格式 + for book in all_book_list: + book_id = book.get("bookId", "") + book_name = book.get("bookName", "") + cover_url = book.get("coverWap", "") + total_chapters = book.get("totalChapterNum", "0") + status_desc = book.get("statusDesc", "") + # 构建视频项 + vod = { + "vod_id": f"/drama/{book_id}", + "vod_name": book_name, + "vod_pic": cover_url, + "vod_remarks": f"{status_desc} {total_chapters}集" + } + search_results.append(vod) + result = { + "list": search_results, + "page": pg + } + return result + + def searchContent(self, key, quick, pg=1): + result = self.switch(key, pg=pg) + result['page'] = pg + return result + + def searchContentPage(self, key, quick, pg=1): + return self.searchContent(key, quick, pg) + + def detailContent(self, ids): + # 获取剧集信息 + vod_id = ids[0] + episode_id = None + chapter_id = None + + if not vod_id.startswith('/drama/'): + if vod_id.startswith('/episode/'): + episode_info = vod_id.replace('/episode/', '').split('/') + if len(episode_info) >= 2: + episode_id = episode_info[0] + chapter_id = episode_info[1] + vod_id = f'/drama/{episode_id}' + else: + vod_id = '/drama/' + vod_id + + drama_url = self.siteUrl + vod_id + print(f"请求URL: {drama_url}") + + 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 Edg/120.0.0.0", + "Referer": self.siteUrl, + "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,en;q=0.8" + } + + rsp = self.fetch(drama_url, headers=headers) + if not rsp or rsp.status_code != 200: + print(f"请求失败,状态码: {getattr(rsp, 'status_code', 'N/A')}") + return {} + + html = rsp.text + next_data_match = re.search(r'', html, re.DOTALL) + + if not next_data_match: + print("未找到NEXT_DATA内容") + return {} + + try: + next_data = json.loads(next_data_match.group(1)) + page_props = next_data.get("props", {}).get("pageProps", {}) + print(f"找到页面属性,包含 {len(page_props.keys())} 个键") + + book_info = page_props.get("bookInfoVo", {}) + chapter_list = page_props.get("chapterList", []) + + title = book_info.get("title", "") + sub_title = f"{book_info.get('totalChapterNum', '')}集" + + categories = [] + for category in book_info.get("categoryList", []): + categories.append(category.get("name", "")) + + vod_content = book_info.get("introduction", "") + + vod = { + "vod_id": vod_id, + "vod_name": title, + "vod_pic": book_info.get("coverWap", ""), + "type_name": ",".join(categories), + "vod_year": "", + "vod_area": book_info.get("countryName", ""), + "vod_remarks": sub_title, + "vod_actor": ", ".join([p.get("name", "") for p in book_info.get("performerList", [])]), + "vod_director": "", + "vod_content": vod_content + } + + # 处理播放列表 + play_url_list = [] + episodes = [] + + if chapter_list: + print(f"找到 {len(chapter_list)} 个章节") + + # 先检查是否有可以直接使用的MP4链接作为模板 + mp4_template = None + first_mp4_chapter_id = None + + # 先搜索第一个章节的MP4链接 + # 为提高成功率,尝试直接请求第一个章节的播放页 + if chapter_list and len(chapter_list) > 0: + first_chapter = chapter_list[0] + first_chapter_id = first_chapter.get("chapterId", "") + drama_id_clean = vod_id.replace('/drama/', '') + + if first_chapter_id and drama_id_clean: + first_episode_url = f"{self.siteUrl}/episode/{drama_id_clean}/{first_chapter_id}" + print(f"请求第一集播放页: {first_episode_url}") + + first_rsp = self.fetch(first_episode_url, headers=headers) + if first_rsp and first_rsp.status_code == 200: + first_html = first_rsp.text + # 直接从HTML提取MP4链接 + mp4_pattern = r'(https?://[^"\']+\.mp4)' + mp4_matches = re.findall(mp4_pattern, first_html) + if mp4_matches: + mp4_template = mp4_matches[0] + first_mp4_chapter_id = first_chapter_id + print(f"找到MP4链接模板: {mp4_template}") + print(f"模板对应的章节ID: {first_mp4_chapter_id}") + + # 如果未找到模板,再检查章节对象中是否有MP4链接 + if not mp4_template: + for chapter in chapter_list[:5]: # 只检查前5个章节以提高效率 + if "chapterVideoVo" in chapter and chapter["chapterVideoVo"]: + chapter_video = chapter["chapterVideoVo"] + mp4_url = chapter_video.get("mp4", "") or chapter_video.get("mp4720p", "") or chapter_video.get("vodMp4Url", "") + if mp4_url and ".mp4" in mp4_url: + mp4_template = mp4_url + first_mp4_chapter_id = chapter.get("chapterId", "") + print(f"从chapterVideoVo找到MP4链接模板: {mp4_template}") + print(f"模板对应的章节ID: {first_mp4_chapter_id}") + break + + # 遍历所有章节处理播放信息 + for chapter in chapter_list: + chapter_id = chapter.get("chapterId", "") + chapter_name = chapter.get("chapterName", "") + + # 1. 如果章节自身有MP4链接,直接使用 + if "chapterVideoVo" in chapter and chapter["chapterVideoVo"]: + chapter_video = chapter["chapterVideoVo"] + mp4_url = chapter_video.get("mp4", "") or chapter_video.get("mp4720p", "") or chapter_video.get("vodMp4Url", "") + if mp4_url and ".mp4" in mp4_url: + episodes.append(f"{chapter_name}${mp4_url}") + continue + + # 2. 如果有MP4模板,尝试替换章节ID构建MP4链接 + if mp4_template and first_mp4_chapter_id and chapter_id: + # 替换模板中的章节ID部分 + if first_mp4_chapter_id in mp4_template: + new_mp4_url = mp4_template.replace(first_mp4_chapter_id, chapter_id) + episodes.append(f"{chapter_name}${new_mp4_url}") + continue + + # 3. 如果上述方法都不可行,回退到使用chapter_id构建中间URL + if chapter_id and chapter_name: + url = f"{vod_id}${chapter_id}${chapter_name}" + episodes.append(f"{chapter_name}${url}") + + if not episodes and vod_id: + # 尝试构造默认的集数 + total_chapters = int(book_info.get("totalChapterNum", "0")) + if total_chapters > 0: + print(f"尝试构造 {total_chapters} 个默认集数") + + # 如果知道章节ID的模式,可以构造 + if chapter_id and episode_id: + for i in range(1, total_chapters + 1): + chapter_name = f"第{i}集" + url = f"{vod_id}${chapter_id}${chapter_name}" + episodes.append(f"{chapter_name}${url}") + else: + # 使用普通的构造方式 + for i in range(1, total_chapters + 1): + chapter_name = f"第{i}集" + url = f"{vod_id}${chapter_name}" + episodes.append(f"{chapter_name}${url}") + + if episodes: + play_url_list.append("#".join(episodes)) + vod['vod_play_from'] = '河马剧场' + vod['vod_play_url'] = '$$$'.join(play_url_list) + + result = { + 'list': [vod] + } + return result + except Exception as e: + print(f"解析详情页失败: {str(e)}") + print(traceback.format_exc()) + return {} + + def playerContent(self, flag, id, vipFlags): + result = {} + print(f"调用playerContent: flag={flag}, id={id}") + + 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 Edg/120.0.0.0", + "Referer": self.siteUrl, + "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,en;q=0.8" + } + + # 解析id参数 + parts = id.split('$') + drama_id = None + chapter_id = None + + if len(parts) >= 2: + drama_id = parts[0] + chapter_id = parts[1] + chapter_name = parts[2] if len(parts) > 2 else "第一集" + print(f"解析参数: drama_id={drama_id}, chapter_id={chapter_id}") + else: + # 处理旧数据格式 + print(f"使用原始URL格式: {id}") + result["parse"] = 0 + result["url"] = id + result["header"] = json.dumps(headers) + return result + + # 直接检查chapter_id是否包含http(可能已经是视频链接) + if 'http' in chapter_id and '.mp4' in chapter_id: + print(f"已经是MP4链接: {chapter_id}") + result["parse"] = 0 + result["url"] = chapter_id + result["header"] = json.dumps(headers) + return result + + # 构建episode页面URL + drama_id_clean = drama_id.replace('/drama/', '') + episode_url = f"{self.siteUrl}/episode/{drama_id_clean}/{chapter_id}" + print(f"请求episode页面: {episode_url}") + + try: + rsp = self.fetch(episode_url, headers=headers) + if not rsp or rsp.status_code != 200: + print(f"请求失败,状态码: {getattr(rsp, 'status_code', 'N/A')}") + result["parse"] = 0 + result["url"] = id + result["header"] = json.dumps(headers) + return result + + html = rsp.text + print(f"获取页面大小: {len(html)} 字节") + + # 尝试从NEXT_DATA提取视频链接 + mp4_url = None + + # 方法1: 从NEXT_DATA提取 + next_data_match = re.search(r'', html, re.DOTALL) + if next_data_match: + try: + print("找到NEXT_DATA") + next_data = json.loads(next_data_match.group(1)) + page_props = next_data.get("props", {}).get("pageProps", {}) + + # 从chapterList中查找当前章节 + chapter_list = page_props.get("chapterList", []) + print(f"找到章节列表,长度: {len(chapter_list)}") + + for chapter in chapter_list: + if chapter.get("chapterId") == chapter_id: + print(f"找到匹配的章节: {chapter.get('chapterName')}") + chapter_video = chapter.get("chapterVideoVo", {}) + mp4_url = chapter_video.get("mp4", "") or chapter_video.get("mp4720p", "") or chapter_video.get("vodMp4Url", "") + if mp4_url: + print(f"从chapterList找到MP4链接: {mp4_url}") + break + + # 如果未找到,尝试从当前章节获取 + if not mp4_url: + current_chapter = page_props.get("chapterInfo", {}) + if current_chapter: + print("找到当前章节信息") + chapter_video = current_chapter.get("chapterVideoVo", {}) + mp4_url = chapter_video.get("mp4", "") or chapter_video.get("mp4720p", "") or chapter_video.get("vodMp4Url", "") + if mp4_url: + print(f"从chapterInfo找到MP4链接: {mp4_url}") + except Exception as e: + print(f"解析NEXT_DATA失败: {str(e)}") + print(traceback.format_exc()) + + # 方法2: 直接从HTML中提取MP4链接 + if not mp4_url: + mp4_pattern = r'(https?://[^"\']+\.mp4)' + mp4_matches = re.findall(mp4_pattern, html) + if mp4_matches: + # 查找含有chapter_id的链接 + matched_mp4 = False + for url in mp4_matches: + if chapter_id in url: + mp4_url = url + matched_mp4 = True + print(f"从HTML直接提取章节MP4链接: {mp4_url}") + break + + # 如果没找到包含chapter_id的链接,使用第一个 + if not matched_mp4 and mp4_matches: + mp4_url = mp4_matches[0] + print(f"从HTML直接提取MP4链接: {mp4_url}") + + if mp4_url and ".mp4" in mp4_url: + print(f"最终找到的MP4链接: {mp4_url}") + result["parse"] = 0 + result["url"] = mp4_url + result["header"] = json.dumps(headers) + return result + else: + print(f"未找到有效的MP4链接,尝试再次解析页面内容") + # 再尝试一次从HTML中广泛搜索所有可能的MP4链接 + all_mp4_pattern = r'(https?://[^"\']+\.mp4)' + all_mp4_matches = re.findall(all_mp4_pattern, html) + if all_mp4_matches: + mp4_url = all_mp4_matches[0] + print(f"从HTML广泛搜索找到MP4链接: {mp4_url}") + result["parse"] = 0 + result["url"] = mp4_url + result["header"] = json.dumps(headers) + return result + + print(f"未找到视频链接,返回原episode URL: {episode_url}") + result["parse"] = 0 + result["url"] = episode_url + result["header"] = json.dumps(headers) + return result + except Exception as e: + print(f"请求或解析失败: {str(e)}") + print(traceback.format_exc()) + result["parse"] = 0 + result["url"] = id + result["header"] = json.dumps(headers) + return result + + def localProxy(self, param): + # 本地代理处理,此处简单返回传入的参数 + return [200, "video/MP2T", {}, param] + + def destroy(self): + # 资源回收 + pass \ No newline at end of file diff --git a/XYQHiker/七新影视.json b/XYQHiker/七新影视.json deleted file mode 100644 index 45855e9..0000000 --- a/XYQHiker/七新影视.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "规则名": "七新影视", - "规则作者": "", - "请求头参数": "手机", - "网页编码格式": "UTF-8", - "图片是否需要代理": "0", - "是否开启获取首页数据": "1", - "首页推荐链接": "http://www.7xdy.com", - "首页列表数组规则": "body&&.stui-vodlist:has(h4)", - "首页片单列表数组规则": "li", - "首页片单是否Jsoup写法": "1", - "分类起始页码": "1", - "分类链接": "http://www.7xdy.com/{cateId}/index{catePg}.html[firstPage=http://www.7xdy.com/{cateId}/index.html]", - "分类名称": "电影&电视剧&综艺&动漫", - "分类名称替换词": "dianyingpian&dianshiju&zongyi&dongman", - //"筛选数据": {}, - "筛选数据": "ext", - //{cateId} - "筛选子分类名称": "动作片&爱情片&科幻片&恐怖片&战争片&喜剧片&一直播&剧情片||国产剧&港台剧&欧美剧&日韩剧", - "筛选子分类替换词": "dongzuopian&aiqingpian&kehuanpian&kongbupian&zhanzhengpian&xijupian&jilupian&juqingpian||guocanju&gangtaiju&oumeiju&rihanju", - //{class} - "筛选类型名称": "", - "筛选类型替换词": "*", - //{area} - "筛选地区名称": "", - "筛选地区替换词": "*", - //{year} - "筛选年份名称": "", - "筛选年份替换词": "*", - //{lang} - "筛选语言名称": "", - "筛选语言替换词": "*", - //{by} - "筛选排序名称": "时间&人气&评分", - "筛选排序替换词": "time&hits&score", - "分类截取模式": "1", - "分类列表数组规则": ".stui-vodlist&&li", - "分类片单是否Jsoup写法": "1", - "分类片单标题": "h4&&a&&Text", - "分类片单链接": "h4&&a&&href", - "分类片单图片": ".lazyload&&data-original", - "分类片单副标题": ".pic-text&&Text", - "分类片单链接加前缀": "http://www.7xdy.com", - "分类片单链接加后缀": "", - "搜索请求头参数": "User-Agent$手机", - "搜索链接": "http://www.7xdy.com/search.php?page=1&searchword={wd}&searchtype=", - "POST请求数据": "searchword={wd}", - "搜索截取模式": "1", - "搜索列表数组规则": ".stui-vodlist__media&&li", - "搜索片单是否Jsoup写法": "1", - "搜索片单图片": ".lazyload&&data-original", - "搜索片单标题": "h3&&a&&Text", - "搜索片单链接": "h3&&a&&href", - "搜索片单副标题": ".pic-text&&Text", - "搜索片单链接加前缀": "http://www.7xdy.com", - "搜索片单链接加后缀": "", - "链接是否直接播放": "0", - "直接播放链接加前缀": "", - "直接播放链接加后缀": "", - "直接播放直链视频请求头": "", - "详情是否Jsoup写法": "0", - "类型详情": "类型:&&", - "年代详情": "年份:&&", - "地区详情": "地区:&&", - "演员详情": "主演:&&

", - "简介详情": "简介:&&

", - "线路列表数组规则": "body&&#playlist", - "线路标题": "h3&&Text", - "播放列表数组规则": "body&&.stui-content__playlist", - "选集列表数组规则": "li", - "选集标题链接是否Jsoup写法": "1", - "选集标题": "a&&Text", - "选集链接": "a&&href", - "是否反转选集序列": "1", - "选集链接加前缀": "http://www.7xdy.com", - "选集链接加后缀": "", - "分析MacPlayer": "0", - "是否开启手动嗅探": "1", - "手动嗅探视频链接关键词": ".mp4#.m3u8#.flv#video/tos#pt=m3u8#obj/tos-#video/tos#mime_type=video#x-oss-signature=", - "手动嗅探视频链接过滤词": ".html#=http" -} \ No newline at end of file diff --git a/api.json b/api.json index f6ac523..d18b0ce 100644 --- a/api.json +++ b/api.json @@ -89,6 +89,29 @@ "filterable": 1, "ext": "http://cmsyt114.lyyytv.cn/api.php/app/" }, + { + "key": "乐享影视", + "name": "乐享|影视", + "type": 3, + "api": "csp_AppYsV2", + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "ext": "http://114.66.55.28:8818/api.php/app/" + }, + { + "key": "金牌影视", + "name": "金牌|影视", + "type": 3, + "api": "./py/金牌影视.py", + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "playerType": 2, + "ext": { + "site": "https://www.hkybqufgh.com,https://www.sizhengxt.com,https://0996zp.com,https://9zhoukj.com/,https://www.sizhengxt.com,https://www.tjrongze.com,https://www.jiabaide.cn,https://cqzuoer.com" + } + }, { "key": "哔哩视频", "name": "哔哩|视频", @@ -198,17 +221,6 @@ "changeable": 1, "ext": "./json/lb.json?" }, - { - "key": "小米", - "name": "小米|4K弹幕", - "type": 3, - "api": "csp_PanWebShare", - "searchable": 1, - "quickSearch": 1, - "filterable": 1, - "changeable": 1, - "ext": "./json/xm.json?" - }, { "key": "至臻", "name": "至臻|4K弹幕", @@ -418,10 +430,23 @@ "key": "河马短剧", "name": "河马|短剧", "type": 3, - "api": "csp_AppHMDJ", + "api": "./py/河马短剧.py", "searchable": 1, - "quickSearch": 0, - "filterable": 0 + "changeable": 1, + "quickSearch": 1, + "filterable": 1, + "playerType": 2 + }, + { + "key": "偷乐短剧", + "name": "偷乐|短剧", + "type": 3, + "api": "./py/偷乐短剧.py", + "searchable": 1, + "changeable": 1, + "quickSearch": 1, + "filterable": 1, + "playerType": 2 }, { "key": "爱看短剧", @@ -434,16 +459,6 @@ "filterable": 1, "playerType": 2 }, - { - "key": "爱我短剧", - "name": "爱我|短剧", - "type": 3, - "api": "csp_XBPQ", - "searchable": 1, - "quickSearch": 1, - "filterable": 1, - "ext": "./XBPQ/爱我短剧.json" - }, { "key": "短剧网", "name": "短剧网|短剧", @@ -699,19 +714,6 @@ "filterable": 1, "ext": "https://cs.hgyx.vip/api2/api.php/app/" }, - { - "key": "金牌影视", - "name": "金牌|影视", - "type": 3, - "api": "./py/金牌影视.py", - "searchable": 1, - "quickSearch": 1, - "filterable": 1, - "playerType": 2, - "ext": { - "site": "https://www.hkybqufgh.com,https://www.sizhengxt.com,https://0996zp.com,https://9zhoukj.com/,https://www.sizhengxt.com,https://www.tjrongze.com,https://www.jiabaide.cn,https://cqzuoer.com" - } - }, { "key": "猎手影视", "name": "猎手|APP", @@ -1287,16 +1289,6 @@ "filterable": 1, "ext": "./XYQHiker/看看影视.json" }, - { - "key": "七新影视", - "name": "七新|影视", - "type": 3, - "api": "csp_XYQHiker", - "searchable": 1, - "quickSearch": 1, - "filterable": 1, - "ext": "./XYQHiker/七新影视.json" - }, { "key": "骚火影视", "name": "骚火|影视", @@ -1433,40 +1425,6 @@ "欧美动漫" ] }, - { - "key": "快车资源", - "name": "快车|采集", - "type": 1, - "api": "https://caiji.kczyapi.com/api.php/provide/vod/", - "searchable": 1, - "changeable": 1, - "categories": [ - "动作片", - "喜剧片", - "爱情片", - "科幻片", - "恐怖片", - "战争片", - "剧情片", - "动画片", - "纪录片", - "国产剧", - "香港剧", - "台湾剧", - "欧美剧", - "韩国剧", - "日本剧", - "泰国剧", - "海外剧", - "国产动漫", - "日本动漫", - "欧美动漫", - "大陆综艺", - "日韩综艺", - "港台综艺", - "欧美综艺" - ] - }, { "key": "索尼资源", "name": "索尼|采集", @@ -2197,6 +2155,64 @@ } } }, + { + "name": "钓鱼", + "type": "1", + "url": "http://8.129.30.117:8117/diaoyu.php?url=", + "ext": { + "flag": [ + "qq", + "腾讯", + "qiyi", + "爱奇艺", + "奇艺", + "youku", + "优酷", + "sohu", + "搜狐", + "letv", + "乐视", + "mgtv", + "芒果", + "tnmb", + "seven", + "bilibili", + "1905" + ], + "header": { + "User-Agent": "okhttp/4.9.1" + } + } + }, + { + "name": "无上", + "type": "1", + "url": "https://mfjx.iwsyy.xyz/?url=", + "ext": { + "flag": [ + "qq", + "腾讯", + "qiyi", + "爱奇艺", + "奇艺", + "youku", + "优酷", + "sohu", + "搜狐", + "letv", + "乐视", + "mgtv", + "芒果", + "tnmb", + "seven", + "bilibili", + "1905" + ], + "header": { + "User-Agent": "okhttp/4.9.1" + } + } + }, { "name": "臻享", "type": "1", diff --git a/spider.jar b/spider.jar index 2696c4a..be1e881 100644 Binary files a/spider.jar and b/spider.jar differ