From c070e216e5cee4f26fae76a11b419ec888fb2fcc Mon Sep 17 00:00:00 2001 From: Harold <8866033@gmail.com> Date: Sun, 19 Apr 2026 20:39:48 +0800 Subject: [PATCH] fix: support nested cupfox player data --- py/tests/test_茶杯狐.py | 18 ++++++++++++++++ py/茶杯狐.py | 48 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/py/tests/test_茶杯狐.py b/py/tests/test_茶杯狐.py index 3b5d483..39e341b 100644 --- a/py/tests/test_茶杯狐.py +++ b/py/tests/test_茶杯狐.py @@ -123,6 +123,24 @@ class TestCupfoxSpider(unittest.TestCase): self.assertEqual(data["url"], "vid-1") self.assertEqual(data["from"], "lineA") + def test_extract_player_data_supports_nested_object_literal(self): + html = """ + + """ + data = self.spider._extract_player_data(html) + self.assertEqual(data["encrypt"], 0) + self.assertEqual(data["vod_data"]["vod_name"], "八千里路云和月") + self.assertEqual(data["from"], "rb") + def test_decode2_recovers_shifted_text(self): encoded = "QXdCQ2tE" self.assertEqual(self.spider._decode2(encoded), "P0") diff --git a/py/茶杯狐.py b/py/茶杯狐.py index af8d5b4..be976b2 100644 --- a/py/茶杯狐.py +++ b/py/茶杯狐.py @@ -160,14 +160,58 @@ class Spider(BaseSpider): return second["text"] def _extract_player_data(self, html_text): - matched = re.search(r"player_aaaa\s*=\s*(\{[\s\S]*?\})\s*;?", str(html_text or "")) + text = str(html_text or "") + matched = re.search(r"player_aaaa\s*=", text, re.I) if not matched: return None + object_start = text.find("{", matched.end()) + if object_start < 0: + return None + raw_object = self._extract_balanced_object(text, object_start) + if not raw_object: + return None try: - return json.loads(matched.group(1)) + return json.loads(raw_object) except Exception: return None + def _extract_balanced_object(self, text, start_index): + raw = str(text or "") + 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 _decode2(self, encoded): if not encoded: return ""