diff --git a/FGBLH/Web鱼壳海豚.json b/FGBLH/Web鱼壳海豚.json index e95564cb..1edb395c 100644 --- a/FGBLH/Web鱼壳海豚.json +++ b/FGBLH/Web鱼壳海豚.json @@ -134,6 +134,18 @@ "api":"csp_yt", "homePage":"https://fgblh.github.io/uhuj.github.io/youtube.html" }, + { + "key": "视觉影院", + "name": "🐬视觉影院.py[追剧]", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/视觉影院.py" + }, + { + "key": "袋鼠影视", + "name": "🐬袋鼠影视.py[追剧]", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/袋鼠影视.py" + }, { "key": "ddvm", "name": "🐬嘀嗒影视.py(关梯)[追剧]", @@ -487,12 +499,6 @@ "type": 3, "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/小鸭子看看.py" }, - { - "key": "fY", - "name": "🐬枫叶影院.py(关梯)[追剧]", - "type": 3, - "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/枫叶影院.py" - }, { "key":"6v", "name":"🐬6V影视[追剧][html]", @@ -647,6 +653,12 @@ "成长逆袭" ] }, + { + "key": "喜福网", + "name": "🐬喜福短剧.py[短剧]", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/喜福短剧.py" + }, { "key": "smdj", "name": "🐬星芽短剧.py[短剧]", @@ -1128,6 +1140,13 @@ "type":3, "api":"csp_wbbb", "homePage":"https://fgblh.github.io/uhuj.github.io/javdb.html" + }, + { + "key":"WhoStv.", + "name":"🐬WhoStv|🔞[成人][html]", + "type":3, + "api":"csp_wbbb", + "homePage":"https://fgblh.github.io/uhuj.github.io/WhoStv.html" }, { "key": "采集聚合成人", diff --git a/FGBLH/Web鱼壳海豚py.json b/FGBLH/Web鱼壳海豚py.json index 8e0be3a8..b2693165 100644 --- a/FGBLH/Web鱼壳海豚py.json +++ b/FGBLH/Web鱼壳海豚py.json @@ -65,6 +65,18 @@ "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/油管.py" }, { + "key": "视觉影院", + "name": "🐬视觉影院.py[追剧]", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/视觉影院.py" + }, + { + "key": "袋鼠影视", + "name": "🐬袋鼠影视.py[追剧]", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/袋鼠影视.py" + }, + { "key": "ppx", "name": "🐬皮皮虾.py[追剧]", "type": 3, @@ -389,18 +401,18 @@ "type": 3, "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/采集聚合.py" }, - { - "key": "fY", - "name": "🐬枫叶影院.py(关梯)[追剧]", - "type": 3, - "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/枫叶影院.py" - }, { "key": "MiFun", "name": "🐬MiFun动漫.py[动漫]", "type": 3, "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/MiFun动漫.py" }, + { + "key": "喜福网", + "name": "🐬喜福短剧.py[短剧]", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/喜福短剧.py" + }, { "key": "smdj", "name": "🐬星芽短剧.py[短剧]", diff --git a/FGBLH/Web鱼壳海豚无18加.json b/FGBLH/Web鱼壳海豚无18加.json index dd80d7f2..26a666fb 100644 --- a/FGBLH/Web鱼壳海豚无18加.json +++ b/FGBLH/Web鱼壳海豚无18加.json @@ -127,6 +127,18 @@ "type": 3, "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/油管直播.py" }, + { + "key": "视觉影院", + "name": "🐬视觉影院.py", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/视觉影院.py" + }, + { + "key": "袋鼠影视", + "name": "🐬袋鼠影视.py", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/袋鼠影视.py" + }, { "key": "ppx", "name": "🐬皮皮虾.py", @@ -468,12 +480,6 @@ "type": 3, "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/采集聚合.py" }, - { - "key": "fY", - "name": "🐬枫叶影院.py(关梯子使用)", - "type": 3, - "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/枫叶影院.py" - }, { "key":"FY", "name":"🐬枫叶影院(关梯子使用)", @@ -543,189 +549,6 @@ "type":3, "api":"csp_gy", "homePage":"https://fgblh.github.io/uhuj.github.io/观影.html" - }, - { - "key": "非凡", - "name": "🐬非凡影视", - "type": 1, - "api": "http://cj.ffzyapi.com/api.php/provide/vod/", - "searchable": 1, - "changeable": 1, - "categories": [ - "国产动漫", - "日韩动漫", - "国产剧", - "韩国剧", - "日本剧", - "电影片", - "连续剧", - "综艺片", - "动漫片", - "动作片", - "喜剧片", - "爱情片", - "科幻片", - "恐怖片", - "剧情片", - "战争片", - "香港剧", - "欧美剧", - "记录片", - "台湾剧", - "海外剧", - "泰国剧", - "大陆综艺", - "港台综艺", - "日韩综艺", - "欧美综艺", - "欧美动漫", - "港台动漫", - "海外动漫" - ] - }, - { - "key": "闪电影视", - "name": "🐬闪电影视|追剧", - "type": 1, - "api": "http://sdzyapi.com/api.php/provide/vod/", - "searchable": 1, - "quickSearch": 1, - "categories": [ - "国产剧", - "短剧", - "韩国剧", - "香港剧", - "台湾剧", - "欧美剧", - "动作片", - "科幻片", - "战争片", - "奇幻片", - "喜剧片", - "爱情片", - "恐怖片", - "犯罪片", - "悬疑片", - "惊悚片", - "剧情片", - "冒险片", - "记录片", - "动作片", - "日本剧", - "泰剧", - "国产综艺", - "港台综艺", - "欧美综艺", - "日韩综艺", - "国产动漫", - "港台动漫", - "日韩动漫" - ] - }, - { - "key": "牛牛影视", - "name": "🐬牛牛影视|追剧", - "type": 0, - "api": "https://api.niuniuzy.me/api.php/provide/vod/at/xml", - "searchable": 1, - "quickSearch": 1, - "categories": [ - "动作片", - "喜剧片", - "爱情片", - "科幻片", - "恐怖片", - "剧情片", - "战争片", - "动画片", - "纪录片", - "预告片", - "邵氏电影", - "4K电影", - "国产剧", - "欧美剧", - "韩剧", - "日剧", - "港剧", - "台剧", - "泰剧", - "海外剧", - "国产动漫", - "日韩动漫", - "欧美动漫", - "港台动漫", - "海外动漫", - "影视解说", - "爽文短剧", - "有声动漫", - "女频恋爱", - "反转爽剧", - "古装仙侠", - "年代穿越", - "脑洞悬疑", - "现代都市", - "演唱会", - "大陆综艺", - "日韩综艺", - "港台综艺", - "欧美综艺", - "篮球", - "足球" - ] - }, - { - "key": "雲飛影视", - "name": "🐬雲飛影视|追剧", - "type": 1, - "api": "http://cj.lziapi.com/api.php/provide/vod/", - "searchable": 1, - "quickSearch": 1, - "filterable": 0, - "playurl": "json:https://lziplayer.com/?url=", - "categories": [ - "国产剧", - "国产动漫", - "泰国剧", - "小湾剧", - "香港剧", - "欧美剧", - "韩国剧", - "日本剧", - "动漫", - "体育", - "加片", - "动作片", - "爱情片", - "喜剧片" - ] - }, -{"key": "火狐","name": "🐬火狐影视🦊|追剧","type": 1,"api": "https://hhzyapi.com/api.php/provide/vod/","searchable": 1,"quickSearch": 0,"filterable": 1,"categories": [ "内地剧", "动作片", "科幻片", "战争片", "喜剧片", "爱情片", "恐怖片", "犯罪片", "剧情片", "冒险片", "记录片", "韩剧", "香港剧", "台湾剧", "欧美剧", "日剧", "马泰剧", "体育赛事", "综艺", "动画片", "中国动漫", "日本动漫", "欧美动漫"] -}, - { - "key": "量子2k", - "name": "🐬量子影视|追剧", - "type": 1, - "api": "http://cj.lziapi.com/api.php/provide/vod/", - "searchable": 1, - "quickSearch": 1, - "filterable": 0, - "playurl": "json:https://lziplayer.com/?url=", - "categories": [ - "国产剧", - "国产动漫", - "泰国剧", - "台湾剧", - "香港剧", - "欧美剧", - "韩国剧", - "日本剧", - "动漫", - "体育", - "剧情片", - "动作片", - "爱情片", - "喜剧片" - ] }, { "key": "API_如意", @@ -798,6 +621,12 @@ "成长逆袭" ] }, + { + "key": "喜福网", + "name": "🐬喜福短剧.py", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/喜福短剧.py" + }, { "key": "smdj", "name": "🐬星芽短剧.py", diff --git a/FGBLH/ok海豚.json b/FGBLH/ok海豚.json index d7af8ec5..758e99af 100644 --- a/FGBLH/ok海豚.json +++ b/FGBLH/ok海豚.json @@ -87,6 +87,18 @@ "type": 3, "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/油管.py" }, + { + "key": "视觉影院", + "name": "🐬视觉影院.py", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/视觉影院.py" + }, + { + "key": "袋鼠影视", + "name": "🐬袋鼠影视.py", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/袋鼠影视.py" + }, { "key": "4K影视", "name": "🐬4K影视.py", @@ -575,6 +587,12 @@ "成长逆袭" ] }, + { + "key": "喜福网", + "name": "🐬喜福短剧.py", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/喜福短剧.py" + }, { "key": "smdj", "name": "🐬星芽短剧.py", diff --git a/FGBLH/ok海豚py.json b/FGBLH/ok海豚py.json index 6964deba..898801de 100644 --- a/FGBLH/ok海豚py.json +++ b/FGBLH/ok海豚py.json @@ -46,10 +46,16 @@ "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/油管.py" }, { - "key": "fY", - "name": "🐬枫叶影院.py(关梯子使用)", + "key": "视觉影院", + "name": "🐬视觉影院.py", "type": 3, - "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/枫叶影院.py" + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/视觉影院.py" + }, + { + "key": "袋鼠影视", + "name": "🐬袋鼠影视.py", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/袋鼠影视.py" }, { "key": "ddvm", @@ -418,6 +424,12 @@ "type": 3, "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/MiFun动漫.py" }, + { + "key": "喜福网", + "name": "🐬喜福短剧.py", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/喜福短剧.py" + }, { "key": "smdj", "name": "🐬星芽短剧.py", diff --git a/FGBLH/ok海豚无18加.json b/FGBLH/ok海豚无18加.json index f959651b..f28070f2 100644 --- a/FGBLH/ok海豚无18加.json +++ b/FGBLH/ok海豚无18加.json @@ -87,6 +87,18 @@ "type": 3, "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/油管.py" }, + { + "key": "视觉影院", + "name": "🐬视觉影院.py", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/视觉影院.py" + }, + { + "key": "袋鼠影视", + "name": "🐬袋鼠影视.py", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/袋鼠影视.py" + }, { "key": "4K影视", "name": "🐬4K影视.py", @@ -224,12 +236,6 @@ "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/jar_js/布布追剧.js", "changeable": 0 }, - { - "key": "fY", - "name": "🐬枫叶影院(关梯子使用)", - "type": 3, - "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/枫叶影院.py" - }, { "key": "hxq", "name": "🐬韩小圈.py(关梯)", @@ -732,6 +738,12 @@ "成长逆袭" ] }, + { + "key": "喜福网", + "name": "🐬喜福短剧.py", + "type": 3, + "api": "https://ghfast.top/https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/py/喜福短剧.py" + }, { "key": "smdj", "name": "🐬星芽短剧.py", diff --git a/FGBLH/py/喜福短剧.py b/FGBLH/py/喜福短剧.py new file mode 100644 index 00000000..17f83e93 --- /dev/null +++ b/FGBLH/py/喜福短剧.py @@ -0,0 +1,233 @@ +# coding=utf-8 +# !/usr/bin/python + +from Crypto.Util.Padding import unpad, pad +from Crypto.Cipher import ARC4, AES +from urllib.parse import unquote, quote +from base.spider import Spider +from datetime import datetime +from bs4 import BeautifulSoup +from base64 import b64decode +import urllib.request +import urllib.parse +import binascii +import requests +import hashlib +import base64 +import uuid +import hmac +import json +import time +import sys +import re +import os + +sys.path.append('..') + +xurl = "https://minidrama-api.contentchina.com" + +headerx = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36' + } + +headers = { + 'Accept': '*/*', + 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6', + 'Cache-Control': 'no-cache', + 'Connection': 'keep-alive', + 'Origin': 'https://minidrama.contentchina.com', + 'Pragma': 'no-cache', + 'Referer': 'https://minidrama.contentchina.com/', + 'Sec-Fetch-Dest': 'empty', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Site': 'cross-site', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0', + 'sec-ch-ua': '"Microsoft Edge";v="143", "Chromium";v="143", "Not A(Brand";v="24"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"Windows"', + } + +class Spider(Spider): + + def getName(self): + return "🌷" + + def init(self, extend): + pass + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + def homeContent(self, filter): + result = {"class": []} + def get_category_data(): + url = f"{xurl}/web/v1/home/categoryList?isLeft=1" + response = requests.get(url=url, headers=headerx) + response.encoding = "utf-8" + return response.json() + def process_categories(data): + categories = [] + for vod in data['data']['categories']: + category_info = { + "type_id": vod['id'], + "type_name": f"🌷{vod['name']}" + } + categories.append(category_info) + return categories + def build_result(categories): + return {"class": categories} + data = get_category_data() + categories = process_categories(data) + result = build_result(categories) + return result + + def homeVideoContent(self): + pass + + def categoryContent(self, cid, pg, filter, ext): + def get_page_number(): + return int(pg) if pg else 1 + def fetch_category_data(page_number): + url = f'{xurl}/web/v1/drama/list?pageSize=24¤tPage={str(page_number)}&filterCategories[]={cid}' + response = requests.get(url=url, headers=headerx) + response.encoding = "utf-8" + return response.json() + def parse_videos(data): + video_list = [] + for vod in data['data']['data']: + video_info = { + "vod_id": f"{vod['albumId']}@{vod['total']}", + "vod_name": vod['title'], + "vod_pic": vod['coverUrl'], + "vod_remarks": f"🌷共{vod.get('total', '暂无备注')}集" + } + video_list.append(video_info) + return video_list + def build_result(video_list, page_number): + return { + 'list': video_list, + 'page': page_number, + 'pagecount': 9999, + 'limit': 90, + 'total': 999999 + } + current_page = get_page_number() + response_data = fetch_category_data(current_page) + parsed_videos = parse_videos(response_data) + result = build_result(parsed_videos, current_page) + return result + + def detailContent(self, ids): + def parse_ids(): + did = ids[0] + parts = did.split("@") + return parts[0], int(parts[1]) + def generate_play_items(base_id, total_count): + return [f"{i}${base_id}@{i}" for i in range(1, total_count + 1)] + def build_play_url(items): + return "#".join(items) + def create_video_info(did, play_url): + return { + "vod_id": did, + "vod_play_from": "喜福专线", + "vod_play_url": play_url + } + def build_result(video_info): + return {'list': [video_info]} + base_id, total_count = parse_ids() + play_items = generate_play_items(base_id, total_count) + play_url = build_play_url(play_items) + video_info = create_video_info(ids[0], play_url) + result = build_result(video_info) + return result + + def playerContent(self, flag, id, vipFlags): + def parse_video_id(): + parts = id.split("@") + return parts[0], parts[1] + def get_play_auth(album_id, seq): + url = f'{xurl}/web/v1/drama/play_auth?albumId={album_id}&seq={seq}' + response = requests.get(url=url, headers=headerx) + response.encoding = "utf-8" + return response.json() + def extract_credentials(data): + video_id = data['data']['vid'] + play_auth_b64 = data['data']['playAuth'] + play_auth_json = base64.b64decode(play_auth_b64).decode('utf-8') + return json.loads(play_auth_json), video_id + def build_request_params(credentials, video_id): + params = { + 'Action': 'GetPlayInfo', + 'Version': '2017-03-21', + 'Format': 'JSON', + 'AccessKeyId': credentials['AccessKeyId'], + 'SecurityToken': credentials['SecurityToken'], + 'VideoId': video_id, + 'AuthInfo': credentials.get('AuthInfo', ''), + 'Timestamp': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'), + 'SignatureMethod': 'HMAC-SHA1', + 'SignatureVersion': '1.0', + 'SignatureNonce': str(uuid.uuid4()), + } + if 'PlayConfig' in credentials: + params['PlayConfig'] = json.dumps(credentials.get('PlayConfig')) + return params + def generate_signature(params, credentials): + sorted_params = sorted(params.items()) + canonicalized_query_string = '&'.join( + [f"{urllib.parse.quote(k, safe='')}={urllib.parse.quote(str(v), safe='')}" for k, v in sorted_params]) + string_to_sign = f"GET&%2F&{urllib.parse.quote(canonicalized_query_string, safe='')}" + key = credentials['AccessKeySecret'] + "&" + signature = hmac.new(key.encode('utf-8'), string_to_sign.encode('utf-8'), hashlib.sha1).digest() + return base64.b64encode(signature).decode('utf-8'), canonicalized_query_string + def get_final_play_url(credentials, canonicalized_query_string, signature_b64): + final_url = f"https://vod.{credentials.get('Region', 'cn-shanghai')}.aliyuncs.com/?{canonicalized_query_string}&Signature={urllib.parse.quote(signature_b64, safe='')}" + response = requests.get(url=final_url, headers=headers) + response.encoding = "utf-8" + data = response.json() + return data['PlayInfoList']['PlayInfo'][0]['PlayURL'] + def build_result(play_url): + return { + "parse": 0, + "playUrl": '', + "url": play_url, + "header": headerx + } + album_id, seq = parse_video_id() + auth_data = get_play_auth(album_id, seq) + credentials, video_id = extract_credentials(auth_data) + request_params = build_request_params(credentials, video_id) + signature_b64, canonicalized_query_string = generate_signature(request_params, credentials) + play_url = get_final_play_url(credentials, canonicalized_query_string, signature_b64) + result = build_result(play_url) + return result + + def searchContentPage(self, key, quick, pg): + pass + + def searchContent(self, key, quick, pg="1"): + return self.searchContentPage(key, quick, '1') + + 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 + + + + + + + + + + + + diff --git a/FGBLH/py/枫叶影院.py b/FGBLH/py/枫叶影院.py deleted file mode 100644 index 81130bf9..00000000 --- a/FGBLH/py/枫叶影院.py +++ /dev/null @@ -1,392 +0,0 @@ -# -*- coding: utf-8 -*- -import re, urllib.parse -import json -from bs4 import BeautifulSoup -import requests -from base.spider import Spider as BaseSpider - - -class Spider(BaseSpider): - def init(self, extend=""): - 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", - "Accept-Language": "zh-CN,zh;q=0.9", - } - - def getName(self): - return '枫叶影院' - - def homeContent(self, filter): - return {"class": [ - {'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": "综艺"}, - ], "filters": self._build_filters()} - - def _build_filters(self): - area = [{"n": "全部", "v": ""}, {"n": "大陆", "v": "大陆"}, {"n": "香港", "v": "香港"}, - {"n": "台湾", "v": "台湾"}, {"n": "美国", "v": "美国"}, {"n": "韩国", "v": "韩国"}, - {"n": "日本", "v": "日本"}, {"n": "泰国", "v": "泰国"}, {"n": "新加坡", "v": "新加坡"}, - {"n": "马来西亚", "v": "马来西亚"}, {"n": "印度", "v": "印度"}, {"n": "英国", "v": "英国"}, - {"n": "法国", "v": "法国"}, {"n": "加拿大", "v": "加拿大"}, {"n": "西班牙", "v": "西班牙"}, - {"n": "俄罗斯", "v": "俄罗斯"}, {"n": "其它", "v": "其它"}] - year = [{"n": "全部", "v": ""}, {"n": "2026", "v": "2026"}, {"n": "2025", "v": "2025"}, - {"n": "2024", "v": "2024"}, {"n": "2023", "v": "2023"}, {"n": "2022", "v": "2022"}, - {"n": "2021", "v": "2021"}, {"n": "2020", "v": "2020"}, {"n": "2019", "v": "2019"}, - {"n": "2018", "v": "2018"}, {"n": "2017", "v": "2017"}, {"n": "2016", "v": "2016"}, - {"n": "2015", "v": "2015"}, {"n": "2014", "v": "2014"}, {"n": "2013", "v": "2013"}, - {"n": "2012", "v": "2012"}, {"n": "2011", "v": "2011"}, {"n": "2010", "v": "2010"}, - {"n": "2009", "v": "2009"}, {"n": "2008", "v": "2008"}, {"n": "2007", "v": "2007"}, - {"n": "2006", "v": "2006"}, {"n": "2005", "v": "2005"}, {"n": "2004", "v": "2004"}] - lang = [{"n": "全部", "v": ""}, {"n": "国语", "v": "国语"}, {"n": "英语", "v": "英语"}, - {"n": "粤语", "v": "粤语"}, {"n": "闽南语", "v": "闽南语"}, {"n": "韩语", "v": "韩语"}, - {"n": "日语", "v": "日语"}, {"n": "法语", "v": "法语"}, {"n": "德语", "v": "德语"}, - {"n": "其它", "v": "其它"}] - sort = [{"n": "时间", "v": "time"}, {"n": "人气", "v": "hits"}, {"n": "评分", "v": "score"}] - letter = [{"n": "全部", "v": ""}, {"n": "A", "v": "A"}, {"n": "B", "v": "B"}, {"n": "C", "v": "C"}, - {"n": "D", "v": "D"}, {"n": "E", "v": "E"}, {"n": "F", "v": "F"}, {"n": "G", "v": "G"}, - {"n": "H", "v": "H"}, {"n": "I", "v": "I"}, {"n": "J", "v": "J"}, {"n": "K", "v": "K"}, - {"n": "L", "v": "L"}, {"n": "M", "v": "M"}, {"n": "N", "v": "N"}, {"n": "O", "v": "O"}, - {"n": "P", "v": "P"}, {"n": "Q", "v": "Q"}, {"n": "R", "v": "R"}, {"n": "S", "v": "S"}, - {"n": "T", "v": "T"}, {"n": "U", "v": "U"}, {"n": "V", "v": "V"}, {"n": "W", "v": "W"}, - {"n": "X", "v": "X"}, {"n": "Y", "v": "Y"}, {"n": "Z", "v": "Z"}, {"n": "0-9", "v": "0-9"}] - return { - "2": [ - {"key": "class", "name": "类型", - "value": [{"n": "全部", "v": "2"}, {"n": "国产剧", "v": "13"}, {"n": "日韩剧", "v": "15"}, - {"n": "海外剧", "v": "16"}]}, - {"key": "area", "name": "地区", "value": area}, - {"key": "genre", "name": "剧情", "value": [{"n": v[0], "v": v[1]} for v in - [("全部", ""), ("古装", "古装"), ("战争", "战争"), - ("青春偶像", "青春偶像"), ("喜剧", "喜剧"), - ("家庭", "家庭"), ("犯罪", "犯罪"), ("动作", "动作"), - ("奇幻", "奇幻"), ("剧情", "剧情"), ("历史", "历史"), - ("经典", "经典"), ("乡村", "乡村"), ("情景", "情景"), - ("商战", "商战"), ("网剧", "网剧"), ("其他", "其他")]]}, - {"key": "year", "name": "年份", "value": year}, - {"key": "lang", "name": "语言", "value": lang}, - {"key": "letter", "name": "字母", "value": letter}, - {"key": "sort", "name": "排序", "value": sort}, - ], - "1": [ - {"key": "class", "name": "类型", - "value": [{"n": "全部", "v": "1"}, {"n": "动作片", "v": "6"}, {"n": "喜剧片", "v": "7"}, - {"n": "恐怖片", "v": "8"}, {"n": "科幻片", "v": "9"}, {"n": "爱情片", "v": "10"}, - {"n": "剧情片", "v": "11"}, {"n": "战争片", "v": "12"}, {"n": "纪录片", "v": "20"}]}, - {"key": "area", "name": "地区", "value": area}, - {"key": "genre", "name": "剧情", "value": [{"n": v[0], "v": v[1]} for v in - [("全部", ""), ("喜剧", "喜剧"), ("爱情", "爱情"), - ("恐怖", "恐怖"), ("动作", "动作"), ("科幻", "科幻"), - ("剧情", "剧情"), ("战争", "战争"), ("警匪", "警匪"), - ("犯罪", "犯罪"), ("动画", "动画"), ("奇幻", "奇幻"), - ("武侠", "武侠"), ("冒险", "冒险"), ("枪战", "枪战"), - ("悬疑", "悬疑"), ("惊悚", "惊悚"), ("经典", "经典"), - ("青春", "青春"), ("文艺", "文艺"), ("微电影", "微电影"), - ("古装", "古装"), ("历史", "历史"), ("运动", "运动"), - ("农村", "农村"), ("儿童", "儿童"), - ("网络电影", "网络电影")]]}, - {"key": "year", "name": "年份", "value": year}, - {"key": "lang", "name": "语言", "value": lang}, - {"key": "letter", "name": "字母", "value": letter}, - {"key": "sort", "name": "排序", "value": sort}, - ], - "4": [ - {"key": "class", "name": "类型", - "value": [{"n": "全部", "v": "4"}, {"n": "国产动漫", "v": "25"}, {"n": "日韩动漫", "v": "26"}]}, - {"key": "genre", "name": "剧情", "value": [{"n": v[0], "v": v[1]} for v in - [("全部", ""), ("情感", "情感"), ("科幻", "科幻"), - ("热血", "热血"), ("推理", "推理"), ("搞笑", "搞笑"), - ("冒险", "冒险"), ("奇幻", "奇幻"), ("战斗", "战斗"), - ("校园", "校园"), ("萝莉", "萝莉"), ("治愈", "治愈"), - ("原创", "原创"), ("亲子", "亲子"), ("益智", "益智"), - ("励志", "励志"), ("其他", "其他")]]}, - {"key": "area", "name": "地区", - "value": [{"n": "全部", "v": ""}, {"n": "大陆", "v": "大陆"}, {"n": "香港", "v": "香港"}, - {"n": "台湾", "v": "台湾"}, {"n": "美国", "v": "美国"}, {"n": "韩国", "v": "韩国"}, - {"n": "日本", "v": "日本"}, {"n": "法国", "v": "法国"}, {"n": "英国", "v": "英国"}, - {"n": "其它", "v": "其它"}]}, - {"key": "year", "name": "年份", "value": year}, - {"key": "lang", "name": "语言", "value": lang}, - {"key": "letter", "name": "字母", "value": letter}, - {"key": "sort", "name": "排序", "value": sort}, - ], - "3": [ - {"key": "class", "name": "类型", - "value": [{"n": "全部", "v": "3"}, {"n": "大陆综艺", "v": "21"}, {"n": "日韩综艺", "v": "22"}]}, - {"key": "genre", "name": "剧情", "value": [{"n": v[0], "v": v[1]} for v in - [("全部", ""), ("选秀", "选秀"), ("情感", "情感"), - ("访谈", "访谈"), ("播报", "播报"), ("音乐", "音乐"), - ("美食", "美食"), ("旅游", "旅游"), ("搞笑", "搞笑"), - ("游戏", "游戏"), ("亲子", "亲子"), ("其它", "其它")]]}, - {"key": "area", "name": "地区", - "value": [{"n": "全部", "v": ""}, {"n": "大陆", "v": "大陆"}, {"n": "香港", "v": "香港"}, - {"n": "台湾", "v": "台湾"}, {"n": "美国", "v": "美国"}, {"n": "韩国", "v": "韩国"}, - {"n": "日本", "v": "日本"}, {"n": "英国", "v": "英国"}, {"n": "其它", "v": "其它"}]}, - {"key": "year", "name": "年份", "value": year}, - {"key": "lang", "name": "语言", "value": lang}, - {"key": "letter", "name": "字母", "value": letter}, - {"key": "sort", "name": "排序", "value": sort}, - ], - } - - def homeVideoContent(self): - html = self._fetch('/') - return {"list": self._parse_video_list(html)} - - def categoryContent(self, tid, pg, filter, extend): - # 构建筛选参数:参照歪比巴卜,直接取extend里的值,fallback到filter - if tid.startswith('/label'): - url = f'{tid}/page/{pg}.html' - html = self._fetch(url) - items = self._parse_video_list(html) - page = int(pg) - page_count = page if len(items) < 24 else page + 2 - return {"list": items, "page": page, "pagecount": page_count, "limit": 24, "total": page_count * 24} - - args = {} - if extend and isinstance(extend, dict): - for k, v in extend.items(): - if v: - args[k] = str(v) - if isinstance(filter, dict): - for k, v in filter.items(): - if v and k not in args: - args[k] = str(v) - route_tid = args.get('class', args.get('tid', str(tid))) - area = args.get('area', '') - genre = args.get('genre', '') - year = args.get('year', '') - lang = args.get('lang', '') - letter = args.get('letter', '') - sort = args.get('sort', '') - # 无筛选走正常分页 - if not area and not genre and not year and not lang and not letter and not sort: - url = f'/cupfox-list/{route_tid}--------{pg}---.html' - html = self._fetch(url) - items = self._parse_video_list(html) - page = int(pg) - soup = BeautifulSoup(html, 'html.parser') - pagecount = page - for a in soup.select('a.page-link'): - if a.text == '尾页': - m = re.search(r'---(\d+)---', a.get('href', '')) - if m: - pagecount = int(m.group(1)) - break - if not items: - pagecount = 0 - return {"list": items, "page": page, "pagecount": pagecount, "limit": 36, "total": 9999} - # 有筛选:{tid}-{area}-{sort}-{genre}-{lang}-{letter}------{year}.html - segs = [route_tid, area, sort, genre, lang, letter, '', '', year] - url = '/cupfox-list/' + '-'.join(segs) + '.html' - html = self._fetch(url) - items = self._parse_video_list(html) - return {"list": items, "page": 1, "pagecount": 1, "limit": 36, "total": 9999} - - def detailContent(self, ids): - result = {"list": []} - vid = ids[0].split(',')[0].strip() - try: - html = self._fetch(f'/detail/{vid}.html') - if not html: return result - soup = BeautifulSoup(html, 'html.parser') - vod_name = soup.select_one('h3.slide-info-title') - vod_name = vod_name.text.strip() if vod_name else '' - vod_pic = soup.select_one('img.lazy') - vod_pic = self._fix_pic(vod_pic.get('data-src', '')) if vod_pic else '' - vod_director = '' - vod_actor = '' - for el in soup.select('.slide-info'): - text = el.get_text(' ').strip() - if text.startswith('导演:'): - vod_director = text.replace('导演:', '').strip() - elif text.startswith('演员:'): - vod_actor = text.replace('演员:', '').strip() - vod_content = soup.select_one('#height_limit') - vod_content = vod_content.get_text(' ', strip=True) if vod_content else '' - play_from, play_url = [], [] - for tab in soup.select('.anthology-tab a.swiper-slide'): - src_name = re.sub(r'<[^>]+>', '', str(tab)).strip() or tab.get_text(' ', strip=True).strip() - if src_name: - play_from.append(src_name) - tab_blocks = soup.select('.anthology-list-box') - for i, block in enumerate(tab_blocks): - ep_list = [] - for a in block.select('li a'): - href = a.get('href', '') - m = re.search(r'/play/(.*?)\.html', href) - if m: - ep_list.append(f'{a.text.strip()}${vid}-{m.group(1)}') - ep_list.reverse() - if ep_list and i < len(play_from): - play_url.append('#'.join(ep_list)) - valid_from = [pf for i, pf in enumerate(play_from) if i < len(play_url)] - result["list"].append({ - "vod_id": vid, "vod_name": vod_name, "vod_pic": vod_pic, - "vod_director": vod_director, "vod_actor": vod_actor, - "vod_content": vod_content, - "vod_play_from": "$$$".join(valid_from), - "vod_play_url": "$$$".join(play_url), - }) - except: - pass - return result - - def searchContent(self, key, quick, pg="1"): - try: - decoded = urllib.parse.unquote(key) - except: - decoded = key - html = self._fetch(f'/cupfox-search/{urllib.parse.quote(decoded)}----------{pg}---.html') - items = self._parse_search_list(html) - return {"list": items, "page": int(pg), "pagecount": 1, "limit": 36, "total": len(items)} - - def playerContent(self, flag, id, vipFlags): - url = '' - try: - url = id if id.startswith('http') else f'{self.host}/play/{id}.html' - html = self._fetch(url) - if html: - m = re.search(r'player_aaaa=(.*?)', html, re.S) - if m: - - try: - pd = json.loads(m.group(1)) - except Exception as e: - print(e) - pd = {} - # print('pd:', pd) - play_url = pd.get('url') - play_id = pd.get('from') - - api_map = { - 'YYNB': 'https://zzrs.mfdyvip.com/player/mplayer.php', - 'JD4K': 'https://fgsrg.hzqingshan.com/player/mplayer.php', - } - if not play_url: - return {"parse": 0, "url": 'https://php.doube.eu.org/error.m3u8', - "header": {'User-Agent': 'Mozilla/5.0'}} - if play_url.startswith('http') and (play_url.endswith('.m3u8') or play_url.endswith('.mp4')): - return {"parse": 0, "url": play_url, "header": {'User-Agent': 'Mozilla/5.0'}} - - else: - headers = { - 'User-Agent': "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.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", - 'accept-language': "zh-CN,zh;q=0.9", - 'cache-control': "no-cache", - 'pragma': "no-cache", - 'priority': "u=0, i", - 'referer': "https://www.ht10010.com/", - 'Content-Type': 'application/x-www-form-urlencoded', - } - response = requests.get(f"https://fgsrg.hzqingshan.com/player/?url={play_url}", headers=headers) - token = re.search(r'data-te="(.*?)"', response.text) - if token: - token = token.group(1) - payload = { - 'url': play_url, - 'token': token - } - # print('payload', payload) - try: - response = self.post(api_map[play_id], data=payload, headers=headers) - - response.raise_for_status() - result = response.json() - # print('result:', result) - if result['code'] == 200 and 'url' in result: - play_url = result['url'] - return {"parse": 0, "url": play_url, "header": { - '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'}} - except Exception as e: - print(e) - except Exception as e: - print(e) - return {"parse": 1, "url": url} - - def localProxy(self, param=''): - return {} - - def isVideoFormat(self, url): - return False - - def manualVideoCheck(self): - return False - - def _fetch(self, url): - try: - if not url.startswith('http'): - url = self.host + url - rsp = self.fetch(url, headers=self.headers) - return rsp.text if rsp else '' - except: - return '' - - def _fix_pic(self, u): - if not u: return '' - if u.startswith('//'): return 'https:' + u - return u.replace('&', '&') - - def _parse_video_list(self, html): - videos, seen = [], set() - soup = BeautifulSoup(html, 'html.parser') - cards = soup.select('a.public-list-exp') - for a in cards: - href = a.get('href', '') - m = re.search(r'/detail/(\d+)\.html', href) - if not m: continue - vod_id = m.group(1) - if vod_id in seen: continue - seen.add(vod_id) - span = ','.join([span.text for span in a.select('span.public-prt')]) - # print('span', span) - vod_name = a.get('title', '') or (a.select_one('img') and a.select_one('img').get('alt', '')) or '' - pic_el = a.select_one('img') - vod_pic = self._fix_pic(pic_el.get('data-src', '')) if pic_el else '' - remark_el = a.select_one('.ft2') or a.select_one('.public-list-prb') - vod_remarks = remark_el.text.strip() if remark_el else '' - videos.append( - {"vod_id": vod_id, "vod_name": vod_name.strip(), "vod_pic": vod_pic, "vod_remarks": vod_remarks, "vod_year": span}) - return videos - - def _parse_search_list(self, html): - videos, seen = [], set() - soup = BeautifulSoup(html, 'html.parser') - cards = soup.select('a.public-list-exp') - for a in cards: - href = a.get('href', '') - m = re.search(r'/detail/(\d+)\.html', href) - if not m: continue - vod_id = m.group(1) - if vod_id in seen: continue - seen.add(vod_id) - pic_el = a.select_one('img') - vod_pic = self._fix_pic(pic_el.get('data-src', '')) if pic_el else '' - title_el = soup.select_one(f'a.thumb-txt[href="/detail/{vod_id}.html"]') - if title_el: - vod_name = title_el.text.strip() - else: - vod_name = a.select_one('img') and a.select_one('img').get('alt', '') or '' - remark_el = a.select_one('.public-list-prb') or a.select_one('.ft2') - vod_remarks = remark_el.text.strip() if remark_el else '' - videos.append( - {"vod_id": vod_id, "vod_name": vod_name.strip(), "vod_pic": vod_pic, "vod_remarks": vod_remarks}) - return videos - - -if __name__ == '__main__': - sp = Spider() - sp.init() - # 20067-5-189 - print(sp.categoryContent('/label/qq','1',True, {})) - # print(sp.playerContent('', '20067-6-189', [])) - # print(sp.playerContent('', '20067-5-189', [])) - pass diff --git a/FGBLH/py/袋鼠影视.py b/FGBLH/py/袋鼠影视.py new file mode 100644 index 00000000..bb5fd2be --- /dev/null +++ b/FGBLH/py/袋鼠影视.py @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +import sys +import re +import requests +from urllib.parse import quote, unquote +sys.path.append('..') +from base.spider import Spider + +class Spider(Spider): + def init(self, extend=""): + self.host = "https://dsystv.com" + self.headers = { + "User-Agent": "Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-G973U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36", + "Referer": self.host + "/", + "Origin": self.host + } + + def getName(self): + return "袋鼠影视" + + def isVideoFormat(self, url): + return bool(re.search(r'\.(m3u8|mp4|flv|avi|mkv|mov|ts)(\?|$)', url or "", re.I)) + + def manualVideoCheck(self): + return False + + def homeContent(self, filter): + return { + "class": [ + {"type_id": "1", "type_name": "电影"}, + {"type_id": "2", "type_name": "电视剧"}, + {"type_id": "3", "type_name": "综艺"}, + {"type_id": "4", "type_name": "动漫"}, + {"type_id": "44", "type_name": "短剧"} + ] + } + + def homeVideoContent(self): + return {"list": self.parseList(self.get(self.host + "/"))} + + def categoryContent(self, tid, pg, filter, extend): + url = self.host + ("/frim/index" + str(tid) + ".html" if str(pg) == "1" else "/search.php?searchtype=5&tid=" + str(tid) + "&page=" + str(pg)) + html = self.get(url) + return { + "page": int(pg), + "pagecount": 999, + "limit": 24, + "total": 999999, + "list": self.parseList(html) + } + + def detailContent(self, ids): + vid = ids[0] + html = self.get(self.host + "/movie/index" + vid + ".html") + name = self.clean(self.match(html, r'
(.*?)
') or self.match(html, r']+data-video-meta=["\']([^"\']*)["\'][^>]*>主演:') + director = self.match(html, r'