feat: add feikuai player parsing
This commit is contained in:
@@ -116,3 +116,30 @@ class TestFeikuaiSpider(unittest.TestCase):
|
||||
vod["vod_play_url"],
|
||||
"第1集$/vodplay/1-1-1.html#第2集$/vodplay/1-1-2.html$$$第1集$/vodplay/1-2-1.html$$$夸克资源$https://pan.quark.cn/s/demo1$$$百度合集$https://pan.baidu.com/s/demo2",
|
||||
)
|
||||
|
||||
def test_base64decode_decodes_fixture(self):
|
||||
self.assertEqual(
|
||||
self.spider._base64decode("aHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vdjIubTN1OA=="),
|
||||
"https://cdn.example.com/v2.m3u8",
|
||||
)
|
||||
|
||||
@patch.object(Spider, "_request_html")
|
||||
def test_player_content_supports_encrypt_1_and_encrypt_2(self, mock_request_html):
|
||||
mock_request_html.side_effect = [
|
||||
'<script>player_aaaa={"url":"https%3A//cdn.example.com/v1.m3u8","encrypt":"1"}</script>',
|
||||
'<script>player_aaaa={"url":"aHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vdjIubTN1OA==","encrypt":"2"}</script>',
|
||||
]
|
||||
direct = self.spider.playerContent("feikuai", "/vodplay/1-1-1.html", {})
|
||||
encoded = self.spider.playerContent("feikuai", "/vodplay/1-1-2.html", {})
|
||||
self.assertEqual(direct["parse"], 0)
|
||||
self.assertEqual(direct["url"], "https://cdn.example.com/v1.m3u8")
|
||||
self.assertEqual(encoded["parse"], 0)
|
||||
self.assertEqual(encoded["url"], "https://cdn.example.com/v2.m3u8")
|
||||
|
||||
@patch.object(Spider, "_request_html")
|
||||
def test_player_content_falls_back_when_script_missing(self, mock_request_html):
|
||||
mock_request_html.return_value = "<html><body>empty</body></html>"
|
||||
result = self.spider.playerContent("feikuai", "/vodplay/1-1-3.html", {})
|
||||
self.assertEqual(result["parse"], 1)
|
||||
self.assertEqual(result["jx"], 1)
|
||||
self.assertEqual(result["url"], "https://feikuai.tv/vodplay/1-1-3.html")
|
||||
|
||||
+41
-1
@@ -1,7 +1,9 @@
|
||||
# coding=utf-8
|
||||
import base64
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from urllib.parse import quote, urljoin
|
||||
from urllib.parse import quote, unquote, urljoin
|
||||
|
||||
from base.spider import Spider as BaseSpider
|
||||
|
||||
@@ -134,6 +136,21 @@ class Spider(BaseSpider):
|
||||
def _join_group_urls(self, groups):
|
||||
return "$$$".join("#".join(group) for group in groups if group)
|
||||
|
||||
def _base64decode(self, value):
|
||||
try:
|
||||
return base64.b64decode(str(value or "")).decode("utf-8")
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
def _extract_player_data(self, html):
|
||||
matched = re.search(r"player_aaaa\s*=\s*(\{[\s\S]*?\})", str(html or ""))
|
||||
if not matched:
|
||||
return {}
|
||||
try:
|
||||
return json.loads(matched.group(1))
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
page = max(1, int(pg))
|
||||
url = self.host + f"/vodshow/{tid}--------{page}---.html"
|
||||
@@ -213,3 +230,26 @@ class Spider(BaseSpider):
|
||||
"vod_play_url": self._join_group_urls(play_urls),
|
||||
}
|
||||
return {"list": [vod]}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
raw_id = str(id or "")
|
||||
if raw_id.startswith(("http://", "https://")) and any(
|
||||
raw_id.lower().split("?")[0].endswith(ext) for ext in [".m3u8", ".mp4", ".flv"]
|
||||
):
|
||||
return {"parse": 0, "jx": 0, "url": raw_id}
|
||||
|
||||
target = self.host + raw_id
|
||||
data = self._extract_player_data(self._request_html(target))
|
||||
raw_url = str(data.get("url") or "")
|
||||
encrypt = str(data.get("encrypt") or "")
|
||||
media_url = ""
|
||||
if encrypt == "1":
|
||||
media_url = unquote(raw_url)
|
||||
elif encrypt == "2":
|
||||
media_url = unquote(self._base64decode(raw_url))
|
||||
elif raw_url:
|
||||
media_url = raw_url
|
||||
|
||||
if media_url.startswith("http"):
|
||||
return {"parse": 0, "jx": 0, "url": media_url}
|
||||
return {"parse": 1, "jx": 1, "url": target}
|
||||
|
||||
Reference in New Issue
Block a user