]>
Commit | Line | Data |
---|---|---|
43df5a7e JMF |
1 | from __future__ import unicode_literals |
2 | ||
5b11143d | 3 | import re |
4 | ||
5 | from .common import InfoExtractor | |
8652770b S |
6 | from ..aes import aes_decrypt_text |
7 | from ..compat import ( | |
8 | compat_str, | |
9 | compat_urllib_parse_unquote, | |
10 | ) | |
db9bd526 | 11 | from ..utils import ( |
8652770b S |
12 | determine_ext, |
13 | ExtractorError, | |
14 | int_or_none, | |
15 | str_to_int, | |
16 | strip_or_none, | |
db9bd526 | 17 | ) |
5b11143d | 18 | |
43df5a7e | 19 | |
5b11143d | 20 | class KeezMoviesIE(InfoExtractor): |
8652770b S |
21 | _VALID_URL = r'https?://(?:www\.)?keezmovies\.com/video/(?:(?P<display_id>[^/]+)-)?(?P<id>\d+)' |
22 | _TESTS = [{ | |
1792bc3a PV |
23 | 'url': 'https://www.keezmovies.com/video/arab-wife-want-it-so-bad-i-see-she-thirsty-and-has-tiny-money-18070681', |
24 | 'md5': '2ac69cdb882055f71d82db4311732a1a', | |
43df5a7e | 25 | 'info_dict': { |
1792bc3a PV |
26 | 'id': '18070681', |
27 | 'display_id': 'arab-wife-want-it-so-bad-i-see-she-thirsty-and-has-tiny-money', | |
9f281cac | 28 | 'ext': 'mp4', |
1792bc3a PV |
29 | 'title': 'Arab wife want it so bad I see she thirsty and has tiny money.', |
30 | 'thumbnail': None, | |
8652770b S |
31 | 'view_count': int, |
32 | 'age_limit': 18, | |
5b11143d | 33 | } |
8652770b | 34 | }, { |
1792bc3a | 35 | 'url': 'http://www.keezmovies.com/video/18070681', |
8652770b S |
36 | 'only_matching': True, |
37 | }] | |
5b11143d | 38 | |
1792bc3a | 39 | def _extract_info(self, url, fatal=True): |
8652770b S |
40 | mobj = re.match(self._VALID_URL, url) |
41 | video_id = mobj.group('id') | |
e15ad9ef S |
42 | display_id = (mobj.group('display_id') |
43 | if 'display_id' in mobj.groupdict() | |
44 | else None) or mobj.group('id') | |
5b11143d | 45 | |
8652770b S |
46 | webpage = self._download_webpage( |
47 | url, display_id, headers={'Cookie': 'age_verified=1'}) | |
5b11143d | 48 | |
8652770b S |
49 | formats = [] |
50 | format_urls = set() | |
5b11143d | 51 | |
8652770b S |
52 | title = None |
53 | thumbnail = None | |
54 | duration = None | |
55 | encrypted = False | |
db9bd526 | 56 | |
8652770b | 57 | def extract_format(format_url, height=None): |
1792bc3a | 58 | if not isinstance(format_url, compat_str) or not format_url.startswith(('http', '//')): |
8652770b S |
59 | return |
60 | if format_url in format_urls: | |
61 | return | |
62 | format_urls.add(format_url) | |
63 | tbr = int_or_none(self._search_regex( | |
64 | r'[/_](\d+)[kK][/_]', format_url, 'tbr', default=None)) | |
65 | if not height: | |
66 | height = int_or_none(self._search_regex( | |
67 | r'[/_](\d+)[pP][/_]', format_url, 'height', default=None)) | |
68 | if encrypted: | |
69 | format_url = aes_decrypt_text( | |
70 | video_url, title, 32).decode('utf-8') | |
71 | formats.append({ | |
72 | 'url': format_url, | |
73 | 'format_id': '%dp' % height if height else None, | |
74 | 'height': height, | |
75 | 'tbr': tbr, | |
76 | }) | |
77 | ||
78 | flashvars = self._parse_json( | |
79 | self._search_regex( | |
80 | r'flashvars\s*=\s*({.+?});', webpage, | |
81 | 'flashvars', default='{}'), | |
82 | display_id, fatal=False) | |
83 | ||
84 | if flashvars: | |
85 | title = flashvars.get('video_title') | |
86 | thumbnail = flashvars.get('image_url') | |
87 | duration = int_or_none(flashvars.get('video_duration')) | |
88 | encrypted = flashvars.get('encrypted') is True | |
89 | for key, value in flashvars.items(): | |
90 | mobj = re.search(r'quality_(\d+)[pP]', key) | |
91 | if mobj: | |
92 | extract_format(value, int(mobj.group(1))) | |
93 | video_url = flashvars.get('video_url') | |
94 | if video_url and determine_ext(video_url, None): | |
95 | extract_format(video_url) | |
96 | ||
97 | video_url = self._html_search_regex( | |
98 | r'flashvars\.video_url\s*=\s*(["\'])(?P<url>http.+?)\1', | |
99 | webpage, 'video url', default=None, group='url') | |
100 | if video_url: | |
101 | extract_format(compat_urllib_parse_unquote(video_url)) | |
102 | ||
103 | if not formats: | |
104 | if 'title="This video is no longer available"' in webpage: | |
105 | raise ExtractorError( | |
106 | 'Video %s is no longer available' % video_id, expected=True) | |
107 | ||
1792bc3a PV |
108 | try: |
109 | self._sort_formats(formats) | |
110 | except ExtractorError: | |
111 | if fatal: | |
112 | raise | |
8652770b S |
113 | |
114 | if not title: | |
115 | title = self._html_search_regex( | |
116 | r'<h1[^>]*>([^<]+)', webpage, 'title') | |
117 | ||
118 | return webpage, { | |
5b11143d | 119 | 'id': video_id, |
8652770b S |
120 | 'display_id': display_id, |
121 | 'title': strip_or_none(title), | |
122 | 'thumbnail': thumbnail, | |
123 | 'duration': duration, | |
124 | 'age_limit': 18, | |
db9bd526 | 125 | 'formats': formats, |
5b11143d | 126 | } |
8652770b S |
127 | |
128 | def _real_extract(self, url): | |
1792bc3a PV |
129 | webpage, info = self._extract_info(url, fatal=False) |
130 | if not info['formats']: | |
131 | return self.url_result(url, 'Generic') | |
8652770b S |
132 | info['view_count'] = str_to_int(self._search_regex( |
133 | r'<b>([\d,.]+)</b> Views?', webpage, 'view count', fatal=False)) | |
134 | return info |