diff --git a/py/AAZ音乐.py b/py/AAZ音乐.py index 1d21689..ee7478a 100644 --- a/py/AAZ音乐.py +++ b/py/AAZ音乐.py @@ -1,4 +1,5 @@ # coding=utf-8 +import json import re import sys from urllib.parse import quote, urljoin @@ -194,6 +195,27 @@ class Spider(BaseSpider): ) return rows + def _post_play_api(self, song_id): + body = "id=%s&type=music" % quote(str(song_id or "")) + response = self.fetch( + self._build_url("/js/play.php"), + headers={ + "User-Agent": self.headers["User-Agent"], + "Referer": self._build_url("/m/%s.html" % song_id), + "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", + "X-Requested-With": "XMLHttpRequest", + }, + data=body, + timeout=10, + verify=False, + ) + if getattr(response, "status_code", 0) != 200: + return {} + try: + return json.loads(getattr(response, "text", "") or "{}") + except Exception: + return {} + def homeContent(self, filter): items = self._parse_song_cards(self._fetch_html(self.category_paths["new"])) return {"class": list(self.classes), "list": items} @@ -262,3 +284,15 @@ class Spider(BaseSpider): } ] } + + def playerContent(self, flag, id, vipFlags): + raw = str(id or "").strip() + if not raw.startswith("song:"): + return {"parse": 0, "url": "", "header": dict(self.headers)} + song_id = raw.split(":", 1)[1] + payload = self._post_play_api(song_id) + return { + "parse": 0, + "url": self._clean_text(payload.get("url")), + "header": dict(self.headers), + } diff --git a/py/tests/test_AAZ音乐.py b/py/tests/test_AAZ音乐.py index 2aa2913..b5fa3e6 100644 --- a/py/tests/test_AAZ音乐.py +++ b/py/tests/test_AAZ音乐.py @@ -97,6 +97,9 @@ FOLDER_DETAIL_HTML = """ """ +PLAY_JSON = '{"url":"https://cdn.example.com/aaz/song2001.mp3","pic":"https://cdn.example.com/cover.jpg"}' +EMPTY_PLAY_JSON = '{"url":""}' + class TestAAZMusicSpider(unittest.TestCase): def setUp(self): @@ -191,6 +194,20 @@ class TestAAZMusicSpider(unittest.TestCase): def test_detail_content_returns_empty_list_for_invalid_vod_id(self): self.assertEqual(self.spider.detailContent(["bad"])["list"], []) + @patch.object(Spider, "fetch") + def test_player_content_resolves_song_id_to_direct_url(self, mock_fetch): + mock_fetch.return_value = SimpleNamespace(status_code=200, text=PLAY_JSON) + result = self.spider.playerContent("AAZ音乐", "song:2001", {}) + self.assertEqual(result["parse"], 0) + self.assertEqual(result["url"], "https://cdn.example.com/aaz/song2001.mp3") + self.assertEqual(result["header"]["Referer"], "https://www.aaz.cx/") + + @patch.object(Spider, "fetch") + def test_player_content_returns_empty_url_for_invalid_or_empty_payload(self, mock_fetch): + mock_fetch.return_value = SimpleNamespace(status_code=200, text=EMPTY_PLAY_JSON) + self.assertEqual(self.spider.playerContent("AAZ音乐", "song:2001", {})["url"], "") + self.assertEqual(self.spider.playerContent("AAZ音乐", "bad", {})["url"], "") + if __name__ == "__main__": unittest.main()