1
0
mirror of https://codeberg.org/polarisfm/youtube-dl synced 2024-11-26 18:34:32 +01:00

[zingmp3_vn] Add new extractor

This commit is contained in:
hatienl0i261299 2020-03-28 21:08:00 +07:00
parent 189186a9a6
commit 1eccbbbb3f

View File

@ -21,8 +21,7 @@ class Zingmp3_vnIE(InfoExtractor):
_VALID_URL = r'''(?x)^ _VALID_URL = r'''(?x)^
((http[s]?|fpt):)\/?\/(www\.|m\.|) ((http[s]?|fpt):)\/?\/(www\.|m\.|)
(?P<site> (?P<site>
(?:(zingmp3\.vn)| (zingmp3\.vn)
(mp3\.zing\.vn))
)\/(?P<type>bai-hat|video-clip|embed)\/(?P<slug>.*?)\/(?P<id>.*?)\W )\/(?P<type>bai-hat|video-clip|embed)\/(?P<slug>.*?)\/(?P<id>.*?)\W
''' '''
IE_NAME = 'zingmp3_vn' IE_NAME = 'zingmp3_vn'
@ -108,31 +107,26 @@ class Zingmp3_vnIE(InfoExtractor):
_default_host = "https://zingmp3.vn/" _default_host = "https://zingmp3.vn/"
def _real_extract(self, url): def _real_extract(self, url):
self.convert_oldDomain_to_newDomain(url)
mobj = re.search(self._VALID_URL, url) mobj = re.search(self._VALID_URL, url)
video_id = mobj.group('id') video_id = mobj.group('id')
type = mobj.group('type') _type = mobj.group('type')
slug = mobj.group('slug') slug = mobj.group('slug')
return self.extract_info_media(type, slug, video_id) return self.extract_info_media(_type, slug, video_id)
def convert_oldDomain_to_newDomain(self,url): def extract_info_media(self, _type, slug, video_id):
if 'mp3.zing.vn' in url:
url = url.replace('mp3.zing.vn','zingmp3.vn')
return url
def extract_info_media(self, type, slug, video_id):
formats = [] formats = []
name_api = '' name_api = ''
if type == 'bai-hat': if _type == 'bai-hat':
name_api = '/song/get-song-info' name_api = '/song/get-song-info'
elif type == 'embed': elif _type == 'embed':
if slug and slug == 'song': if slug and slug == 'song':
name_api = '/song/get-song-info' name_api = '/song/get-song-info'
elif type == 'video-clip': elif _type == 'video-clip':
name_api = "/video/get-video-detail" name_api = "/video/get-video-detail"
api = self.get_api_with_signature(name_api=name_api, video_id=video_id) api = self.get_api_with_signature(name_api=name_api, video_id=video_id)
info = self._download_json(url_or_request=api, video_id=video_id) info = self._download_json(url_or_request=api, video_id=video_id)
if type == 'video-clip' and not self._downloader.params.get("cookiefile"): if _type == 'video-clip' and not self._downloader.params.get("cookiefile"):
# TODO: Have api can get best quality like 1080p, 720p, default if dont have VIP just 480p is best quality. # TODO: Have api can get best quality like 1080p, 720p, default if dont have VIP just 480p is best quality.
# If requests are continuous without downtime, # If requests are continuous without downtime,
# you may be blocked IP for a short period of time, # you may be blocked IP for a short period of time,
@ -195,7 +189,7 @@ class Zingmp3_vnIE(InfoExtractor):
streaming = data.get('streaming') streaming = data.get('streaming')
if streaming.get('msg'): if streaming.get('msg'):
if type == 'video-clip': if _type == 'video-clip':
stream_data = streaming.get('data', dict) stream_data = streaming.get('data', dict)
for protocol, stream in stream_data.items(): for protocol, stream in stream_data.items():
if protocol == 'default': if protocol == 'default':
@ -220,9 +214,9 @@ class Zingmp3_vnIE(InfoExtractor):
else: else:
if streaming.get('msg') != "Success": if streaming.get('msg') != "Success":
self.to_screen( self.to_screen(
f" - {self.IE_NAME} requires authentication.\n" "Zingmp3_vn requires authentication."
f"\t\t- Because This media need VIP account to listen or watch.\n" "Because This media need VIP account to listen or watch."
f"\t\t- You may want to use --cookies.\n\n" "You may want to use --cookies FILE."
) )
return return
default = streaming.get('default') default = streaming.get('default')
@ -265,11 +259,13 @@ class Zingmp3_vnIE(InfoExtractor):
'formats': formats 'formats': formats
} }
def get_api_with_signature(self, name_api, video_id='', alias='', type='', new_release=False): def get_api_with_signature(self, name_api, video_id='', alias='', _type='', new_release=False):
""" """
- The api of this site has 1 param named sig => signature - The api of this site has 1 param named sig => signature
- It uses the hash function of the variables ctime, id, and name_api. - It uses the hash function of the variables ctime, id, and name_api.
- Sone api don't need id, just need ctime and name_api, - Sone api don't need id, just need ctime and name_api,
:param _type:
:param alias:
:param name_api: :param name_api:
:param video_id: :param video_id:
:param type: :param type:
@ -280,6 +276,7 @@ class Zingmp3_vnIE(InfoExtractor):
SECRET_KEY = b'10a01dcf33762d3a204cb96429918ff6' SECRET_KEY = b'10a01dcf33762d3a204cb96429918ff6'
if not name_api: if not name_api:
return return
_time = str(int(datetime.datetime.now().timestamp()))
def get_hash256(string): def get_hash256(string):
return hashlib.sha256(string.encode('utf-8')).hexdigest() return hashlib.sha256(string.encode('utf-8')).hexdigest()
@ -295,74 +292,69 @@ class Zingmp3_vnIE(InfoExtractor):
data = "&".join(data) data = "&".join(data)
return data return data
def get_api_by_id(id): def get_api_by_id(_id):
url = f"https://zingmp3.vn/api{name_api}?id={id}&" url = r"https://zingmp3.vn/api%s?id=%s&" % (name_api, _id)
time = str(int(datetime.datetime.now().timestamp())) sha256 = get_hash256(r"ctime=%sid=%s" % (_time, _id))
sha256 = get_hash256(f"ctime={time}id={id}")
data = { data = {
'ctime': time, 'ctime': _time,
'api_key': API_KEY, 'api_key': API_KEY,
'sig': get_hmac512(f"{name_api}{sha256}") 'sig': get_hmac512(r"%s%s" % (name_api, sha256))
} }
return url + get_request_path(data) return url + get_request_path(data)
def get_api_chart(type): def get_api_chart(_type):
url = f"https://zingmp3.vn/api{name_api}?type={type}&" url = r"https://zingmp3.vn/api%s?type=%s&" % (name_api, _type)
time = str(int(datetime.datetime.now().timestamp())) sha256 = get_hash256(r"ctime=%s" % (_time))
sha256 = get_hash256(f"ctime={time}")
data = { data = {
'ctime': time, 'ctime': _time,
'api_key': API_KEY, 'api_key': API_KEY,
'sig': get_hmac512(f"{name_api}{sha256}") 'sig': get_hmac512(r"%s%s" % (name_api, sha256))
} }
return url + get_request_path(data) return url + get_request_path(data)
def get_api_new_release(): def get_api_new_release():
url = f"https://zingmp3.vn/api{name_api}?" url = r"https://zingmp3.vn/api%s?" % (name_api)
time = str(int(datetime.datetime.now().timestamp())) sha256 = get_hash256(r"ctime=%s" % (_time))
sha256 = get_hash256(f"ctime={time}")
data = { data = {
'ctime': time, 'ctime': _time,
'api_key': API_KEY, 'api_key': API_KEY,
'sig': get_hmac512(f"{name_api}{sha256}") 'sig': get_hmac512(r"%s%s" % (name_api, sha256))
} }
return url + get_request_path(data) return url + get_request_path(data)
def get_api_download(id): def get_api_download(_id):
url = f"https://download.zingmp3.vn/api{name_api}?id={id}&" url = r"https://download.zingmp3.vn/api%s?id=%s&" % (name_api, _id)
time = str(int(datetime.datetime.now().timestamp())) sha256 = get_hash256(r"ctime=%sid=%s" % (_time, _id))
sha256 = get_hash256(f"ctime={time}id={id}")
data = { data = {
'ctime': time, 'ctime': _time,
'api_key': API_KEY, 'api_key': API_KEY,
'sig': get_hmac512(f"{name_api}{sha256}") 'sig': get_hmac512(r"%s%s" % (name_api, sha256))
} }
return url + get_request_path(data) return url + get_request_path(data)
def get_api_info_alias(alias): def get_api_info_alias(alias):
url = f"https://zingmp3.vn/api{name_api}?alias={alias}&" url = r"https://zingmp3.vn/api%s?alias=%s&" % (name_api, alias)
time = str(int(datetime.datetime.now().timestamp())) sha256 = get_hash256(r"ctime=%s" % (_time))
sha256 = get_hash256(f"ctime={time}")
data = { data = {
'ctime': time, 'ctime': _time,
'api_key': API_KEY, 'api_key': API_KEY,
'sig': get_hmac512(f"{name_api}{sha256}") 'sig': get_hmac512(r"%s%s" % (name_api, sha256))
} }
return url + get_request_path(data) return url + get_request_path(data)
if 'download' in name_api: if 'download' in name_api:
return get_api_download(id=video_id) return get_api_download(_id=video_id)
if alias: if alias:
return get_api_info_alias(alias) return get_api_info_alias(alias)
if video_id: if video_id:
return get_api_by_id(video_id) return get_api_by_id(video_id)
if type: if _type:
return get_api_chart(type) return get_api_chart(_type)
if new_release: if new_release:
return get_api_new_release() return get_api_new_release()
return return
@ -374,8 +366,7 @@ class Zingmp3_vnPlaylistIE(Zingmp3_vnIE):
_VALID_URL = r'''(?x)^ _VALID_URL = r'''(?x)^
((http[s]?|fpt):)\/?\/(www\.|m\.|) ((http[s]?|fpt):)\/?\/(www\.|m\.|)
(?P<site> (?P<site>
(?:(zingmp3\.vn)| (zingmp3\.vn)
(mp3\.zing\.vn))
)\/(?P<type>album|playlist)\/(?P<slug>.*?)\/(?P<playlist_id>.*?)\W )\/(?P<type>album|playlist)\/(?P<slug>.*?)\/(?P<playlist_id>.*?)\W
''' '''
@ -416,7 +407,6 @@ class Zingmp3_vnPlaylistIE(Zingmp3_vnIE):
name_api = '/playlist/get-playlist-detail' name_api = '/playlist/get-playlist-detail'
def _real_extract(self, url): def _real_extract(self, url):
self.convert_oldDomain_to_newDomain(url)
mobj = re.search(self._VALID_URL, url) mobj = re.search(self._VALID_URL, url)
playlist_id = mobj.group('playlist_id') playlist_id = mobj.group('playlist_id')
return self._extract_playlist(id_playlist=playlist_id) return self._extract_playlist(id_playlist=playlist_id)
@ -449,13 +439,12 @@ class Zingmp3_vnUserIE(Zingmp3_vnIE):
_VALID_URL = r'''(?x)^ _VALID_URL = r'''(?x)^
((http[s]?|fpt):)\/?\/(www\.|m\.|) ((http[s]?|fpt):)\/?\/(www\.|m\.|)
(?P<site> (?P<site>
(?:(zingmp3\.vn)| (zingmp3\.vn)
(mp3\.zing\.vn))
)\/(?P<nghe_si>nghe-si\/|) )\/(?P<nghe_si>nghe-si\/|)
(?P<name>.*?) (?P<name>.*?)
(?:$|\/) (?:$|\/)
(?: (?:
(?P<name_chu_de>.*?)\/(?P<id_chu_de>.*?\.) (?P<name_chu_de>.*?)\/(?P<id_chu_de>.*?)\.
| |
(?P<slug_name>.*?$) (?P<slug_name>.*?$)
) )
@ -551,7 +540,6 @@ class Zingmp3_vnUserIE(Zingmp3_vnIE):
} }
def _real_extract(self, url): def _real_extract(self, url):
self.convert_oldDomain_to_newDomain(url)
mobj = re.search(self._VALID_URL, url) mobj = re.search(self._VALID_URL, url)
name = mobj.group('name') name = mobj.group('name')
slug_name = mobj.group('slug_name') slug_name = mobj.group('slug_name')
@ -562,7 +550,7 @@ class Zingmp3_vnUserIE(Zingmp3_vnIE):
name_api = self.list_name_api_user.get(slug_name) or None name_api = self.list_name_api_user.get(slug_name) or None
self.id_artist = None self.id_artist = None
if nghe_si: if nghe_si:
webpage = self._download_webpage(url_or_request=f"https://mp3.zing.vn/nghe-si/{name}", video_id=name) webpage = self._download_webpage(url_or_request=r"https://mp3.zing.vn/nghe-si/%s" % (name), video_id=name)
self.id_artist = self._search_regex(r'''(?x) self.id_artist = self._search_regex(r'''(?x)
\<a.*?tracking=\"\_frombox=artist_artistfollow\" \<a.*?tracking=\"\_frombox=artist_artistfollow\"
\s+data-id=\"(?P<id_artist>.*?)\" \s+data-id=\"(?P<id_artist>.*?)\"
@ -580,7 +568,7 @@ class Zingmp3_vnUserIE(Zingmp3_vnIE):
return self.playlist_result( return self.playlist_result(
entries=self._entries(), entries=self._entries(),
playlist_id=self.id_artist, playlist_id=self.id_artist,
playlist_title=f"{name}-{slug_name}" playlist_title=r"%s-%s" % (name, slug_name)
) )
elif name == 'chu-de': elif name == 'chu-de':
self.IE_NAME = "zingmp3_vn:chu-de" self.IE_NAME = "zingmp3_vn:chu-de"
@ -659,11 +647,11 @@ class Zingmp3_vnUserIE(Zingmp3_vnIE):
class Zingmp3_vnChartIE(Zingmp3_vnIE): class Zingmp3_vnChartIE(Zingmp3_vnIE):
IE_NAME = "zingmp3_vn:#zingchart" IE_NAME = "zingmp3_vn:#zingchart"
_VALID_URL = r'''(?x)^ _VALID_URL = r'''(?x)^
((http[s]?|fpt):)\/?\/(www\.|m\.|) ((http[s]?|fpt):)\/?\/(www\.|m\.|)
(?P<site> (?P<site>
(?:(zingmp3\.vn)| (zingmp3\.vn)
(mp3\.zing\.vn))
)\/(?P<name>zing-chart-tuan|zing-chart|top-new-release)\/ )\/(?P<name>zing-chart-tuan|zing-chart|top-new-release)\/
(?P<slug_name>.*?)(\.|\/)(?P<id_name>.*?\.)? (?P<slug_name>.*?)(\.|\/)(?P<id_name>.*?\.)?
''' '''
@ -720,7 +708,6 @@ class Zingmp3_vnChartIE(Zingmp3_vnIE):
} }
def _real_extract(self, url): def _real_extract(self, url):
self.convert_oldDomain_to_newDomain(url)
mobj = re.search(self._VALID_URL, url) mobj = re.search(self._VALID_URL, url)
name = mobj.group('name') name = mobj.group('name')
slug_name = mobj.group('slug_name') slug_name = mobj.group('slug_name')
@ -728,7 +715,7 @@ class Zingmp3_vnChartIE(Zingmp3_vnIE):
if name == 'zing-chart': if name == 'zing-chart':
api = self.get_api_with_signature( api = self.get_api_with_signature(
name_api=self.list_name_api.get(name).get('name'), name_api=self.list_name_api.get(name).get('name'),
type=self.list_name_api.get(name).get(slug_name) _type=self.list_name_api.get(name).get(slug_name)
) )
elif name == 'zing-chart-tuan': elif name == 'zing-chart-tuan':
api = self.get_api_with_signature( api = self.get_api_with_signature(
@ -740,11 +727,18 @@ class Zingmp3_vnChartIE(Zingmp3_vnIE):
name_api=self.list_name_api.get(name).get('name'), name_api=self.list_name_api.get(name).get('name'),
new_release=True new_release=True
) )
count = 0
info = None
while count != 3:
webpage = self._download_webpage(url_or_request=api, video_id=name) webpage = self._download_webpage(url_or_request=api, video_id=name)
if webpage:
info = self._parse_json(webpage, name, transform_source=js_to_json) info = self._parse_json(webpage, name, transform_source=js_to_json)
break
count += 1
if info:
return self.playlist_result( return self.playlist_result(
entries=self._entries(try_get(info, lambda x: x['data']['items'])), entries=self._entries(try_get(info, lambda x: x['data']['items'])),
playlist_title=f"{name}-{slug_name}" playlist_title=r"%s-%s" % (name, slug_name)
) )
def _entries(self, items): def _entries(self, items):