feat: add dbku player decoders

This commit is contained in:
Harold
2026-04-18 12:03:00 +08:00
parent 33aebd6df3
commit 6a060f8214
2 changed files with 62 additions and 1 deletions
+27
View File
@@ -1,4 +1,5 @@
import unittest
import base64
from importlib.machinery import SourceFileLoader
from pathlib import Path
from unittest.mock import patch
@@ -128,6 +129,32 @@ class TestDBKUSpider(unittest.TestCase):
self.assertEqual(result["list"][0]["vod_id"], "https://www.dbku.tv/voddetail/200.html")
self.assertEqual(result["list"][0]["vod_name"], "详情影片")
def test_parse_player_data_reads_json_block(self):
html = '<script>var player_data = {"url":"https://video.example/a.m3u8","encrypt":"0"};</script>'
data = self.spider._parse_player_data(html)
self.assertEqual(data["url"], "https://video.example/a.m3u8")
def test_decode_play_url_by_encrypt_supports_modes_0_1_2_3(self):
self.assertEqual(
self.spider._decode_play_url_by_encrypt("https://video.example/raw.m3u8", 0),
"https://video.example/raw.m3u8",
)
self.assertEqual(
self.spider._decode_play_url_by_encrypt("https%3A//video.example/escape.m3u8", 1),
"https://video.example/escape.m3u8",
)
mode2 = base64.b64encode("https://video.example/base64.m3u8".encode("utf-8")).decode("utf-8")
self.assertEqual(
self.spider._decode_play_url_by_encrypt(mode2, 2),
"https://video.example/base64.m3u8",
)
mode3_raw = "ABCDEFGHhttps://video.example/trimmed.m3u8HGFEDCBA"
mode3 = base64.b64encode(mode3_raw.encode("utf-8")).decode("utf-8")
self.assertEqual(
self.spider._decode_play_url_by_encrypt("12345678" + mode3, 3),
"https://video.example/trimmed.m3u8",
)
if __name__ == "__main__":
unittest.main()
+35 -1
View File
@@ -1,7 +1,9 @@
# coding=utf-8
import base64
import json
import re
import sys
from urllib.parse import quote
from urllib.parse import quote, unquote
from lxml import etree
@@ -212,3 +214,35 @@ class Spider(BaseSpider):
vod_id = ids[0]
html = self._request_html(vod_id, expect_xpath="//*[contains(@class,'title')]|//a[contains(@href,'/vodplay/')]")
return self._parse_detail_page(html, vod_id)
def _parse_player_data(self, html):
matched = re.search(r"var\s+player_data\s*=\s*(\{[\s\S]*?\})\s*;?\s*</script>", html, re.I)
if not matched:
matched = re.search(r"var\s+player_[^=]*\s*=\s*(\{[\s\S]*?\})\s*;?\s*</script>", html, re.I)
if not matched:
return None
try:
return json.loads(matched.group(1))
except Exception:
return None
def _decode_play_url_by_encrypt(self, value, encrypt):
raw = str(value or "")
mode = int(encrypt or 0)
if not raw:
return ""
try:
if mode == 1:
return unquote(raw)
if mode == 2:
decoded = base64.b64decode(raw).decode("utf-8")
return unquote(decoded)
if mode == 3:
text = raw[8:] if len(raw) > 16 else raw
text = base64.b64decode(text).decode("utf-8")
if len(text) > 16:
text = text[8:-8]
return text
return raw
except Exception:
return raw