|
1 | 1 | from .common import InfoExtractor
|
2 |
| -from ..utils import js_to_json, traverse_obj |
| 2 | +from ..utils import ( |
| 3 | + ExtractorError, |
| 4 | + clean_html, |
| 5 | + url_or_none, |
| 6 | +) |
| 7 | +from ..utils.traversal import subs_list_to_dict, traverse_obj |
3 | 8 |
|
4 | 9 |
|
5 | 10 | class MonsterSirenHypergryphMusicIE(InfoExtractor):
|
| 11 | + IE_NAME = 'monstersiren' |
| 12 | + IE_DESC = '塞壬唱片' |
| 13 | + _API_BASE = 'https://monster-siren.hypergryph.com/api' |
6 | 14 | _VALID_URL = r'https?://monster-siren\.hypergryph\.com/music/(?P<id>\d+)'
|
7 | 15 | _TESTS = [{
|
8 | 16 | 'url': 'https://monster-siren.hypergryph.com/music/514562',
|
9 | 17 | 'info_dict': {
|
10 | 18 | 'id': '514562',
|
11 | 19 | 'ext': 'wav',
|
12 |
| - 'artists': ['塞壬唱片-MSR'], |
13 |
| - 'album': 'Flame Shadow', |
14 | 20 | 'title': 'Flame Shadow',
|
| 21 | + 'album': 'Flame Shadow', |
| 22 | + 'artists': ['塞壬唱片-MSR'], |
| 23 | + 'description': 'md5:19e2acfcd1b65b41b29e8079ab948053', |
| 24 | + 'thumbnail': r're:https?://web\.hycdn\.cn/siren/pic/.+\.jpg', |
| 25 | + }, |
| 26 | + }, { |
| 27 | + 'url': 'https://monster-siren.hypergryph.com/music/514518', |
| 28 | + 'info_dict': { |
| 29 | + 'id': '514518', |
| 30 | + 'ext': 'wav', |
| 31 | + 'title': 'Heavenly Me (Instrumental)', |
| 32 | + 'album': 'Heavenly Me', |
| 33 | + 'artists': ['塞壬唱片-MSR', 'AIYUE blessed : 理名'], |
| 34 | + 'description': 'md5:ce790b41c932d1ad72eb791d1d8ae598', |
| 35 | + 'thumbnail': r're:https?://web\.hycdn\.cn/siren/pic/.+\.jpg', |
15 | 36 | },
|
16 | 37 | }]
|
17 | 38 |
|
18 | 39 | def _real_extract(self, url):
|
19 | 40 | audio_id = self._match_id(url)
|
20 |
| - webpage = self._download_webpage(url, audio_id) |
21 |
| - json_data = self._search_json( |
22 |
| - r'window\.g_initialProps\s*=', webpage, 'data', audio_id, transform_source=js_to_json) |
| 41 | + song = self._download_json(f'{self._API_BASE}/song/{audio_id}', audio_id) |
| 42 | + if traverse_obj(song, 'code') != 0: |
| 43 | + msg = traverse_obj(song, ('msg', {str}, filter)) |
| 44 | + raise ExtractorError( |
| 45 | + msg or 'API returned an error response', expected=bool(msg)) |
| 46 | + |
| 47 | + album = None |
| 48 | + if album_id := traverse_obj(song, ('data', 'albumCid', {str})): |
| 49 | + album = self._download_json( |
| 50 | + f'{self._API_BASE}/album/{album_id}/detail', album_id, fatal=False) |
23 | 51 |
|
24 | 52 | return {
|
25 | 53 | 'id': audio_id,
|
26 |
| - 'title': traverse_obj(json_data, ('player', 'songDetail', 'name')), |
27 |
| - 'url': traverse_obj(json_data, ('player', 'songDetail', 'sourceUrl')), |
28 |
| - 'ext': 'wav', |
29 | 54 | 'vcodec': 'none',
|
30 |
| - 'artists': traverse_obj(json_data, ('player', 'songDetail', 'artists', ...)), |
31 |
| - 'album': traverse_obj(json_data, ('musicPlay', 'albumDetail', 'name')), |
| 55 | + **traverse_obj(song, ('data', { |
| 56 | + 'title': ('name', {str}), |
| 57 | + 'artists': ('artists', ..., {str}), |
| 58 | + 'subtitles': ({'url': 'lyricUrl'}, all, {subs_list_to_dict(lang='en')}), |
| 59 | + 'url': ('sourceUrl', {url_or_none}), |
| 60 | + })), |
| 61 | + **traverse_obj(album, ('data', { |
| 62 | + 'album': ('name', {str}), |
| 63 | + 'description': ('intro', {clean_html}), |
| 64 | + 'thumbnail': ('coverUrl', {url_or_none}), |
| 65 | + })), |
32 | 66 | }
|
0 commit comments