diff options
| author | Yen Chi Hsuan <yan12125@gmail.com> | 2016-07-06 20:09:05 +0800 | 
|---|---|---|
| committer | Yen Chi Hsuan <yan12125@gmail.com> | 2016-07-06 20:09:05 +0800 | 
| commit | f8752b86ac66d462caeb44b2ec18eda94973466d (patch) | |
| tree | 6cdc5c22d3fee54072c425eca34a06052f707194 | |
| parent | 84c237fb8a2afa06fd3c36f7da9517682e63480e (diff) | |
[Onet,ClipRs] Add new extractor for onet.tv and use it for clip.rs
Closes #9950
| -rw-r--r-- | youtube_dl/extractor/cliprs.py | 73 | ||||
| -rw-r--r-- | youtube_dl/extractor/extractors.py | 6 | ||||
| -rw-r--r-- | youtube_dl/extractor/onet.py | 171 | 
3 files changed, 184 insertions, 66 deletions
diff --git a/youtube_dl/extractor/cliprs.py b/youtube_dl/extractor/cliprs.py index 4f9320ea5..d55b26d59 100644 --- a/youtube_dl/extractor/cliprs.py +++ b/youtube_dl/extractor/cliprs.py @@ -1,16 +1,10 @@  # coding: utf-8  from __future__ import unicode_literals -from .common import InfoExtractor -from ..utils import ( -    ExtractorError, -    float_or_none, -    int_or_none, -    parse_iso8601, -) +from .onet import OnetBaseIE -class ClipRsIE(InfoExtractor): +class ClipRsIE(OnetBaseIE):      _VALID_URL = r'https?://(?:www\.)?clip\.rs/(?P<id>[^/]+)/\d+'      _TEST = {          'url': 'http://www.clip.rs/premijera-frajle-predstavljaju-novi-spot-za-pesmu-moli-me-moli/3732', @@ -27,64 +21,13 @@ class ClipRsIE(InfoExtractor):      }      def _real_extract(self, url): -        video_id = self._match_id(url) +        display_id = self._match_id(url) -        webpage = self._download_webpage(url, video_id) +        webpage = self._download_webpage(url, display_id) -        video_id = self._search_regex( -            r'id=(["\'])mvp:(?P<id>.+?)\1', webpage, 'mvp id', group='id') +        mvp_id = self._search_mvp_id(webpage) -        response = self._download_json( -            'http://qi.ckm.onetapi.pl/', video_id, -            query={ -                'body[id]': video_id, -                'body[jsonrpc]': '2.0', -                'body[method]': 'get_asset_detail', -                'body[params][ID_Publikacji]': video_id, -                'body[params][Service]': 'www.onet.pl', -                'content-type': 'application/jsonp', -                'x-onet-app': 'player.front.onetapi.pl', -            }) +        info_dict = self._extract_from_id(mvp_id, webpage) +        info_dict['display_id'] = display_id -        error = response.get('error') -        if error: -            raise ExtractorError( -                '%s said: %s' % (self.IE_NAME, error['message']), expected=True) - -        video = response['result'].get('0') - -        formats = [] -        for _, formats_dict in video['formats'].items(): -            if not isinstance(formats_dict, dict): -                continue -            for format_id, format_list in formats_dict.items(): -                if not isinstance(format_list, list): -                    continue -                for f in format_list: -                    if not f.get('url'): -                        continue -                    formats.append({ -                        'url': f['url'], -                        'format_id': format_id, -                        'height': int_or_none(f.get('vertical_resolution')), -                        'width': int_or_none(f.get('horizontal_resolution')), -                        'abr': float_or_none(f.get('audio_bitrate')), -                        'vbr': float_or_none(f.get('video_bitrate')), -                    }) -        self._sort_formats(formats) - -        meta = video.get('meta', {}) - -        title = self._og_search_title(webpage, default=None) or meta['title'] -        description = self._og_search_description(webpage, default=None) or meta.get('description') -        duration = meta.get('length') or meta.get('lenght') -        timestamp = parse_iso8601(meta.get('addDate'), ' ') - -        return { -            'id': video_id, -            'title': title, -            'description': description, -            'duration': duration, -            'timestamp': timestamp, -            'formats': formats, -        } +        return info_dict diff --git a/youtube_dl/extractor/extractors.py b/youtube_dl/extractor/extractors.py index d21d7870a..e52faa078 100644 --- a/youtube_dl/extractor/extractors.py +++ b/youtube_dl/extractor/extractors.py @@ -139,9 +139,9 @@ from .chirbit import (      ChirbitProfileIE,  )  from .cinchcast import CinchcastIE -from .cliprs import ClipRsIE  from .clipfish import ClipfishIE  from .cliphunter import CliphunterIE +from .cliprs import ClipRsIE  from .clipsyndicate import ClipsyndicateIE  from .closertotruth import CloserToTruthIE  from .cloudy import CloudyIE @@ -581,6 +581,10 @@ from .nytimes import (  from .nuvid import NuvidIE  from .odnoklassniki import OdnoklassnikiIE  from .oktoberfesttv import OktoberfestTVIE +from .onet import ( +    OnetIE, +    OnetChannelIE, +)  from .onionstudios import OnionStudiosIE  from .ooyala import (      OoyalaIE, diff --git a/youtube_dl/extractor/onet.py b/youtube_dl/extractor/onet.py new file mode 100644 index 000000000..1e0672de8 --- /dev/null +++ b/youtube_dl/extractor/onet.py @@ -0,0 +1,171 @@ +# coding: utf-8 +from __future__ import unicode_literals + +import re + +from .common import InfoExtractor +from ..utils import ( +    determine_ext, +    ExtractorError, +    float_or_none, +    get_element_by_class, +    int_or_none, +    js_to_json, +    parse_iso8601, +    remove_start, +    strip_or_none, +    url_basename, +) + + +class OnetBaseIE(InfoExtractor): +    def _search_mvp_id(self, webpage): +        return self._search_regex( +            r'id=(["\'])mvp:(?P<id>.+?)\1', webpage, 'mvp id', group='id') + +    def _extract_from_id(self, video_id, webpage): +        response = self._download_json( +            'http://qi.ckm.onetapi.pl/', video_id, +            query={ +                'body[id]': video_id, +                'body[jsonrpc]': '2.0', +                'body[method]': 'get_asset_detail', +                'body[params][ID_Publikacji]': video_id, +                'body[params][Service]': 'www.onet.pl', +                'content-type': 'application/jsonp', +                'x-onet-app': 'player.front.onetapi.pl', +            }) + +        error = response.get('error') +        if error: +            raise ExtractorError( +                '%s said: %s' % (self.IE_NAME, error['message']), expected=True) + +        video = response['result'].get('0') + +        formats = [] +        for _, formats_dict in video['formats'].items(): +            if not isinstance(formats_dict, dict): +                continue +            for format_id, format_list in formats_dict.items(): +                if not isinstance(format_list, list): +                    continue +                for f in format_list: +                    video_url = f.get('url') +                    if not video_url: +                        continue +                    ext = determine_ext(video_url) +                    if format_id == 'ism': +                        # TODO: Support Microsoft Smooth Streaming +                        continue +                    elif ext == 'mpd': +                        # TODO: Current DASH formats are broken - $Time$ pattern in +                        # <SegmentTemplate> not implemented yet +                        # formats.extend(self._extract_mpd_formats( +                        #    video_url, video_id, mpd_id='dash', fatal=False)) +                        continue +                    else: +                        formats.append({ +                            'url': video_url, +                            'format_id': format_id, +                            'height': int_or_none(f.get('vertical_resolution')), +                            'width': int_or_none(f.get('horizontal_resolution')), +                            'abr': float_or_none(f.get('audio_bitrate')), +                            'vbr': float_or_none(f.get('video_bitrate')), +                        }) +        self._sort_formats(formats) + +        meta = video.get('meta', {}) + +        title = self._og_search_title(webpage, default=None) or meta['title'] +        description = self._og_search_description(webpage, default=None) or meta.get('description') +        duration = meta.get('length') or meta.get('lenght') +        timestamp = parse_iso8601(meta.get('addDate'), ' ') + +        return { +            'id': video_id, +            'title': title, +            'description': description, +            'duration': duration, +            'timestamp': timestamp, +            'formats': formats, +        } + + +class OnetIE(OnetBaseIE): +    _VALID_URL = 'https?://(?:www\.)?onet\.tv/[a-z]/[a-z]+/(?P<display_id>[0-9a-z-]+)/(?P<id>[0-9a-z]+)' +    IE_NAME = 'onet.tv' + +    _TEST = { +        'url': 'http://onet.tv/k/openerfestival/open-er-festival-2016-najdziwniejsze-wymagania-gwiazd/qbpyqc', +        'info_dict': { +            'id': 'qbpyqc', +            'display_id': 'open-er-festival-2016-najdziwniejsze-wymagania-gwiazd', +            'ext': 'mp4', +            'title': 'Open\'er Festival 2016: najdziwniejsze wymagania gwiazd', +            'description': 'Trzy samochody, których nigdy nie użyto, prywatne spa, hotel dekorowany czarnym suknem czy nielegalne używki. Organizatorzy koncertów i festiwali muszą stawać przed nie lada wyzwaniem zapraszając gwia...', +            'upload_date': '20160705', +            'timestamp': 1467721580, +        }, +    } + +    def _real_extract(self, url): +        mobj = re.match(self._VALID_URL, url) +        display_id, video_id = mobj.group('display_id', 'id') + +        webpage = self._download_webpage(url, display_id) + +        mvp_id = self._search_mvp_id(webpage) + +        info_dict = self._extract_from_id(mvp_id, webpage) +        info_dict.update({ +            'id': video_id, +            'display_id': display_id, +        }) + +        return info_dict + + +class OnetChannelIE(OnetBaseIE): +    _VALID_URL = r'https?://(?:www\.)?onet\.tv/[a-z]/(?P<id>[a-z]+)(?:[?#]|$)' +    IE_NAME = 'onet.tv:channel' + +    _TEST = { +        'url': 'http://onet.tv/k/openerfestival', +        'info_dict': { +            'id': 'openerfestival', +            'title': 'Open\'er Festival Live', +            'description': 'Dziękujemy, że oglądaliście transmisje. Zobaczcie nasze relacje i wywiady z artystami.', +        }, +        'playlist_mincount': 46, +    } + +    def _real_extract(self, url): +        channel_id = self._match_id(url) + +        webpage = self._download_webpage(url, channel_id) + +        current_clip_info = self._parse_json(self._search_regex( +            r'var\s+currentClip\s*=\s*({[^}]+})', webpage, 'video info'), channel_id, +            transform_source=lambda s: js_to_json(re.sub(r'\'\s*\+\s*\'', '', s))) +        video_id = remove_start(current_clip_info['ckmId'], 'mvp:') +        video_name = url_basename(current_clip_info['url']) + +        if self._downloader.params.get('noplaylist'): +            self.to_screen( +                'Downloading just video %s because of --no-playlist' % video_name) +            return self._extract_from_id(video_id, webpage) + +        self.to_screen( +            'Downloading channel %s - add --no-playlist to just download video %s' % ( +                channel_id, video_name)) +        matches = re.findall( +            r'<a[^>]+href=[\'"](https?://(?:www\.)?onet\.tv/[a-z]/[a-z]+/[0-9a-z-]+/[0-9a-z]+)', +            webpage) +        entries = [ +            self.url_result(video_link, OnetIE.ie_key()) +            for video_link in matches] + +        channel_title = strip_or_none(get_element_by_class('o_channelName', webpage)) +        channel_description = strip_or_none(get_element_by_class('o_channelDesc', webpage)) +        return self.playlist_result(entries, channel_id, channel_title, channel_description)  | 
