feat: add AAZ音乐 playback support
This commit is contained in:
+34
@@ -1,4 +1,5 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
import json
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from urllib.parse import quote, urljoin
|
from urllib.parse import quote, urljoin
|
||||||
@@ -194,6 +195,27 @@ class Spider(BaseSpider):
|
|||||||
)
|
)
|
||||||
return rows
|
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):
|
def homeContent(self, filter):
|
||||||
items = self._parse_song_cards(self._fetch_html(self.category_paths["new"]))
|
items = self._parse_song_cards(self._fetch_html(self.category_paths["new"]))
|
||||||
return {"class": list(self.classes), "list": items}
|
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),
|
||||||
|
}
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ FOLDER_DETAIL_HTML = """
|
|||||||
</body></html>
|
</body></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):
|
class TestAAZMusicSpider(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -191,6 +194,20 @@ class TestAAZMusicSpider(unittest.TestCase):
|
|||||||
def test_detail_content_returns_empty_list_for_invalid_vod_id(self):
|
def test_detail_content_returns_empty_list_for_invalid_vod_id(self):
|
||||||
self.assertEqual(self.spider.detailContent(["bad"])["list"], [])
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user