]>
jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/zingmp3.py
2 from __future__
import unicode_literals
8 from .common
import InfoExtractor
16 class ZingMp3BaseIE(InfoExtractor
):
17 _VALID_URL_TMPL
= r
'https?://(?:mp3\.zing|zingmp3)\.vn/(?P<type>(?:%s))/[^/]+/(?P<id>\w+)(?:\.html|\?)'
18 _GEO_COUNTRIES
= ['VN']
19 _DOMAIN
= 'https://zingmp3.vn'
21 'bai-hat': '/api/v2/page/get/song',
22 'embed': '/api/v2/page/get/song',
23 'video-clip': '/api/v2/page/get/video',
24 'playlist': '/api/v2/page/get/playlist',
25 'album': '/api/v2/page/get/playlist',
26 'lyric': '/api/v2/lyric/get/lyric',
27 'song_streaming': '/api/v2/song/get/streaming',
30 _API_KEY
= '88265e23d4284f25963e6eedac8fbfa3'
31 _SECRET_KEY
= b
'2aa2d1c561e809b267f3638c4a307aab'
33 def _extract_item(self
, item
, song_id
, type_url
, fatal
):
34 item_id
= item
.get('encodeId') or song_id
35 title
= item
.get('title') or item
.get('alias')
37 if type_url
== 'video-clip':
38 source
= item
.get('streaming')
40 api
= self
.get_api_with_signature(name_api
=self
._SLUG
_API
.get('song_streaming'), param
={'id': item_id}
)
41 source
= self
._download
_json
(api
, video_id
=item_id
).get('data')
44 for k
, v
in (source
or {}).items():
47 if k
in ('mp4', 'hls'):
48 for res
, video_url
in v
.items():
52 formats
.extend(self
._extract
_m
3u8_formats
(
53 video_url
, item_id
, 'mp4',
54 'm3u8_native', m3u8_id
=k
, fatal
=False))
57 'format_id': 'mp4-' + res
,
59 'height': int_or_none(self
._search
_regex
(
60 r
'^(\d+)p', res
, 'resolution', default
=None)),
68 'tbr': int_or_none(k
),
69 'url': self
._proto
_relative
_url
(v
),
76 if msg
== 'Sorry, this content is not available in your country.':
77 self
.raise_geo_restricted(countries
=self
._GEO
_COUNTRIES
, metadata_available
=True)
78 self
.raise_no_formats(msg
, expected
=True)
79 self
._sort
_formats
(formats
)
81 lyric
= item
.get('lyric')
83 api
= self
.get_api_with_signature(name_api
=self
._SLUG
_API
.get("lyric"), param
={'id': item_id}
)
84 info_lyric
= self
._download
_json
(api
, video_id
=item_id
)
85 lyric
= traverse_obj(info_lyric
, ('data', 'file'))
92 album
= item
.get('album') or {}
98 'thumbnail': traverse_obj(item
, 'thumbnail', 'thumbnailM'),
99 'subtitles': subtitles
,
100 'duration': int_or_none(item
.get('duration')),
102 'artist': traverse_obj(item
, 'artistsNames', 'artists_names'),
103 'album': traverse_obj(album
, 'name', 'title'),
104 'album_artist': traverse_obj(album
, 'artistsNames', 'artists_names'),
107 def _real_initialize(self
):
108 if not self
.get_param('cookiefile') and not self
.get_param('cookiesfrombrowser'):
109 self
._request
_webpage
(HEADRequest(self
._DOMAIN
), None, note
='Updating cookies')
111 def _real_extract(self
, url
):
112 song_id
, type_url
= self
._match
_valid
_url
(url
).group('id', 'type')
114 api
= self
.get_api_with_signature(name_api
=self
._SLUG
_API
[type_url
], param
={'id': song_id}
)
116 return self
._process
_data
(self
._download
_json
(api
, song_id
)['data'], song_id
, type_url
)
118 def get_api_with_signature(self
, name_api
, param
):
119 sha256
= hashlib
.sha256(''.join(f
'{k}={v}' for k
, v
in param
.items()).encode('utf-8')).hexdigest()
122 'apiKey': self
._API
_KEY
,
123 'sig': hmac
.new(self
._SECRET
_KEY
, f
'{name_api}{sha256}'.encode('utf-8'), hashlib
.sha512
).hexdigest(),
126 return f
'{self._DOMAIN}{name_api}?{urllib.parse.urlencode(data)}'
129 class ZingMp3IE(ZingMp3BaseIE
):
130 _VALID_URL
= ZingMp3BaseIE
._VALID
_URL
_TMPL
% 'bai-hat|video-clip|embed'
132 'url': 'https://mp3.zing.vn/bai-hat/Xa-Mai-Xa-Bao-Thy/ZWZB9WAB.html',
133 'md5': 'ead7ae13693b3205cbc89536a077daed',
136 'title': 'Xa Mãi Xa',
138 'thumbnail': r
're:^https?://.+\.jpg',
145 'track': 'Xa Mãi Xa',
147 'album': 'Special Album',
148 'album_artist': 'Bảo Thy',
151 'url': 'https://zingmp3.vn/video-clip/Suong-Hoa-Dua-Loi-K-ICM-RYO/ZO8ZF7C7.html',
152 'md5': 'e9c972b693aa88301ef981c8151c4343',
155 'title': 'Sương Hoa Đưa Lối',
157 'thumbnail': r
're:^https?://.+\.jpg',
159 'track': 'Sương Hoa Đưa Lối',
160 'artist': 'K-ICM, RYO',
163 'url': 'https://zingmp3.vn/embed/song/ZWZEI76B?start=false',
164 'only_matching': True,
166 'url': 'https://zingmp3.vn/bai-hat/Xa-Mai-Xa-Bao-Thy/ZWZB9WAB.html',
167 'only_matching': True,
170 IE_DESC
= 'zingmp3.vn'
172 def _process_data(self
, data
, song_id
, type_url
):
173 return self
._extract
_item
(data
, song_id
, type_url
, True)
176 class ZingMp3AlbumIE(ZingMp3BaseIE
):
177 _VALID_URL
= ZingMp3BaseIE
._VALID
_URL
_TMPL
% 'album|playlist'
179 'url': 'http://mp3.zing.vn/album/Lau-Dai-Tinh-Ai-Bang-Kieu-Minh-Tuyet/ZWZBWDAF.html',
183 'title': 'Lâu Đài Tình Ái',
187 'url': 'http://mp3.zing.vn/playlist/Duong-Hong-Loan-apollobee/IWCAACCB.html',
188 'only_matching': True,
190 'url': 'https://zingmp3.vn/album/Lau-Dai-Tinh-Ai-Bang-Kieu-Minh-Tuyet/ZWZBWDAF.html',
191 'only_matching': True,
193 IE_NAME
= 'zingmp3:album'
195 def _process_data(self
, data
, song_id
, type_url
):
197 for item
in traverse_obj(data
, ('song', 'items')) or []:
198 entry
= self
._extract
_item
(item
, song_id
, type_url
, False)
202 return self
.playlist_result(entries(), traverse_obj(data
, 'id', 'encodeId'),
203 traverse_obj(data
, 'name', 'title'))