622 lines
24 KiB
Python
622 lines
24 KiB
Python
# -*- coding: utf-8 -*-
|
||
# 初见影视爬虫 - 爱豆儿解析版
|
||
import re
|
||
import json
|
||
import urllib.parse
|
||
import sys
|
||
|
||
sys.path.append('..')
|
||
from base.spider import Spider
|
||
|
||
|
||
class Spider(Spider):
|
||
|
||
def init(self, extend=""):
|
||
self.extend = extend
|
||
|
||
def getName(self):
|
||
return "初见影视"
|
||
|
||
def isVideoFormat(self, url):
|
||
return False
|
||
|
||
def manualVideoCheck(self):
|
||
return False
|
||
|
||
def destroy(self):
|
||
pass
|
||
|
||
host = 'https://cjysw.cc'
|
||
|
||
headers = {
|
||
'User-Agent': 'Mozilla/5.0 (Linux; Android 10; Mobile) '
|
||
'AppleWebKit/537.36 (KHTML, like Gecko) '
|
||
'Chrome/114.0.0.0 Mobile Safari/537.36',
|
||
'Referer': host,
|
||
}
|
||
|
||
classes_config = [
|
||
("电影", "1"),
|
||
("剧集", "15"),
|
||
("动漫", "30"),
|
||
("综艺", "24"),
|
||
("纪录片", "63"),
|
||
("短剧", "47"),
|
||
("Netflix", "60"),
|
||
]
|
||
|
||
# ====== 只使用爱豆儿解析接口 ======
|
||
PARSE_API = "https://jx.aidouer.net/?url="
|
||
|
||
def homeContent(self, filter):
|
||
result = {}
|
||
classes = []
|
||
|
||
for name, tid in self.classes_config:
|
||
classes.append({
|
||
"type_name": name,
|
||
"type_id": tid
|
||
})
|
||
|
||
filters = {}
|
||
|
||
filters["1"] = [
|
||
{"key": "class", "name": "类型", "value": [
|
||
{"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": "历史"},
|
||
]},
|
||
{"key": "area", "name": "地区", "value": [
|
||
{"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": "其他"},
|
||
]},
|
||
{"key": "year", "name": "年份", "value": [
|
||
{"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"},
|
||
]},
|
||
]
|
||
|
||
filters["15"] = [
|
||
{"key": "class", "name": "类型", "value": [
|
||
{"n": "全部", "v": ""},
|
||
{"n": "国产剧", "v": "国产剧"},
|
||
{"n": "港剧", "v": "港剧"},
|
||
{"n": "台剧", "v": "台剧"},
|
||
{"n": "日剧", "v": "日剧"},
|
||
{"n": "韩剧", "v": "韩剧"},
|
||
{"n": "美剧", "v": "美剧"},
|
||
{"n": "英剧", "v": "英剧"},
|
||
{"n": "泰剧", "v": "泰剧"},
|
||
]},
|
||
{"key": "area", "name": "地区", "value": [
|
||
{"n": "全部", "v": ""},
|
||
{"n": "大陆", "v": "大陆"},
|
||
{"n": "香港", "v": "香港"},
|
||
{"n": "台湾", "v": "台湾"},
|
||
{"n": "美国", "v": "美国"},
|
||
{"n": "日本", "v": "日本"},
|
||
{"n": "韩国", "v": "韩国"},
|
||
{"n": "英国", "v": "英国"},
|
||
]},
|
||
{"key": "year", "name": "年份", "value": [
|
||
{"n": "全部", "v": ""},
|
||
{"n": "2026", "v": "2026"},
|
||
{"n": "2025", "v": "2025"},
|
||
{"n": "2024", "v": "2024"},
|
||
{"n": "2023", "v": "2023"},
|
||
{"n": "2022", "v": "2022"},
|
||
]},
|
||
]
|
||
|
||
filters["30"] = [
|
||
{"key": "area", "name": "地区", "value": [
|
||
{"n": "全部", "v": ""},
|
||
{"n": "大陆", "v": "大陆"},
|
||
{"n": "日本", "v": "日本"},
|
||
{"n": "美国", "v": "美国"},
|
||
]},
|
||
{"key": "year", "name": "年份", "value": [
|
||
{"n": "全部", "v": ""},
|
||
{"n": "2026", "v": "2026"},
|
||
{"n": "2025", "v": "2025"},
|
||
{"n": "2024", "v": "2024"},
|
||
]},
|
||
]
|
||
|
||
filters["24"] = [
|
||
{"key": "year", "name": "年份", "value": [
|
||
{"n": "全部", "v": ""},
|
||
{"n": "2026", "v": "2026"},
|
||
{"n": "2025", "v": "2025"},
|
||
{"n": "2024", "v": "2024"},
|
||
]},
|
||
]
|
||
|
||
filters["63"] = [
|
||
{"key": "year", "name": "年份", "value": [
|
||
{"n": "全部", "v": ""},
|
||
{"n": "2026", "v": "2026"},
|
||
{"n": "2025", "v": "2025"},
|
||
{"n": "2024", "v": "2024"},
|
||
]},
|
||
]
|
||
|
||
filters["47"] = [
|
||
{"key": "year", "name": "年份", "value": [
|
||
{"n": "全部", "v": ""},
|
||
{"n": "2026", "v": "2026"},
|
||
{"n": "2025", "v": "2025"},
|
||
]},
|
||
]
|
||
|
||
filters["60"] = [
|
||
{"key": "year", "name": "年份", "value": [
|
||
{"n": "全部", "v": ""},
|
||
{"n": "2026", "v": "2026"},
|
||
{"n": "2025", "v": "2025"},
|
||
]},
|
||
]
|
||
|
||
result['filters'] = filters
|
||
|
||
rsp = self.fetch(self.host, headers=self.headers)
|
||
html = rsp.text
|
||
|
||
vlist = []
|
||
|
||
pattern = r'<a[^>]*href="([^"]+)"[^>]*class="[^"]*module-poster-item[^"]*"[^>]*>(.*?)</a>'
|
||
items = re.findall(pattern, html, re.DOTALL)
|
||
|
||
for href, item_html in items:
|
||
title_match = re.search(r'<div[^>]*class="[^"]*module-poster-item-title[^"]*"[^>]*>([^<]*)</div>', item_html)
|
||
title = title_match.group(1).strip() if title_match else ''
|
||
|
||
note_match = re.search(r'<div[^>]*class="[^"]*module-item-note[^"]*"[^>]*>([^<]*)</div>', item_html)
|
||
note = note_match.group(1).strip() if note_match else ''
|
||
|
||
pic_match = re.search(r'<img[^>]*data-original="([^"]+)"[^>]*>', item_html)
|
||
pic = pic_match.group(1) if pic_match else ''
|
||
if not pic:
|
||
pic_match = re.search(r'<img[^>]*src="([^"]+)"[^>]*>', item_html)
|
||
pic = pic_match.group(1) if pic_match else ''
|
||
|
||
if pic and not pic.startswith('http'):
|
||
pic = self.host + pic if pic.startswith('/') else self.host + '/' + pic
|
||
if href and not href.startswith('http'):
|
||
href = self.host + href if href.startswith('/') else self.host + '/' + href
|
||
|
||
if title:
|
||
vlist.append({
|
||
'vod_id': href,
|
||
'vod_name': title,
|
||
'vod_pic': pic,
|
||
'vod_remarks': note
|
||
})
|
||
|
||
result['class'] = classes
|
||
result['list'] = vlist[:30]
|
||
return result
|
||
|
||
def homeVideoContent(self):
|
||
return {}
|
||
|
||
def categoryContent(self, tid, pg, filter, extend):
|
||
page = int(pg) if pg else 1
|
||
|
||
class_val = extend.get('class', '') if extend else ''
|
||
area_val = extend.get('area', '') if extend else ''
|
||
year_val = extend.get('year', '') if extend else ''
|
||
|
||
if page == 1:
|
||
if class_val and not area_val and not year_val:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}/class/{class_val}.html"
|
||
elif area_val and not class_val and not year_val:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}/area/{area_val}.html"
|
||
elif year_val and not class_val and not area_val:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}/year/{year_val}.html"
|
||
elif class_val and area_val and not year_val:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}/class/{class_val}/area/{area_val}.html"
|
||
elif class_val and year_val and not area_val:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}/class/{class_val}/year/{year_val}.html"
|
||
elif area_val and year_val and not class_val:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}/area/{area_val}/year/{year_val}.html"
|
||
else:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}.html"
|
||
else:
|
||
if class_val and not area_val and not year_val:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}/class/{class_val}/page/{page}.html"
|
||
elif area_val and not class_val and not year_val:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}/area/{area_val}/page/{page}.html"
|
||
elif year_val and not class_val and not area_val:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}/year/{year_val}/page/{page}.html"
|
||
elif class_val and area_val and not year_val:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}/class/{class_val}/area/{area_val}/page/{page}.html"
|
||
else:
|
||
url = f"{self.host}/index.php/vod/show/id/{tid}/page/{page}.html"
|
||
|
||
rsp = self.fetch(url, headers=self.headers)
|
||
html = rsp.text
|
||
|
||
videos = []
|
||
|
||
pattern = r'<a[^>]*href="([^"]+)"[^>]*class="[^"]*module-poster-item[^"]*"[^>]*>(.*?)</a>'
|
||
items = re.findall(pattern, html, re.DOTALL)
|
||
|
||
for href, item_html in items:
|
||
title_match = re.search(r'<div[^>]*class="[^"]*module-poster-item-title[^"]*"[^>]*>([^<]*)</div>', item_html)
|
||
title = title_match.group(1).strip() if title_match else ''
|
||
|
||
note_match = re.search(r'<div[^>]*class="[^"]*module-item-note[^"]*"[^>]*>([^<]*)</div>', item_html)
|
||
note = note_match.group(1).strip() if note_match else ''
|
||
|
||
pic_match = re.search(r'<img[^>]*data-original="([^"]+)"[^>]*>', item_html)
|
||
pic = pic_match.group(1) if pic_match else ''
|
||
if not pic:
|
||
pic_match = re.search(r'<img[^>]*src="([^"]+)"[^>]*>', item_html)
|
||
pic = pic_match.group(1) if pic_match else ''
|
||
|
||
if pic and not pic.startswith('http'):
|
||
pic = self.host + pic if pic.startswith('/') else self.host + '/' + pic
|
||
if href and not href.startswith('http'):
|
||
href = self.host + href if href.startswith('/') else self.host + '/' + href
|
||
|
||
if title:
|
||
videos.append({
|
||
'vod_id': href,
|
||
'vod_name': title,
|
||
'vod_pic': pic,
|
||
'vod_remarks': note
|
||
})
|
||
|
||
pagecount = 1
|
||
page_pattern = r'<a[^>]*class="[^"]*page-link[^"]*"[^>]*>(\d+)</a>'
|
||
page_matches = re.findall(page_pattern, html)
|
||
for p in page_matches:
|
||
if p.isdigit() and int(p) > pagecount:
|
||
pagecount = int(p)
|
||
|
||
result = {
|
||
'list': videos,
|
||
'page': page,
|
||
'pagecount': pagecount,
|
||
'limit': 90,
|
||
'total': 999999
|
||
}
|
||
return result
|
||
|
||
def detailContent(self, ids):
|
||
vid = ids[0]
|
||
if not vid.startswith('http'):
|
||
url = self.host + vid if vid.startswith('/') else self.host + '/' + vid
|
||
else:
|
||
url = vid
|
||
|
||
rsp = self.fetch(url, headers=self.headers)
|
||
html = rsp.text
|
||
|
||
info = {'vod_id': vid}
|
||
|
||
title_match = re.search(r'<h1[^>]*>([^<]+)</h1>', html)
|
||
if title_match:
|
||
info['vod_name'] = title_match.group(1).strip()
|
||
else:
|
||
title_match = re.search(r'<title>([^<]+)</title>', html)
|
||
if title_match:
|
||
info['vod_name'] = title_match.group(1).split('-')[0].strip()
|
||
|
||
pic_match = re.search(r'<img[^>]*data-original="([^"]+)"[^>]*class="[^"]*lazy[^"]*"[^>]*alt="[^"]*"[^>]*>', html)
|
||
if not pic_match:
|
||
pic_match = re.search(r'<img[^>]*src="([^"]+)"[^>]*class="[^"]*lazy[^"]*"[^>]*alt="[^"]*"[^>]*>', html)
|
||
if not pic_match:
|
||
pic_match = re.search(r'<div[^>]*class="[^"]*module-item-pic[^"]*"[^>]*>.*?<img[^>]*src="([^"]+)"', html, re.DOTALL)
|
||
if pic_match:
|
||
pic = pic_match.group(1)
|
||
if pic and not pic.startswith('http'):
|
||
pic = self.host + pic if pic.startswith('/') else self.host + '/' + pic
|
||
info['vod_pic'] = pic
|
||
|
||
desc_match = re.search(r'<div[^>]*class="[^"]*module-info-introduction-content[^"]*"[^>]*>(.*?)</div>', html, re.DOTALL)
|
||
if desc_match:
|
||
info['vod_content'] = re.sub(r'<[^>]+>', '', desc_match.group(1)).strip()
|
||
|
||
info_items = re.findall(r'<div[^>]*class="[^"]*module-info-item[^"]*"[^>]*>.*?<span[^>]*class="[^"]*module-info-item-title[^"]*"[^>]*>([^<]*)</span>.*?<div[^>]*class="[^"]*module-info-item-content[^"]*"[^>]*>(.*?)</div>', html, re.DOTALL)
|
||
|
||
for title, value in info_items:
|
||
title = title.strip().replace(':', '').replace(':', '')
|
||
value = re.sub(r'<[^>]+>', '', value).strip()
|
||
if '导演' in title:
|
||
info['vod_director'] = value
|
||
elif '主演' in title:
|
||
info['vod_actor'] = value
|
||
elif '集数' in title or '更新' in title:
|
||
info['vod_remarks'] = value
|
||
elif '年份' in title or '上映' in title:
|
||
info['vod_year'] = value
|
||
|
||
vod_id = None
|
||
player_match = re.search(r'var player_aaaa\s*=\s*({[^;]+})', html)
|
||
if player_match:
|
||
try:
|
||
player_data = json.loads(player_match.group(1))
|
||
if player_data.get('id'):
|
||
vod_id = player_data['id']
|
||
except:
|
||
pass
|
||
|
||
if not vod_id:
|
||
vod_match = re.search(r'/detail/(\d+)\.html', url)
|
||
if vod_match:
|
||
vod_id = vod_match.group(1)
|
||
else:
|
||
vod_match = re.search(r'/play/(\d+)-\d+-\d+\.html', url)
|
||
if vod_match:
|
||
vod_id = vod_match.group(1)
|
||
|
||
tabs = []
|
||
|
||
tab_pattern1 = r'<(?:div|a)[^>]*class="[^"]*module-tab-item[^"]*"[^>]*>.*?<span>([^<]+)</span>'
|
||
tabs = re.findall(tab_pattern1, html, re.DOTALL)
|
||
tabs = list(dict.fromkeys(tabs))
|
||
|
||
if not tabs:
|
||
tab_pattern2 = r'<span[^>]*class="[^"]*module-tab-value[^"]*"[^>]*>([^<]*)</span>'
|
||
tabs = re.findall(tab_pattern2, html)
|
||
tabs = list(dict.fromkeys(tabs))
|
||
|
||
if not tabs:
|
||
tab_pattern3 = r'选择播放源\s*([^<]+)'
|
||
tabs = re.findall(tab_pattern3, html)
|
||
tabs = list(dict.fromkeys(tabs))
|
||
|
||
if not tabs:
|
||
tabs = ['高清']
|
||
|
||
play_items = []
|
||
|
||
container_pattern = r'<div[^>]*class="[^"]*module-play-list[^"]*"[^>]*>(.*?)</div>'
|
||
containers = re.findall(container_pattern, html, re.DOTALL)
|
||
|
||
for container in containers:
|
||
link_pattern = r'<a[^>]*href="([^"]+)"[^>]*>(.*?)</a>'
|
||
links = re.findall(link_pattern, container, re.DOTALL)
|
||
for href, title in links:
|
||
title = re.sub(r'<[^>]+>', '', title).strip()
|
||
if not title:
|
||
title = '播放'
|
||
if href.startswith('/'):
|
||
href = self.host + href
|
||
if href not in [item.split('$')[-1] for item in play_items]:
|
||
play_items.append(f'{title}${href}')
|
||
|
||
if not play_items and vod_id:
|
||
for idx, tab_name in enumerate(tabs):
|
||
sid = idx + 1
|
||
total = 40
|
||
total_match = re.search(r'<small>(\d+)</small>', html)
|
||
if total_match:
|
||
total = int(total_match.group(1))
|
||
episodes = []
|
||
for nid in range(1, total + 1):
|
||
ep_name = f"第{nid}集"
|
||
ep_url = f"{self.host}/play/{vod_id}-{sid}-{nid}.html"
|
||
episodes.append(f'{ep_name}${ep_url}')
|
||
if episodes:
|
||
play_items.extend(episodes)
|
||
|
||
ktabs = []
|
||
klists = []
|
||
|
||
if play_items:
|
||
if len(tabs) == 1:
|
||
ktabs = tabs
|
||
klists = ['#'.join(play_items)]
|
||
else:
|
||
items_per_tab = max(1, len(play_items) // len(tabs))
|
||
for i in range(len(tabs)):
|
||
start = i * items_per_tab
|
||
end = start + items_per_tab if i < len(tabs) - 1 else len(play_items)
|
||
if start < len(play_items):
|
||
ktabs.append(tabs[i])
|
||
klists.append('#'.join(play_items[start:end]))
|
||
|
||
if not ktabs:
|
||
link_pattern = r'<a[^>]*class="[^"]*module-play-list-link[^"]*"[^>]*href="([^"]+)"[^>]*>([^<]+)</a>'
|
||
links = re.findall(link_pattern, html)
|
||
if links:
|
||
episodes = []
|
||
for href, title in links:
|
||
if href and not href.startswith('#'):
|
||
if not href.startswith('http'):
|
||
href = self.host + href if href.startswith('/') else self.host + '/' + href
|
||
episodes.append(f'{title}${href}')
|
||
if episodes:
|
||
ktabs.append("播放")
|
||
klists.append('#'.join(episodes))
|
||
|
||
info["vod_play_from"] = '$$$'.join(ktabs) if ktabs else "初见影视"
|
||
info["vod_play_url"] = '$$$'.join(klists) if klists else ""
|
||
|
||
return {'list': [info]}
|
||
|
||
def searchContent(self, key, quick, pg="1"):
|
||
page = int(pg) if pg else 1
|
||
encoded_key = urllib.parse.quote(key, safe='')
|
||
url = f"{self.host}/index.php/vod/search.html?wd={encoded_key}&page={page}"
|
||
|
||
rsp = self.fetch(url, headers=self.headers)
|
||
html = rsp.text
|
||
|
||
videos = []
|
||
|
||
card_pattern = r'<div class="module-card-item[^"]*"[^>]*>(.*?)</div>\s*</div>\s*</div>'
|
||
cards = re.findall(card_pattern, html, re.DOTALL)
|
||
|
||
if not cards:
|
||
card_pattern = r'<div class="module-card-item[^"]*"[^>]*>(.*?)</div>'
|
||
temp_cards = re.findall(card_pattern, html, re.DOTALL)
|
||
cards = [c for c in temp_cards if len(c) > 100]
|
||
|
||
for card_html in cards:
|
||
href_match = re.search(r'<a[^>]*href="([^"]+)"[^>]*class="[^"]*module-card-item-poster[^"]*"[^>]*>', card_html)
|
||
if not href_match:
|
||
href_match = re.search(r'<a[^>]*href="([^"]+)"[^>]*>.*?<div class="module-card-item-title', card_html, re.DOTALL)
|
||
if not href_match:
|
||
href_match = re.search(r'<a[^>]*href="([^"]+)"[^>]*>', card_html)
|
||
href = href_match.group(1) if href_match else ''
|
||
|
||
title_match = re.search(r'<div class="module-card-item-title">.*?<a[^>]*>.*?<strong>([^<]+)</strong>', card_html, re.DOTALL)
|
||
if not title_match:
|
||
title_match = re.search(r'<strong>([^<]+)</strong>', card_html)
|
||
if not title_match:
|
||
title_match = re.search(r'<div class="module-card-item-title">.*?<a[^>]*>([^<]+)</a>', card_html, re.DOTALL)
|
||
title = title_match.group(1).strip() if title_match else ''
|
||
|
||
note_match = re.search(r'<div class="module-item-note">([^<]*)</div>', card_html)
|
||
note = note_match.group(1).strip() if note_match else ''
|
||
|
||
pic_match = re.search(r'<img[^>]*data-original="([^"]+)"[^>]*>', card_html)
|
||
if not pic_match:
|
||
pic_match = re.search(r'<img[^>]*src="([^"]+)"[^>]*>', card_html)
|
||
pic = pic_match.group(1) if pic_match else ''
|
||
|
||
if pic and not pic.startswith('http'):
|
||
pic = self.host + pic if pic.startswith('/') else self.host + '/' + pic
|
||
if href and not href.startswith('http'):
|
||
href = self.host + href if href.startswith('/') else self.host + '/' + href
|
||
|
||
if title:
|
||
videos.append({
|
||
'vod_id': href,
|
||
'vod_name': title,
|
||
'vod_pic': pic,
|
||
'vod_remarks': note
|
||
})
|
||
|
||
if not videos:
|
||
try:
|
||
from pyquery import PyQuery as pq
|
||
data = pq(html)
|
||
for item in data('.module-card-item').items():
|
||
href = item('a.module-card-item-poster').attr('href') or ''
|
||
title = item('.module-card-item-title strong').text() or ''
|
||
note = item('.module-item-note').text() or ''
|
||
pic = item('img').attr('data-original') or ''
|
||
|
||
if title:
|
||
if pic and not pic.startswith('http'):
|
||
pic = self.host + pic if pic.startswith('/') else self.host + '/' + pic
|
||
if href and not href.startswith('http'):
|
||
href = self.host + href if href.startswith('/') else self.host + '/' + href
|
||
videos.append({
|
||
'vod_id': href,
|
||
'vod_name': title,
|
||
'vod_pic': pic,
|
||
'vod_remarks': note
|
||
})
|
||
except:
|
||
pass
|
||
|
||
return {
|
||
'list': videos,
|
||
'page': page,
|
||
'pagecount': 9999,
|
||
'limit': 90,
|
||
'total': 999999
|
||
}
|
||
|
||
# ============================================================
|
||
# 使用爱豆儿解析接口
|
||
# ============================================================
|
||
def playerContent(self, flag, id, vipFlags):
|
||
if id.startswith('http'):
|
||
play_url = id
|
||
else:
|
||
play_url = self.host + id if id.startswith('/') else self.host + '/' + id
|
||
|
||
rsp = self.fetch(play_url, headers=self.headers)
|
||
html = rsp.text
|
||
|
||
real_url = play_url
|
||
|
||
# ====== 从 player_aaaa 提取 ======
|
||
player_match = re.search(r'var player_aaaa\s*=\s*({[^;]+})', html)
|
||
if player_match:
|
||
try:
|
||
player_data = json.loads(player_match.group(1))
|
||
if player_data.get('url'):
|
||
real_url = player_data['url'].replace('\\/', '/')
|
||
if real_url.startswith('//'):
|
||
real_url = 'https:' + real_url
|
||
except:
|
||
pass
|
||
|
||
# ====== 从 iframe 提取 ======
|
||
iframe_match = re.search(r'<iframe[^>]*src="([^"]+)"[^>]*>', html)
|
||
if iframe_match:
|
||
real_url = iframe_match.group(1)
|
||
if real_url.startswith('//'):
|
||
real_url = 'https:' + real_url
|
||
if real_url.startswith('/'):
|
||
real_url = self.host + real_url
|
||
|
||
# ====== 判断URL类型 ======
|
||
# 如果是m3u8/mp4,直接播放
|
||
if '.m3u8' in real_url or '.mp4' in real_url:
|
||
return {'parse': 0, 'url': real_url, 'header': self.headers}
|
||
|
||
# ====== 如果是第三方网站,使用爱豆儿解析 ======
|
||
need_parse = False
|
||
parse_keywords = [
|
||
'iqiyi.com', 'bilibili.com', 'v.qq.com', 'youku.com',
|
||
'qq.com', 'mgtv.com', 'sohu.com', 'le.com', 'pptv.com',
|
||
'爱奇艺', '腾讯', '优酷', '芒果', '乐视', '哔哩'
|
||
]
|
||
for keyword in parse_keywords:
|
||
if keyword in real_url:
|
||
need_parse = True
|
||
break
|
||
|
||
if need_parse:
|
||
parse_url = self.PARSE_API + urllib.parse.quote(real_url)
|
||
parse_headers = self.headers.copy()
|
||
parse_headers['Referer'] = 'https://jx.aidouer.net'
|
||
return {
|
||
'parse': 0,
|
||
'url': parse_url,
|
||
'header': parse_headers
|
||
}
|
||
|
||
return {'parse': 0, 'url': real_url, 'header': self.headers}
|
||
|
||
def localProxy(self, param):
|
||
return None |