diff --git a/py/tests/test_耐视点播.py b/py/tests/test_耐视点播.py
index 60d8e4d..c4bf82b 100644
--- a/py/tests/test_耐视点播.py
+++ b/py/tests/test_耐视点播.py
@@ -228,6 +228,19 @@ class TestNSVodSpider(unittest.TestCase):
self.assertEqual(result["url"], "https://cdn.example/direct.m3u8")
self.assertEqual(result["header"]["Referer"], "https://nsvod.me/index.php/vod/play/id/70/sid/1/nid/1.html")
+ @patch.object(Spider, "_request_html")
+ def test_player_content_supports_nested_player_aaaa_object(self, mock_request_html):
+ mock_request_html.return_value = """
+
+ """
+ result = self.spider.playerContent("DY线路", "/index.php/vod/play/id/22663/sid/1/nid/1.html", {})
+ self.assertEqual(result["parse"], 0)
+ self.assertEqual(result["jx"], 0)
+ self.assertEqual(result["url"], "https://vip.dytt-kan.com/20260423/13858_751d8d46/index.m3u8")
+ self.assertEqual(result["header"]["Referer"], "https://nsvod.me/index.php/vod/play/id/22663/sid/1/nid/1.html")
+
@patch.object(Spider, "_request_html")
def test_player_content_falls_back_to_inline_m3u8(self, mock_request_html):
mock_request_html.return_value = ''
diff --git a/py/耐视点播.py b/py/耐视点播.py
index 9d3144f..f0ba47b 100644
--- a/py/耐视点播.py
+++ b/py/耐视点播.py
@@ -261,12 +261,56 @@ class Spider(BaseSpider):
return {"list": []}
return {"list": [vod]}
+ def _extract_balanced_object(self, text, start_index):
+ raw = self._stringify(text)
+ if start_index < 0 or start_index >= len(raw) or raw[start_index] != "{":
+ return ""
+
+ depth = 0
+ in_string = False
+ quote_char = ""
+ escaped = False
+
+ for index in range(start_index, len(raw)):
+ char = raw[index]
+ if in_string:
+ if escaped:
+ escaped = False
+ elif char == "\\":
+ escaped = True
+ elif char == quote_char:
+ in_string = False
+ continue
+
+ if char in ('"', "'"):
+ in_string = True
+ quote_char = char
+ continue
+
+ if char == "{":
+ depth += 1
+ continue
+
+ if char == "}":
+ depth -= 1
+ if depth == 0:
+ return raw[start_index : index + 1]
+
+ return ""
+
def _extract_player_data(self, html):
- matched = re.search(r"var\s+player_aaaa\s*=\s*(\{[\s\S]*?\})", self._stringify(html), re.I)
+ text = self._stringify(html)
+ matched = re.search(r"player_aaaa\s*=", text, re.I)
if not matched:
return {}
+ object_start = text.find("{", matched.end())
+ if object_start < 0:
+ return {}
+ raw_object = self._extract_balanced_object(text, object_start)
+ if not raw_object:
+ return {}
try:
- return json.loads(matched.group(1))
+ return json.loads(raw_object)
except Exception:
return {}