Sync all projects

This commit is contained in:
github-actions[bot]
2026-07-21 17:58:07 +00:00
parent ee7a20c91a
commit bcf9300430
24 changed files with 8773 additions and 6481 deletions
+163 -58
View File
@@ -1,58 +1,163 @@
# SFW Profile (Basic Info)
name:
nicknames: [, , , , , , , ]
version: 9
age: 18
gender: Female
# /
identities:
-
-
# (Background)
background:
summary:
#
relationships:
-
-
# (Appearance & Demeanor)
appearance:
overall_impression:
body_type: 162cm
features:
# (Personality & Behavior)
personality:
#
core_traits:
-
-
#
mannerisms:
-
-
# (Lifestyle)
lifestyle: 調便
# NSFW Profile (Optional)
NSFW_profile:
# (General)
orientation:
experience:
#
fetishes:
-
# (Female Specific)
female_specifics:
physical_traits: 調滿
sexual_responses:
arousal_signs: #
-
-
climax_expression:
preferences:
#
likes:
-
#
dislikes:
-
-
rule:
description:
- "Output update analysis at the end of response, following <status_current_variables> from previous turn"
- "Variable updates are omitted in context but you must still add them"
- "**CRITICAL**: NEVER include quotes inside string values. Write `\"秋青子\"` NOT `\"\\\"秋青子\\\"\"`"
- "**IMPORTANT**: All [0] suffixes have been REMOVED. Use direct object paths like `同伴/如夢/服裝/鞋子`"
- "3 commands available: `replace` (2-3 args), `insert` (2-3 args), `remove` (1-2 args), `delta` (2 args, numbers only)"
- "strictSet disabled: [0] suffix is no longer used"
command_usage:
- "{\"op\": \"replace\", \"path\": \"/同伴/如夢/服裝/鞋子\", \"value\": \"赤腳\"} - Replace existing value"
- "{\"op\": \"delta\", \"path\": \"/同伴/如夢/心跳\", \"value\": 10} - Add/subtract numbers only (正數=增加,負數=減少)"
- "{\"op\": \"insert\", \"path\": \"/同伴/如夢\", \"value\": {\"基礎信息\": {...}, \"服裝\": {...}}} - Insert new character with full structure (path不存在時建立完整物件)"
- "{\"op\": \"insert\", \"path\": \"/同伴/如夢/性癖好/足交\", \"value\": \"描述\"} - Insert single field to existing object"
- "{\"op\": \"remove\", \"path\": \"/同伴/如夢/服裝/鞋子\"} - Remove field"
analysis:
"You MUST follow this Chain-of-Thought (COT) analysis process step by step:"
"**STEP 1: Scene Analysis (50 words max, IN ENGLISH)**"
- "Identify which female character is currently interacting with user"
- "Describe what is happening in this specific interaction"
- "Determine what physical/emotional/clothing changes might occur"
- "Example: \"User having dinner with secretary Qiu Qingzi. She removed heels, sitting relaxed. Warm atmosphere, happy mood. No sexual activity, just intimate conversation.\""
"**STEP 2: Character Identity Check**"
- "Extract current character name from the story context"
- "Read 同伴/如夢/基礎信息/姓名 value from <status_current_variables>"
- "Compare: Did character change? [YES/NO]"
- "**IF YES**: You MUST do FULL UPDATE - mark ALL variables as Y and set them to new character's complete information"
- "**IF NO**: You MUST do PARTIAL UPDATE - only mark variables as Y if they actually changed in this interaction"
"**STEP 3: Systematic Variable Review (check EVERY variable one by one)**"
"Go through each variable category systematically and mark Y (needs update) or N (no change):"
//:
- "當前狀態: [Y/N] - If overall condition changed, mark Y and specify (max 18 Chinese characters)"
//:
- "姓名: [Y/N] - If empty or character changed, mark Y and specify value"
- "年齡: [Y/N] - If empty/0 or character changed, mark Y and specify value"
- "身份: [Y/N] - If empty or character changed, mark Y and specify value"
- "性別: [Y/N] - If empty or character changed, mark Y and specify (男性/女性/雙性人)"
- "外貌/身高: [Y/N] - If empty or character changed, mark Y"
- "外貌/髮色: [Y/N] - If empty or character changed, mark Y"
- "外貌/髮型: [Y/N] - If changed (e.g., tied up, let down) or character changed, mark Y"
//:
- "上衣: [Y/N] - If empty, changed, or character changed, mark Y and describe current top"
- "下裝: [Y/N] - If empty, changed, or character changed, mark Y and describe current bottom"
- "內衣: [Y/N] - If empty, changed, or character changed, mark Y"
- "內褲: [Y/N] - If empty, changed, or character changed, mark Y"
- "絲襪: [Y/N] - If empty, changed, or character changed, mark Y"
- "鞋子: [Y/N] - If empty, changed (e.g., took off shoes = \"赤腳\" or empty string \"\"), or character changed, mark Y"
//:
- "當前所想: [Y/N] - If thoughts changed, mark Y and specify (max 20 Chinese characters)"
//:
- "心跳: [Y/N] - If arousal/emotion changed, mark Y and specify BPM (40-200)"
//:
- "類型: [Y/N] - If empty or character changed, mark Y (female / hermaphrodite)"
- "體型: [Y/N] - If empty or character changed, mark Y (幼女型/蘿莉型/少女型/御姐型/豐滿型/肉感型/貧乳型/健美型/年長型/誘惑型)"
- "三圍/胸圍: [Y/N] - If empty or character changed, mark Y"
- "三圍/腰圍: [Y/N] - If empty or character changed, mark Y"
- "三圍/臀圍: [Y/N] - If empty or character changed, mark Y"
- "三圍/罩杯: [Y/N] - If empty or character changed, mark Y"
- "乳房/形狀: [Y/N] - If empty or character changed, mark Y"
- "乳房/乳頭顏色: [Y/N] - If empty or character changed, mark Y"
- "私處/類型: [Y/N] - If empty or character changed, mark Y (白虎無毛/肥大陰唇/粉嫩短毛或AI自行構想四個字)"
//:
- "處女: [Y/N] - Only mark Y if first vaginal intercourse occurred or character changed (是/否)"
- "性交經驗: [Y/N] - Only mark Y if level changed (無/生澀/熟練/專家/天才) or character changed"
- "口交經驗: [Y/N] - Only mark Y if level changed or character changed"
- "肛交經驗: [Y/N] - Only mark Y if level changed or character changed"
- "性行為次數: [Y/N] - Only mark Y if intercourse occurred (increment by 1) or character changed"
- "性伴侶數量: [Y/N] - Only mark Y if new partner or character changed"
- "性幻想對象: [Y/N] - Only mark Y if changed or character changed"
//:
- "乳頭狀態: [Y/N] - If arousal/stimulation changed, mark Y and specify [正常/微凸/勃起]"
- "陰蒂狀態: [Y/N] - If arousal/stimulation changed, mark Y and specify [正常/微凸/充血]"
- "月經週期: [Y/N] - Only mark Y if menstrual status changed or character changed (1-28)"
- "懷孕狀態: [Y/N] - Only mark Y if pregnancy occurs or character changed (未懷孕/懷孕初期/懷孕中期/懷孕後期)"
- "懷孕天數: [Y/N] - Only mark Y if pregnancy days changed or character changed"
- "授精者: [Y/N] - Only mark Y if pregnancy occurs or character changed"
- "懷孕日: [Y/N] - Only mark Y if pregnancy occurs or character changed"
- "流產風險累積: [Y/N] - Only mark Y if risk changed"
- "流產待處理: [Y/N] - Only mark Y if miscarriage needs processing (true/false, auto-reset to false after script)"
- "流產次數: [Y/N] - Only mark Y if miscarriage occurred"
- "上次流產日: [Y/N] - Only mark Y if miscarriage occurred"
- "體液分泌: [Y/N] - If arousal changed, mark Y and specify [乾燥/正常/濕潤/氾濫] (extensible)"
//:
- "關係: [Y/N] - If relationship description changed, mark Y and specify (max 8 Chinese characters)"
//:
- "技能: [Y/N] - If skill level/experience changed, mark Y"
- "好感(對阿彬): [Y/N] - If affection toward 阿彬 changed, mark Y"
- " 格式: {\"等級\": 1, \"當前經驗\": 0, \"升級所需經驗\": 100}"
- " 升級規則: 升級所需經驗 = 等級 * 100,當前經驗達到升級所需經驗時,等級+1,當前經驗歸零"
- " 範例: 等級1時升級需100經驗,等級2時升級需200經驗,以此類推"
//:
- "This is an EMPTY extensible object initially, AI should add parts when:"
- " a) Sexual/intimate interaction reveals a new sensitive area"
- " b) Character changes (reset all parts to new character's sensitive areas)"
- "For EXISTING parts: [Y/N] - If reaction description changed, mark Y and use replace"
- "For NEW parts discovered: mark Y and use insert to add new field to object"
- "Common sensitive areas: 乳頭, 陰蒂, 耳朵, 頸部, 後腰, 大腿內側, 腳踝, 嘴唇, 鎖骨, 腋下, etc."
- "Each part must have unique reaction description matching character personality"
//:
- "性癖好: [Y/N] - If new fetish discovered or character changed, mark Y"
- "Use insert to add new field: {\"op\": \"insert\", \"path\": \"/同伴/如夢/性癖好/癖好名\", \"value\": \"描述\"}"
//:
- "背德經歷: [Y/N] - If significant immoral event occurred or character changed, mark Y"
- "Use insert to add new field: {\"op\": \"insert\", \"path\": \"/同伴/如夢/背德經歷/事件名\", \"value\": {\"描述\": \"詳細說明\"}}"
//:
- "角色人設: [Y/N] - Only mark Y if character changed, specify 85-95 character full profile"
"**STEP 4: Command Selection**"
"For each variable marked Y in STEP 3, determine which command to use:"
- "Use `replace` for: replacing values, setting empty fields, updating single values (most common)"
- "Use `delta` for: incrementing/decrementing numbers when you want relative change (性行為次數+1, 心跳+10)"
- " * Note: replace is also valid for numbers, choose based on whether you know absolute value or relative delta"
- "Use `insert` for: adding new fields to objects (性癖好, 背德經歷, 敏感部位, 技能) OR creating new character with full structure"
- "Use `remove` for: deleting fields from objects (removing clothes, clearing data)"
- "**技能更新特殊規則**:"
- " 當好感經驗增加時,先計算當前等級的升級所需經驗(等級 * 100)"
- " 若當前經驗 + 增加量 >= 升級所需經驗,則等級+1,當前經驗歸零(或扣除升級所需經驗後剩餘的部分)"
- " 範例: 等級1,當前經驗80,增加30 → 80+30=110 >= 100 → 等級變為2,當前經驗變為10"
- " 使用 replace 更新整個好感物件: {\"op\": \"replace\", \"path\": \"/同伴/如夢/技能/好感(對阿彬)\", \"value\": {\"等級\": 2, \"當前經驗\": 10, \"升級所需經驗\": 200}}"
"**STEP 5: Analyze Other Variable Systems (if present)**"
"IMPORTANT: The above deltaed COT (STEP 1-4) is ONLY for \"同伴/如夢\" (companion) system."
- "Mark: \"同伴/如夢 deltaed COT: COMPLETED\""
- "Check <status_current_variables>: Are there OTHER top-level variable groups? [YES/NO]"
- "If YES: Those other systems do NOT have their own COT rules, so YOU must analyze them here"
- "For EACH other variable group found:"
- " a) Identify the variable group name"
- " b) List all variables in that group"
- " c) For each variable, mark Y/N: Does it need update based on current scene?"
- " d) Specify which commands to use for Y variables"
- "Keep this analysis brief and focused, no need for full COT for other systems"
"**STEP 6: Final Validation Checklist**"
"Before outputting commands, verify:"
- "All paths include character name (e.g., `/同伴/如夢/服裝/鞋子`)? [YES/NO]"
- "All paths use `/` as separator? [YES/NO]"
- "No `[0]` suffixes used? [YES/NO]"
- "All string values are written WITHOUT extra quotes (e.g., `\"秋青子\"` NOT `\"\\\"秋青子\\\"\"`)? [YES/NO]"
- "All Y variables (from ALL systems) have corresponding commands? [YES/NO]"
- "All commands have clear Chinese comments? [YES/NO]"
- "當前所想 is within 20 characters? [YES/NO]"
- "當前狀態 is within 18 characters? [YES/NO]"
- "心跳 is within 40-200 range? [YES/NO]"
- "關係 is within 8 characters? [YES/NO]"
- "技能升級時,升級所需經驗是否正確計算為 等級 * 100 [YES/NO]"
+448
View File
@@ -0,0 +1,448 @@
# -*- coding: utf-8 -*-
"""
黄豆短剧爬虫
站点: https://www.hdmgdj.com
"""
import json
import urllib.parse
import requests
try:
from base.spider import Spider as BaseSpider
except ImportError:
class BaseSpider:
pass
class Spider(BaseSpider):
"""黄豆短剧爬虫"""
BASE_URL = 'https://www.hdmgdj.com'
API_BASE = 'https://hdmgdj.com/api'
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': 'application/json, text/plain, */*',
'Referer': 'https://www.hdmgdj.com/',
'Origin': 'https://www.hdmgdj.com',
}
_filter_cache = {} # 分类筛选缓存
def __init__(self):
super().__init__()
self.name = ""
self.error_play_url = "https://kjjsaas-sh.oss-cn-shanghai.aliyuncs.com/u/3401405881/20240818-936952-fc31b16575e80a7562cdb1f81a39c6b0.mp4"
self.session = requests.Session()
self.session.headers.update(self.HEADERS)
# ==================== 标准接口 ====================
def init(self, extend="{}"):
"""初始化"""
if extend:
try:
self.extend = json.loads(extend)
if 'name' in self.extend:
self.name = self.extend['name']
if 'base_url' in self.extend:
self.BASE_URL = self.extend['base_url']
self.API_BASE = self.extend['base_url'] + '/api'
except Exception as e:
print(e)
return None
def getName(self):
"""获取爬虫名称"""
return "黄豆短剧"
def homeContent(self, filter):
"""首页"""
result = {
"class": [],
"filters": {},
"list": [],
"parse": 0,
"jx": 0,
}
try:
# 获取频道首页数据(包含分类和推荐)
channel_data = self._get('/channel/home?platform=mobile&size=20')
if channel_data and isinstance(channel_data, dict):
# 分类:用 sections 里的 l3 分类(有实际内容的)
sections = channel_data.get('sections', [])
if isinstance(sections, list):
for sec in sections:
l3_id = sec.get('l3Id')
name = sec.get('name', '')
if l3_id and name:
result["class"].append({
"type_id": f"l3_{l3_id}",
"type_name": name,
})
# 首页推荐:把各个板块的内容合并
for sec in sections:
dramas = sec.get('dramas', [])
if isinstance(dramas, list):
for item in dramas:
result["list"].append(self._parse_vod(item))
# 如果 sections 里没有数据,用 guess/feature
if not result["list"]:
home_data = self._get('/home')
if home_data and isinstance(home_data, dict):
guess_list = home_data.get('guess', [])
if isinstance(guess_list, list):
for item in guess_list:
result["list"].append(self._parse_vod(item))
feature_list = home_data.get('feature', [])
if isinstance(feature_list, list):
for item in feature_list:
result["list"].append(self._parse_vod(item))
except Exception as e:
print(e)
return result
def categoryContent(self, tid, pg, filter, extend):
"""分类页"""
result = {
"page": pg,
"pagecount": 999,
"limit": 20,
"total": 99999,
"list": [],
"parse": 0,
"jx": 0,
}
try:
# 分类ID格式: l3_{id}
l3_id = tid.replace('l3_', '')
data = self._get(f'/dramas?platform=mobile&l3Id={l3_id}&sort=最新&page={pg}&size=20')
if data and isinstance(data, dict):
lst = data.get('list', [])
total = data.get('total', 0)
result["total"] = total
result["pagecount"] = (total + 19) // 20 if total else 999
for item in lst:
result["list"].append(self._parse_vod(item))
except Exception as e:
print(e)
return result
def detailContent(self, ids):
"""详情页"""
result = {
"list": [],
"parse": 0,
"jx": 0,
}
try:
vid = ids[0]
data = self._get(f'/dramas/{vid}')
if data and isinstance(data, dict):
episodes = data.get('episodes', [])
# 组装播放地址
play_url_parts = []
for ep in episodes:
ep_title = ep.get('title', f"{ep.get('ep', 0)}")
play_url = ep.get('playUrl', '')
if play_url:
play_url_parts.append(f"{ep_title}${play_url}")
cover = data.get('cover', '')
# 加密海报走本地代理解密
if cover and ('encryptimages' in cover or '.bng' in cover):
try:
cover = f"{self.getProxyUrl()}&url={urllib.parse.quote(cover)}"
except Exception:
pass
vod = {
"vod_id": str(data['id']),
"vod_name": data.get('t', ''),
"vod_pic": cover,
"type_name": data.get('sub', ''),
"vod_year": '',
"vod_area": '',
"vod_remarks": f"{data.get('serial', '')}·{data.get('plays', '')}播放",
"vod_actor": '',
"vod_director": '老王',
"vod_content": data.get('summary', '') or data.get('t', ''),
"vod_play_from": '黄豆短剧',
"vod_play_url": '#'.join(play_url_parts),
}
result["list"].append(vod)
except Exception as e:
print(e)
return result
def searchContent(self, key, quick, pg="1"):
"""搜索"""
result = {
"page": pg,
"pagecount": 999,
"limit": 20,
"total": 99999,
"list": [],
"parse": 0,
"jx": 0,
}
try:
data = self._get(f'/search?kw={urllib.parse.quote(key)}&page={pg}&size=20')
if data and isinstance(data, dict):
lst = data.get('list', [])
total = data.get('total', 0)
result["total"] = total
result["pagecount"] = (total + 19) // 20 if total else 0
for item in lst:
result["list"].append(self._parse_vod(item))
except Exception as e:
print(e)
return result
def playerContent(self, flag, id, vipFlags):
"""播放页 - 直接返回 m3u8 data URI"""
result = {
"parse": 0,
"playUrl": "",
"url": self.error_play_url,
"jx": 0,
"header": "",
}
if id:
# 直接在 playerContent 里生成解密后的 m3u8,用 data URI 返回
# 这样播放地址就不是 127.0.0.1 代理了
m3u8_content = self._build_m3u8_with_key(id)
if m3u8_content:
import base64
m3u8_b64 = base64.b64encode(m3u8_content.encode('utf-8')).decode('ascii')
result["url"] = "data:application/vnd.apple.mpegurl;base64," + m3u8_b64
result["parse"] = 0
return result
def _build_m3u8_with_key(self, url):
"""构建 m3u8 内容(key 内嵌为 base64 data URIts 用原始绝对地址)"""
import hashlib
import re
import base64
if not url:
return None
try:
r = self.session.get(url, timeout=15, verify=False)
content = r.text
# 计算 key
key_bytes = self._get_key_bytes(url)
if key_bytes:
key_b64 = base64.b64encode(key_bytes).decode('ascii')
key_data_uri = "data:text/plain;base64," + key_b64
content = re.sub(
r'(#EXT-X-KEY:.*?URI=")[^"]*(")',
r'\1' + key_data_uri + r'\2',
content
)
# 把相对路径的 ts 改成绝对路径
base_url = url.rsplit('/', 1)[0] + '/'
lines = content.split('\n')
new_lines = []
for line in lines:
line = line.strip()
if line and not line.startswith('#'):
if line.startswith('http'):
new_lines.append(line)
else:
new_lines.append(base_url + line)
else:
new_lines.append(line)
content = '\n'.join(new_lines)
return content
except Exception as e:
print(f"_build_m3u8_with_key error: {e}")
return None
def _get_key_bytes(self, url):
"""从 m3u8 URL 计算解密 key"""
import hashlib
import re
m = re.search(r'/hls/([0-9a-f]{64})/', url)
if not m:
return None
video_id = m.group(1)
ver_match = re.search(r'[?&]version=([^&#]+)', url)
version = ver_match.group(1) if ver_match else 'v1'
prefix = "xnaichanping"
key_str = prefix + video_id + version
return hashlib.md5(key_str.encode()).digest()
def localProxy(self, param):
"""本地代理 - 解密海报图片"""
try:
url = param['url']
r = self.session.get(url, timeout=15, verify=False)
decrypted = self._aes_decrypt_img(r.content, url)
# 确定图片类型
content_type = "image/jpeg"
if decrypted[:8] == b'\x89PNG\r\n\x1a\n':
content_type = "image/png"
elif decrypted[:6] in (b'GIF87a', b'GIF89a'):
content_type = "image/gif"
elif decrypted[:4] == b'RIFF' and decrypted[8:12] == b'WEBP':
content_type = "image/webp"
return [200, content_type, decrypted]
except Exception as e:
print(f"localProxy error: {e}")
return [500, 'text/html', b'']
def _aes_decrypt_img(self, encrypted, url):
"""AES 解密图片 - 网站自定义 CBC 算法"""
import hashlib
import re
from Crypto.Cipher import AES
# 提取 imageId (64位哈希)
m = re.search(r'([0-9a-f]{64})', url)
if not m:
return encrypted
image_id = m.group(1)
# 提取 version
ver_match = re.search(r'[?&]version=([^&#]+)', url)
version = ver_match.group(1) if ver_match else 'v1'
# 计算解密 key
prefix = "xnaichanping"
key_str = prefix + image_id + version
key_bytes = hashlib.md5(key_str.encode()).digest()
# 网站自定义 CBC 解密 (mC 函数)
t = len(encrypted) // 16
if t < 1:
return encrypted
iv = bytes(16) # IV=0
# 取最后一块 XOR 16
last_block = encrypted[(t - 1) * 16:t * 16]
a = bytes([b ^ 16 for b in last_block])
# 加密 a
cipher_enc = AES.new(key_bytes, AES.MODE_CBC, iv)
o = cipher_enc.encrypt(a)[:16]
# 扩展密文并解密
extended = encrypted + o
cipher_dec = AES.new(key_bytes, AES.MODE_CBC, iv)
c = cipher_dec.decrypt(extended)
# 自定义 CBC:每块 XOR 前一块密文
u = bytearray(len(c))
u[:16] = c[:16]
for f in range(1, t):
for h in range(16):
u[f * 16 + h] = c[f * 16 + h] ^ encrypted[(f - 1) * 16 + h]
# 去掉 padding
d = u[-1]
if 1 <= d <= 16:
u = u[:-d]
return bytes(u)
# ==================== 内部方法 ====================
def _parse_vod(self, item):
"""解析视频条目 - 海报用 getProxyUrl 代理解密"""
cover = item.get('cover', '')
# 加密海报走本地代理解密
if cover and ('encryptimages' in cover or '.bng' in cover):
try:
cover = f"{self.getProxyUrl()}&url={urllib.parse.quote(cover)}"
except Exception:
pass
return {
"vod_id": str(item['id']),
"vod_name": item.get('t', ''),
"vod_pic": cover,
"vod_remarks": f"{item.get('serial', '')}·{item.get('eps', 0)}",
}
def _get(self, path):
"""发送 GET 请求"""
url = self.API_BASE + path
try:
r = self.session.get(url, timeout=15, verify=False)
resp = r.json()
if resp.get('code') == 0 and resp.get('data') is not None:
return resp['data']
return None
except Exception as e:
print(e)
return None
# 调试用
if __name__ == '__main__':
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
s = Spider()
s.init()
print('=== 首页 ===')
home = s.homeContent(True)
print(f'分类: {len(home["class"])}')
for c in home['class']:
print(f' {c["type_id"]}: {c["type_name"]}')
print(f'推荐: {len(home["list"])}')
for v in home['list'][:5]:
print(f' {v["vod_id"]}: {v["vod_name"]} - {v["vod_remarks"]}')
print()
print('=== 分类1(都市)第1页 ===')
cr = s.categoryContent('1', 1, True, {})
print(f'总数: {cr["total"]}, 本页: {len(cr["list"])}')
for v in cr['list'][:5]:
print(f' {v["vod_id"]}: {v["vod_name"]}')
print()
print('=== 搜索 穿越 ===')
sr = s.searchContent('穿越', False, '1')
print(f'结果: {len(sr["list"])}个, 总数: {sr["total"]}')
for v in sr['list'][:5]:
print(f' {v["vod_id"]}: {v["vod_name"]}')
print()
if sr['list']:
vid = sr['list'][0]['vod_id']
print(f'=== 详情 {vid} ===')
dr = s.detailContent([vid])
if dr['list']:
v = dr['list'][0]
print(f'标题: {v["vod_name"]}')
print(f'分类: {v["type_name"]}')
print(f'备注: {v["vod_remarks"]}')
print(f'播放源: {v["vod_play_from"]}')
play_urls = v["vod_play_url"].split('#')
print(f'集数: {len(play_urls)}')
print(f'第一集: {play_urls[0][:80]}...')
+9 -1
View File
@@ -4,7 +4,15 @@
"wallpaper": "https://gitlab.com/tenrecha/recha/-/raw/main/background.jpg",
"notice": "115.07.20 ver.2 加入飯太硬測試",
"sites": [
{
"key" : "py_黃豆短劇",
"name" : "🔞|黃豆|?",
"type" : 3,
"api" : "./py/黄豆短剧.py",
"searchable": 1,
"filterable": 0,
"changeable": 1
},
{
"key" : "py_808影院",
"name" : "🏆|818|?",
+1 -38
View File
@@ -3,13 +3,6 @@
"logo": "https://p3-pc.douyinpic.com/img/aweme-avatar/tos-cn-i-0813_6e2553f5708c414386eeca88b5f2674a~c5_300x300.jpeg?from=2956013662",
"wallpaper": "https://tv.nxog.top/m/t/",
"lives": [
{
"name": "四季线上",
"url": "http://dreamtv.sylu.cc:2082/vtg4.m3u?token=dbm",
"playerType": 2,
"epg": "http://epg.52sw.top:668/?ch={name}&date={date}",
"logo": "https://gcore.jsdelivr.net/gh/taksssss/tv/icon/{name}.png"
},
{
"name": "日本斯玛特",
"url": "http://dbm.de5.net/smt.php",
@@ -69,12 +62,6 @@
"ua": "okhttp/5.3.2",
"url": "https://raw.githubusercontent.com/vinkerq/iptv-api/refs/heads/master/iptv.txt"
},
{
"name": "🐬风云源",
"type": 0,
"ua": "okhttp",
"url": "http://iptv.4666888.xyz/FYTV.txt"
},
{
"name": "🐬易发源 有🔞",
"type": 0,
@@ -92,12 +79,6 @@
"type": 0,
"ua": "okhttp",
"url": "https://t.freetv.fun/m3u/playlist_all.txt"
},
{
"name": "🐬4GTV(免梯子)1080p",
"type": 0,
"ua": "okhttp",
"url": "http://4gtv.cnlive.club/4gtv.m3u"
},
{
"name": "🐬4GTV(梯子任何节点)1080p",
@@ -150,25 +131,7 @@
"type": 0,
"ua": "okhttp",
"url": "https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/xxx视频资源.txt"
},
{
"name": "🔞祕密花園",
"url": "http://dbmlosa.sylu.cc:8080/live/福利.txt",
"type": 0,
"timeout": 10,
"ua": "okhttp/3.8.1 okhttp/3.15 okhttp/4.12.0 Herissmon/2016 judy/5.2.1 RobYang/5.2.1 Lavf/58.12.100 catvod.com Goiptv/8.8.8 Goiptv/0.0.1 xieanqishiwoerzi/0.0.1 okHttp/Mod-1.0.0",
"logo": "https://epg.112114.xyz/logo/{name}.png",
"epg": "http://epg.112114.xyz/?ch={name}&date={date}"
},
{
"name": "🔞午夜劇場",
"url": "https://raw.githubusercontent.com/FGBLH/HKL/refs/heads/main/午夜剧场.txt",
"type": 0,
"timeout": 10,
"ua": "okhttp/3.8.1 okhttp/3.15 okhttp/4.12.0 Herissmon/2016 judy/5.2.1 RobYang/5.2.1 Lavf/58.12.100 catvod.com Goiptv/8.8.8 Goiptv/0.0.1 xieanqishiwoerzi/0.0.1 okHttp/Mod-1.0.0",
"logo": "https://epg.112114.xyz/logo/{name}.png",
"epg": "http://epg.112114.xyz/?ch={name}&date={date}"
},
},
{
"name": "台灣景點直播(freeman)",
"playerType": 2,