fix: handle nested nsvod player payload
This commit is contained in:
@@ -228,6 +228,19 @@ class TestNSVodSpider(unittest.TestCase):
|
|||||||
self.assertEqual(result["url"], "https://cdn.example/direct.m3u8")
|
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")
|
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 = """
|
||||||
|
<script type="text/javascript">
|
||||||
|
var player_aaaa={"flag":"play","encrypt":0,"vod_data":{"vod_name":"阿爸请你嘛嘛吼","vod_actor":"甲,乙","vod_class":"剧情"},"url":"https:\\/\\/vip.dytt-kan.com\\/20260423\\/13858_751d8d46\\/index.m3u8","from":"dyttm3u8","id":"22663","sid":1,"nid":1}
|
||||||
|
</script>
|
||||||
|
"""
|
||||||
|
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")
|
@patch.object(Spider, "_request_html")
|
||||||
def test_player_content_falls_back_to_inline_m3u8(self, mock_request_html):
|
def test_player_content_falls_back_to_inline_m3u8(self, mock_request_html):
|
||||||
mock_request_html.return_value = '<script>var now="https://cdn.example/fallback.m3u8?token=1"</script>'
|
mock_request_html.return_value = '<script>var now="https://cdn.example/fallback.m3u8?token=1"</script>'
|
||||||
|
|||||||
+46
-2
@@ -261,12 +261,56 @@ class Spider(BaseSpider):
|
|||||||
return {"list": []}
|
return {"list": []}
|
||||||
return {"list": [vod]}
|
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):
|
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:
|
if not matched:
|
||||||
return {}
|
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:
|
try:
|
||||||
return json.loads(matched.group(1))
|
return json.loads(raw_object)
|
||||||
except Exception:
|
except Exception:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user