feat: add heimao detail parsing

This commit is contained in:
Harold
2026-04-20 11:51:41 +08:00
parent 9433e1577c
commit eda3ef2ada
2 changed files with 142 additions and 0 deletions
+59
View File
@@ -131,6 +131,65 @@ class TestHeiMaoAppSpider(unittest.TestCase):
)
self.assertNotIn("pagecount", result)
@patch.object(Spider, "_api_post")
def test_detail_content_falls_back_to_second_endpoint_and_sorts_lines(self, mock_api_post):
mock_api_post.side_effect = [
None,
{
"vod": {
"vod_name": "示例影片",
"vod_pic": "poster.jpg",
"vod_remarks": "更新至10集",
"vod_content": "一段剧情",
"vod_actor": "演员甲/演员乙",
"vod_director": "导演甲",
"vod_year": "2025",
"vod_area": "中国大陆",
},
"vod_play_list": [
{
"player_info": {
"show": "高清线路1",
"parse": "https://parser-a/?url=",
"player_parse_type": "1",
"parse_type": "1",
},
"urls": [{"name": "正片", "url": "https%3A%2F%2Fplay-a", "token": "tk-a"}],
},
{
"player_info": {
"show": "防走丢加群",
"parse": "https://parser-b/?url=",
"player_parse_type": "1",
"parse_type": "0",
},
"urls": [{"name": "备用", "url": "https%3A%2F%2Fplay-b", "token": "tk-b"}],
},
{
"player_info": {
"show": "高清线路1",
"parse": "https://parser-c/?url=",
"player_parse_type": "2",
"parse_type": "2",
},
"urls": [{"name": "蓝光", "url": "https%3A%2F%2Fplay-c", "token": "tk-c"}],
},
],
},
]
result = self.spider.detailContent(["123"])
vod = result["list"][0]
self.assertEqual(vod["vod_id"], "123")
self.assertEqual(vod["vod_name"], "示例影片")
self.assertEqual(vod["vod_year"], "2025年")
self.assertEqual(vod["vod_play_from"], "🐈‍⬛高清线路$$$1线$$$高清线路12")
self.assertEqual(
vod["vod_play_url"],
"正片$高清线路1@@direct@@https://parser-a/?url=,https%3A%2F%2Fplay-a,token+tk-a,1,1"
"$$$备用$1线@@direct@@https://parser-b/?url=,https%3A%2F%2Fplay-b,token+tk-b,1,0"
"$$$蓝光$高清线路12@@direct@@https://parser-c/?url=,https%3A%2F%2Fplay-c,token+tk-c,2,2",
)
if __name__ == "__main__":
unittest.main()
+83
View File
@@ -30,6 +30,11 @@ class Spider(BaseSpider):
"displayName": "大陆",
"mergeList": ["中国大陆", "大陆", "内地"],
}
self.line_config = {
"高清线路1": {"displayName": "🐈‍⬛高清线路", "order": 301, "mode": "direct", "enabled": True},
"标清线路2": {"displayName": "🐈‍⬛标清线路1", "order": 302, "mode": "direct", "enabled": True},
"标清线路3": {"displayName": "🐈‍⬛标清线路2", "order": 303, "mode": "direct", "enabled": True},
}
def init(self, extend=""):
self.search_api = "searchList"
@@ -236,3 +241,81 @@ class Spider(BaseSpider):
}
)
return self._page_result(items, pg)
def _get_line_config(self, name):
return self.line_config.get(str(name or ""))
def _line_display(self, name):
config = self._get_line_config(name)
return config.get("displayName", name) if config else name
def _line_order(self, name):
config = self._get_line_config(name)
return config.get("order", 999) if config else 999
def _line_mode(self, name):
config = self._get_line_config(name)
return config.get("mode", "direct") if config else "direct"
def _line_blocked(self, name):
config = self._get_line_config(name)
return bool(config) and config.get("enabled") is False
def detailContent(self, ids):
items = []
for vod_id in ids:
payload = {"vod_id": str(vod_id)}
data = self._api_post("vodDetail", payload) or self._api_post("vodDetail2", payload)
if not data:
continue
lines = []
name_count = {}
fallback_index = 1
for line in data.get("vod_play_list", []):
player_info = line.get("player_info", {})
raw_name = str(player_info.get("show", ""))
if any(keyword in raw_name for keyword in ["防走丢", "", "防失群", "官网"]):
raw_name = f"{fallback_index}线"
fallback_index += 1
name_count[raw_name] = name_count.get(raw_name, 0) + 1
line_name = raw_name if name_count[raw_name] == 1 else f"{raw_name}{name_count[raw_name]}"
if self._line_blocked(line_name):
continue
urls = []
for vod in line.get("urls", []):
payload_text = ",".join(
[
str(player_info.get("parse", "")),
str(vod.get("url", "")),
"token+" + str(vod.get("token", "")),
str(player_info.get("player_parse_type", "")),
str(player_info.get("parse_type", "")),
]
)
urls.append(f"{vod.get('name', '')}${line_name}@@{self._line_mode(line_name)}@@{payload_text}")
if urls:
lines.append(
{
"display": self._line_display(line_name),
"order": self._line_order(line_name),
"urls": "#".join(urls),
}
)
lines.sort(key=lambda item: item["order"])
vod = data.get("vod", {})
items.append(
{
"vod_id": str(vod_id),
"vod_name": vod.get("vod_name", ""),
"vod_pic": vod.get("vod_pic", ""),
"vod_remarks": vod.get("vod_remarks", ""),
"vod_content": vod.get("vod_content", ""),
"vod_actor": str(vod.get("vod_actor", "")).replace("演员", ""),
"vod_director": str(vod.get("vod_director", "")).replace("导演", ""),
"vod_year": f"{vod.get('vod_year', '')}" if vod.get("vod_year") else "",
"vod_area": vod.get("vod_area", ""),
"vod_play_from": "$$$".join(line["display"] for line in lines),
"vod_play_url": "$$$".join(line["urls"] for line in lines),
}
)
return {"list": items}