diff options
| -rw-r--r-- | youtube_dl/extractor/generic.py | 183 | 
1 files changed, 183 insertions, 0 deletions
diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py index a9c064105..01e406750 100644 --- a/youtube_dl/extractor/generic.py +++ b/youtube_dl/extractor/generic.py @@ -28,6 +28,7 @@ from ..utils import (      mimetype2ext,      orderedSet,      parse_duration, +    parse_resolution,      sanitized_Request,      smuggle_url,      unescapeHTML, @@ -2227,6 +2228,97 @@ class GenericIE(InfoExtractor):              # Sibnet embed (https://help.sibnet.ru/?sibnet_video_embed)              'url': 'https://phpbb3.x-tk.ru/bbcode-video-sibnet-t24.html',              'only_matching': True, +        }, { +            # KVS Player +            'url': 'https://www.kvs-demo.com/videos/105/kelis-4th-of-july/', +            'info_dict': { +                'id': '105', +                'display_id': 'kelis-4th-of-july', +                'ext': 'mp4', +                'title': 'Kelis - 4th Of July', +                'thumbnail': r're:https://(?:www\.)?kvs-demo.com/contents/videos_screenshots/0/105/preview.jpg', +            }, +        }, { +            # KVS Player +            'url': 'https://www.kvs-demo.com/embed/105/', +            'info_dict': { +                'id': '105', +                'display_id': 'kelis-4th-of-july', +                'ext': 'mp4', +                'title': 'Kelis - 4th Of July / Embed Player', +                'thumbnail': r're:https://(?:www\.)?kvs-demo.com/contents/videos_screenshots/0/105/preview.jpg', +            }, +            'params': { +                'skip_download': True, +            }, +        }, { +            # KVS Player +            'url': 'https://thisvid.com/videos/fruit-is-healthy/', +            'md5': 'f83e52f409b9139a7efee58ef926a72e', +            'info_dict': { +                'id': '7079579', +                'display_id': 'fruit-is-healthy', +                'ext': 'mp4', +                'title': 'Fruit is healthy - ThisVid.com', +                'thumbnail': 'https://media.thisvid.com/contents/videos_screenshots/7079000/7079579/preview.jpg', +            } +        }, { +            # KVS Player +            'url': 'https://thisvid.com/embed/7079579/', +            'info_dict': { +                'id': '7079579', +                'display_id': 'fruit-is-healthy', +                'ext': 'mp4', +                'title': 'Fruit is healthy - ThisVid.com', +                'thumbnail': 'https://media.thisvid.com/contents/videos_screenshots/7079000/7079579/preview.jpg', +            }, +            'params': { +                'skip_download': True, +            }, +        }, { +            # KVS Player +            'url': 'https://youix.com/video/leningrad-zoj/', +            'md5': '94f96ba95706dc3880812b27b7d8a2b8', +            'info_dict': { +                'id': '18485', +                'display_id': 'leningrad-zoj', +                'ext': 'mp4', +                'title': 'Клип: Ленинград - ЗОЖ скачать, смотреть онлайн | Youix.com', +                'thumbnail': r're:https://youix.com/contents/videos_screenshots/18000/18485/preview(?:_480x320_youix_com.mp4)?\.jpg', +            }, +        }, { +            # KVS Player +            'url': 'https://youix.com/embed/18485', +            'md5': '94f96ba95706dc3880812b27b7d8a2b8', +            'info_dict': { +                'id': '18485', +                'display_id': 'leningrad-zoj', +                'ext': 'mp4', +                'title': 'Ленинград - ЗОЖ', +                'thumbnail': r're:https://youix.com/contents/videos_screenshots/18000/18485/preview(?:_480x320_youix_com.mp4)?\.jpg', +            }, +        }, { +            # KVS Player +            'url': 'https://bogmedia.org/videos/21217/40-nochey-40-nights-2016/', +            'md5': '94166bdb26b4cb1fb9214319a629fc51', +            'info_dict': { +                'id': '21217', +                'display_id': '40-nochey-2016', +                'ext': 'mp4', +                'title': '40 ночей (2016) - BogMedia.org', +                'thumbnail': 'https://bogmedia.org/contents/videos_screenshots/21000/21217/preview_480p.mp4.jpg', +            }, +        }, { +            # KVS Player (for sites that serve kt_player.js via non-https urls) +            'url': 'http://www.camhub.world/embed/389508', +            'md5': 'fbe89af4cfb59c8fd9f34a202bb03e32', +            'info_dict': { +                'id': '389508', +                'display_id': 'syren-de-mer-onlyfans-05-07-2020have-a-happy-safe-holiday5f014e68a220979bdb8cd-source', +                'ext': 'mp4', +                'title': 'Syren De Mer  onlyfans_05-07-2020Have_a_happy_safe_holiday5f014e68a220979bdb8cd_source / Embed плеер', +                'thumbnail': r're:https?://www\.camhub\.world/contents/videos_screenshots/389000/389508/preview\.mp4\.jpg', +            },          },      ] @@ -2332,6 +2424,87 @@ class GenericIE(InfoExtractor):              'title': title,          } +    def _extract_kvs(self, url, webpage, video_id): + +        def getlicensetoken(license): +            modlicense = license.replace('$', '').replace('0', '1') +            center = int(len(modlicense) / 2) +            fronthalf = int(modlicense[:center + 1]) +            backhalf = int(modlicense[center:]) + +            modlicense = compat_str(4 * abs(fronthalf - backhalf)) + +            def parts(): +                for o in range(0, center + 1): +                    for i in range(1, 5): +                        yield compat_str((int(license[o + i]) + int(modlicense[o])) % 10) + +            return ''.join(parts()) + +        def getrealurl(video_url, license_code): +            if not video_url.startswith('function/0/'): +                return video_url  # not obfuscated + +            url_path, _, url_query = video_url.partition('?') +            urlparts = url_path.split('/')[2:] +            license = getlicensetoken(license_code) +            newmagic = urlparts[5][:32] + +            def spells(x, o): +                l = (o + sum(int(n) for n in license[o:])) % 32 +                for i in range(0, len(x)): +                    yield {l: x[o], o: x[l]}.get(i, x[i]) + +            for o in range(len(newmagic) - 1, -1, -1): +                newmagic = ''.join(spells(newmagic, o)) + +            urlparts[5] = newmagic + urlparts[5][32:] +            return '/'.join(urlparts) + '?' + url_query + +        flashvars = self._search_regex( +            r'(?s)<script\b[^>]*>.*?var\s+flashvars\s*=\s*(\{.+?\});.*?</script>', +            webpage, 'flashvars') +        flashvars = self._parse_json(flashvars, video_id, transform_source=js_to_json) + +        # extract the part after the last / as the display_id from the +        # canonical URL. +        display_id = self._search_regex( +            r'(?:<link href="https?://[^"]+/(.+?)/?" rel="canonical"\s*/?>' +            r'|<link rel="canonical" href="https?://[^"]+/(.+?)/?"\s*/?>)', +            webpage, 'display_id', fatal=False +        ) +        title = self._html_search_regex(r'<(?:h1|title)>(?:Video: )?(.+?)</(?:h1|title)>', webpage, 'title') + +        thumbnail = flashvars['preview_url'] +        if thumbnail.startswith('//'): +            protocol, _, _ = url.partition('/') +            thumbnail = protocol + thumbnail + +        url_keys = list(filter(re.compile(r'^video_(?:url|alt_url\d*)$').match, flashvars.keys())) +        formats = [] +        for key in url_keys: +            if '/get_file/' not in flashvars[key]: +                continue +            format_id = flashvars.get(key + '_text', key) +            formats.append(merge_dicts( +                parse_resolution(format_id) or parse_resolution(flashvars[key]), { +                    'url': getrealurl(flashvars[key], flashvars['license_code']), +                    'format_id': format_id, +                    'ext': 'mp4', +                })) +            if not formats[-1].get('height'): +                formats[-1]['quality'] = 1 + +        self._sort_formats(formats) + +        return { +            'id': flashvars['video_id'], +            'display_id': display_id, +            'title': title, +            'thumbnail': thumbnail, +            'formats': formats, +        } +      def _real_extract(self, url):          if url.startswith('//'):              return self.url_result(self.http_scheme() + url) @@ -3389,6 +3562,16 @@ class GenericIE(InfoExtractor):                  info_dict['formats'] = formats                  return info_dict +        # Look for generic KVS player (before ld+json for tests) +        found = re.search( +            r'<script\b[^>]+?\bsrc\s*=\s*(["\'])https?://(?:\S+?/)+kt_player\.js\?v=(?P<ver>(?P<maj_ver>\d+)(\.\d+)+)\1[^>]*>', +            webpage) +        if found: +            self.report_extraction('KVS Player') +            if found.group('maj_ver') not in ('4', '5', '6'): +                self.report_warning('Untested major version (%s) in player engine - download may fail.' % (found.group('ver'), )) +            return self._extract_kvs(url, webpage, video_id) +          # Looking for http://schema.org/VideoObject          json_ld = self._search_json_ld(              webpage, video_id, default={}, expected_type='VideoObject')  | 
