From 04917fd6df51583ec2c4c35dc92f34dd25e00b71 Mon Sep 17 00:00:00 2001 From: Harold <8866033@gmail.com> Date: Thu, 23 Apr 2026 19:15:36 +0800 Subject: [PATCH] feat: add jikanyingshi detail and player --- py/tests/test_即看影视.py | 38 +++++++++++++++++++++++++++++++++ py/即看影视.py | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/py/tests/test_即看影视.py b/py/tests/test_即看影视.py index d4f7ffb..43005bb 100644 --- a/py/tests/test_即看影视.py +++ b/py/tests/test_即看影视.py @@ -165,6 +165,44 @@ class TestJiKanYingShiSpider(unittest.TestCase): self.assertEqual(result["list"], []) self.assertEqual(result["total"], 0) + @patch.object(Spider, "_fetch_api") + def test_detail_content_wraps_single_vod_in_list(self, mock_fetch_api): + mock_fetch_api.return_value = {"data": {"vod_id": "d1", "vod_name": "详情片"}} + + result = self.spider.detailContent(["d1"]) + + self.assertEqual(mock_fetch_api.call_args.args, ("/sk-api/vod/one", {"vodId": "d1"})) + self.assertEqual(result, {"list": [{"vod_id": "d1", "vod_name": "详情片"}]}) + + @patch.object(Spider, "_fetch_api") + def test_player_content_prefers_skjson_url(self, mock_fetch_api): + mock_fetch_api.return_value = {"data": {"url": "https://media.example/final.m3u8"}} + + result = self.spider.playerContent("", "https://wrapped.example/play", "") + + self.assertEqual( + mock_fetch_api.call_args.args, + ("/sk-api/vod/skjson", {"url": "https://wrapped.example/play", "skjsonindex": 0}), + ) + self.assertEqual(result["url"], "https://media.example/final.m3u8") + self.assertEqual(result["jx"], 0) + + @patch.object(Spider, "_fetch_api") + def test_player_content_falls_back_to_original_id_and_sets_jx_for_video_sites(self, mock_fetch_api): + mock_fetch_api.side_effect = RuntimeError("parse failed") + + result = self.spider.playerContent("", "https://v.qq.com/x/cover/abcd", "") + + self.assertEqual(result["url"], "https://v.qq.com/x/cover/abcd") + self.assertEqual(result["jx"], 1) + self.assertEqual(result["parse"], 0) + + @patch.object(Spider, "_fetch_api") + def test_detail_content_returns_empty_list_when_api_has_no_data(self, mock_fetch_api): + mock_fetch_api.return_value = {"data": None} + + self.assertEqual(self.spider.detailContent(["404"]), {"list": []}) + if __name__ == "__main__": unittest.main() diff --git a/py/即看影视.py b/py/即看影视.py index 5b19675..fd598ca 100644 --- a/py/即看影视.py +++ b/py/即看影视.py @@ -209,3 +209,47 @@ class Spider(BaseSpider): return self._page_result(data.get("data") or [], pg, 10) except Exception: return self._page_result([], pg, 10) + + def detailContent(self, ids): + vod_id = ids[0] if isinstance(ids, (list, tuple)) else ids + try: + data = self._fetch_api("/sk-api/vod/one", {"vodId": vod_id}) + except Exception: + return {"list": []} + vod = data.get("data") + return {"list": [vod]} if isinstance(vod, dict) else {"list": []} + + def _player_headers(self): + return { + "User-Agent": ( + "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) " + "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 " + "Mobile/15E148 Safari/604.1" + ) + } + + def playerContent(self, flag, id, vipFlags): + try: + data = self._fetch_api("/sk-api/vod/skjson", {"url": id, "skjsonindex": 0}) + play_url = str((data.get("data") or {}).get("url") or "") + if play_url.startswith("http"): + return { + "parse": 0, + "jx": 0, + "url": play_url, + "header": self._player_headers(), + } + except Exception: + pass + + target = str(id or "") + jx = 1 if any( + domain in target.lower() + for domain in ["iqiyi.com", "qq.com", "youku.com", "mgtv.com", "bilibili.com"] + ) else 0 + return { + "parse": 0, + "jx": jx, + "url": target, + "header": self._player_headers(), + }