From e1d64f84e9acd56ae5f9f6402de949d537258b45 Mon Sep 17 00:00:00 2001
From: Harold <8866033@gmail.com>
Date: Fri, 24 Apr 2026 17:48:09 +0800
Subject: [PATCH] fix: support lumman tudou parser flow
---
py/tests/test_路漫漫.py | 35 +++++++++++++++++++++++++++++++++++
py/路漫漫.py | 37 +++++++++++++++++++++++++++++--------
2 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/py/tests/test_路漫漫.py b/py/tests/test_路漫漫.py
index c738906..12732f6 100644
--- a/py/tests/test_路漫漫.py
+++ b/py/tests/test_路漫漫.py
@@ -189,6 +189,41 @@ class TestLuManManSpider(unittest.TestCase):
)
self.assertEqual(result, "")
+ @patch.object(Spider, "_post_json")
+ @patch.object(Spider, "_get_html")
+ def test_resolve_player_url_supports_tudou_yunbox_flow(self, mock_html, mock_post_json):
+ player = {"url": "DU_token_value&t=DU", "encrypt": "0", "from": "tudou"}
+ mock_html.side_effect = [
+ """
+ MacPlayer.Html = '';
+ document.getElementById('playerCnt').src = 'https://yun.92cj.com/acfun58.php?id=' + MacPlayer.Parse + MacPlayer.PlayUrl + '&referer='+ window.location.href;
+ """,
+ """
+
+ """,
+ ]
+ mock_post_json.return_value = {"url": "https://video.example.com/final.m3u8"}
+ result = self.spider._resolve_player_url(player, "https://www.lmm85.com/play/7541_2_1.html")
+ self.assertEqual(result, "https://video.example.com/final.m3u8")
+ mock_post_json.assert_called_once_with(
+ "https://yun.92cj.com/yunbox/ducloud.php",
+ {
+ "vid": "DU_token_value",
+ "t": "1777023867",
+ "token": "659d24991db8fb7e2750e30f7afb3107",
+ "act": "0",
+ "play": "1",
+ },
+ referer="https://yun.92cj.com/yunbox/?type=DU&vid=DU_token_value&referer=https://www.lmm85.com/play/7541_2_1.html",
+ )
+
if __name__ == "__main__":
unittest.main()
diff --git a/py/路漫漫.py b/py/路漫漫.py
index a20418d..27a3f94 100644
--- a/py/路漫漫.py
+++ b/py/路漫漫.py
@@ -251,9 +251,26 @@ class Spider(BaseSpider):
raw = re.sub(r"[\+\s']", "", matched.group(1))
raw = raw.replace("MacPlayer.PlayUrl", video_url)
raw = raw.replace("window.location.href", play_page_url)
- raw = raw.replace("MacPlayer.Parse", self.host + "/?url=")
+ if "acfun58.php?id=" in raw or "yun.92cj.com" in raw:
+ raw = raw.replace("MacPlayer.Parse", "")
+ else:
+ raw = raw.replace("MacPlayer.Parse", self.host + "/?url=")
return raw
+ def _build_tudou_yunbox_url(self, video_url, play_page_url):
+ raw = str(video_url or "").strip()
+ source_type = ""
+ vid = raw
+ matched = re.search(r"[?&]t=([^&]+)$", raw)
+ if matched:
+ source_type = matched.group(1)
+ vid = raw[: matched.start()]
+ vid = vid.replace("+", " ")
+ return (
+ "https://yun.92cj.com/yunbox/"
+ f"?type={quote(source_type)}&vid={quote(vid)}&referer={play_page_url}"
+ )
+
def _resolve_player_url(self, player, play_page_url):
media = self._decode_player_url(player.get("url", ""), player.get("encrypt", "0"))
if self._is_media_url(media):
@@ -263,27 +280,31 @@ class Spider(BaseSpider):
return ""
js_url = f"{self.host}/static/player/{source}.js"
js_text = self._get_html(js_url, headers={"Referer": play_page_url})
- iframe_url = self._extract_js_src(js_text, media, play_page_url)
- if not iframe_url or "type=" not in iframe_url:
+ parser_page_url = ""
+ if source == "tudou":
+ parser_page_url = self._build_tudou_yunbox_url(media, play_page_url)
+ else:
+ parser_page_url = self._extract_js_src(js_text, media, play_page_url)
+ if not parser_page_url or ("type=" not in parser_page_url and source != "tudou"):
return ""
- iframe_html = self._get_html(iframe_url, headers={"Referer": self.host})
+ iframe_html = self._get_html(parser_page_url, headers={"Referer": play_page_url})
if not re.search(r'vid\s*=\s*".+?"', iframe_html):
return ""
api_path = self.regStr(r'post\("(.*?)"', iframe_html)
if not api_path:
return ""
- post_url = urljoin(self.host + "/", api_path.lstrip("/"))
+ post_url = urljoin(parser_page_url, api_path.lstrip("/"))
token = self.regStr(r'token\s*=\s*"(.*?)"', iframe_html)
payload = {
"vid": self.regStr(r'vid\s*=\s*"(.*?)"', iframe_html),
- "t": self.regStr(r'var\s+t\s*=\s*"(.*?)"', iframe_html),
+ "t": self.regStr(r'\bvar\s+t\s*=\s*"(.*?)"', iframe_html),
"token": self._decrypt_token(token),
"act": self.regStr(r'act\s*=\s*"(.*?)"', iframe_html),
"play": self.regStr(r'play\s*=\s*"(.*?)"', iframe_html),
}
- data = self._post_json(post_url, payload, referer=self.host)
+ post_referer = parser_page_url if source == "tudou" else self.host
+ data = self._post_json(post_url, payload, referer=post_referer)
return str(data.get("url", "")).strip()
- return ""
def playerContent(self, flag, id, vipFlags):
play_page_url = self._decode_play_id(id)