diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | youtube_dl/extractor/__init__.py | 4 | ||||
-rw-r--r-- | youtube_dl/extractor/youtube.py | 8 | ||||
-rw-r--r-- | youtube_dl/extractor/zingmp3.py | 107 |
4 files changed, 116 insertions, 4 deletions
@@ -84,3 +84,4 @@ xantares Jan Matějka Mauroy Sébastien William Sewell +Dao Hoang Son diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index 43185345e..fb5e6ac77 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -511,6 +511,10 @@ from .youtube import ( YoutubeWatchLaterIE, ) from .zdf import ZDFIE +from .zingmp3 import ( + ZingMp3SongIE, + ZingMp3AlbumIE, +) _ALL_CLASSES = [ klass diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index fa3ead95b..4ebc7b712 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -1567,14 +1567,14 @@ class YoutubeFeedsInfoExtractor(YoutubeBaseInfoExtractor): class YoutubeRecommendedIE(YoutubeFeedsInfoExtractor): - IE_DESC = 'YouTube.com recommended videos, "ytrec" keyword (requires authentication)' + IE_DESC = 'YouTube.com recommended videos, ":ytrec" for short (requires authentication)' _VALID_URL = r'https?://www\.youtube\.com/feed/recommended|:ytrec(?:ommended)?' _FEED_NAME = 'recommended' _PLAYLIST_TITLE = 'Youtube Recommended videos' class YoutubeWatchLaterIE(YoutubeFeedsInfoExtractor): - IE_DESC = 'Youtube watch later list, "ytwatchlater" keyword (requires authentication)' + IE_DESC = 'Youtube watch later list, ":ytwatchlater" for short (requires authentication)' _VALID_URL = r'https?://www\.youtube\.com/feed/watch_later|:ytwatchlater' _FEED_NAME = 'watch_later' _PLAYLIST_TITLE = 'Youtube Watch Later' @@ -1582,7 +1582,7 @@ class YoutubeWatchLaterIE(YoutubeFeedsInfoExtractor): class YoutubeHistoryIE(YoutubeFeedsInfoExtractor): - IE_DESC = 'Youtube watch history, "ythistory" keyword (requires authentication)' + IE_DESC = 'Youtube watch history, ":ythistory" for short (requires authentication)' _VALID_URL = 'https?://www\.youtube\.com/feed/history|:ythistory' _FEED_NAME = 'history' _PERSONAL_FEED = True @@ -1591,7 +1591,7 @@ class YoutubeHistoryIE(YoutubeFeedsInfoExtractor): class YoutubeFavouritesIE(YoutubeBaseInfoExtractor): IE_NAME = 'youtube:favorites' - IE_DESC = 'YouTube.com favourite videos, "ytfav" keyword (requires authentication)' + IE_DESC = 'YouTube.com favourite videos, ":ytfav" for short (requires authentication)' _VALID_URL = r'https?://www\.youtube\.com/my_favorites|:ytfav(?:ou?rites)?' _LOGIN_REQUIRED = True diff --git a/youtube_dl/extractor/zingmp3.py b/youtube_dl/extractor/zingmp3.py new file mode 100644 index 000000000..1afbe68ed --- /dev/null +++ b/youtube_dl/extractor/zingmp3.py @@ -0,0 +1,107 @@ +# coding=utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor + + +class ZingMp3BaseInfoExtractor(InfoExtractor): + + @staticmethod + def _extract_item(item): + title = item.find('./title').text.strip() + source = item.find('./source').text + extension = item.attrib['type'] + thumbnail = item.find('./backimage').text + + return { + 'title': title, + 'url': source, + 'ext': extension, + 'thumbnail': thumbnail, + } + + def _extract_player_xml(self, player_xml_url, id, playlist_title=None): + player_xml = self._download_xml(player_xml_url, id, 'Downloading Player XML') + items = player_xml.findall('./item') + + if len(items) == 1: + # one single song + data = self._extract_item(items[0]) + data['id'] = id + + return data + else: + # playlist of songs + entries = [] + + for i, item in enumerate(items, 1): + entry = self._extract_item(item) + entry['id'] = '%s-%d' % (id, i) + entries.append(entry) + + return { + '_type': 'playlist', + 'id': id, + 'title': playlist_title, + 'entries': entries, + } + + +class ZingMp3SongIE(ZingMp3BaseInfoExtractor): + _VALID_URL = r'https?://mp3\.zing\.vn/bai-hat/(?P<slug>[^/]+)/(?P<song_id>\w+)\.html' + _TESTS = [{ + 'url': 'http://mp3.zing.vn/bai-hat/Xa-Mai-Xa-Bao-Thy/ZWZB9WAB.html', + 'md5': 'ead7ae13693b3205cbc89536a077daed', + 'info_dict': { + 'id': 'ZWZB9WAB', + 'title': 'Xa Mãi Xa', + 'ext': 'mp3', + 'thumbnail': 're:^https?://.*\.jpg$', + }, + }] + IE_NAME = 'zingmp3:song' + IE_DESC = 'mp3.zing.vn songs' + + def _real_extract(self, url): + matched = re.match(self._VALID_URL, url) + slug = matched.group('slug') + song_id = matched.group('song_id') + + webpage = self._download_webpage( + 'http://mp3.zing.vn/bai-hat/%s/%s.html' % (slug, song_id), song_id) + + player_xml_url = self._search_regex( + r'&xmlURL=(?P<xml_url>[^&]+)&', webpage, 'player xml url') + + return self._extract_player_xml(player_xml_url, song_id) + + +class ZingMp3AlbumIE(ZingMp3BaseInfoExtractor): + _VALID_URL = r'https?://mp3\.zing\.vn/album/(?P<slug>[^/]+)/(?P<album_id>\w+)\.html' + _TESTS = [{ + 'url': 'http://mp3.zing.vn/album/Lau-Dai-Tinh-Ai-Bang-Kieu-Minh-Tuyet/ZWZBWDAF.html', + 'info_dict': { + '_type': 'playlist', + 'id': 'ZWZBWDAF', + 'title': 'Lâu Đài Tình Ái - Bằng Kiều ft. Minh Tuyết | Album 320 lossless', + }, + 'playlist_count': 10, + }] + IE_NAME = 'zingmp3:album' + IE_DESC = 'mp3.zing.vn albums' + + def _real_extract(self, url): + matched = re.match(self._VALID_URL, url) + slug = matched.group('slug') + album_id = matched.group('album_id') + + webpage = self._download_webpage( + 'http://mp3.zing.vn/album/%s/%s.html' % (slug, album_id), album_id) + player_xml_url = self._search_regex( + r'&xmlURL=(?P<xml_url>[^&]+)&', webpage, 'player xml url') + + return self._extract_player_xml( + player_xml_url, album_id, + playlist_title=self._og_search_title(webpage)) |