[youtube] Skip unsupported adaptive stream type (#18804)
[youtube-dl] / youtube_dl / extractor / spankbang.py
1 from __future__ import unicode_literals
2
3 import re
4
5 from .common import InfoExtractor
6 from ..utils import (
7     ExtractorError,
8     parse_duration,
9     parse_resolution,
10     str_to_int,
11 )
12
13
14 class SpankBangIE(InfoExtractor):
15     _VALID_URL = r'https?://(?:(?:www|m|[a-z]{2})\.)?spankbang\.com/(?P<id>[\da-z]+)/video'
16     _TESTS = [{
17         'url': 'http://spankbang.com/3vvn/video/fantasy+solo',
18         'md5': '1cc433e1d6aa14bc376535b8679302f7',
19         'info_dict': {
20             'id': '3vvn',
21             'ext': 'mp4',
22             'title': 'fantasy solo',
23             'description': 'dillion harper masturbates on a bed',
24             'thumbnail': r're:^https?://.*\.jpg$',
25             'uploader': 'silly2587',
26             'age_limit': 18,
27         }
28     }, {
29         # 480p only
30         'url': 'http://spankbang.com/1vt0/video/solvane+gangbang',
31         'only_matching': True,
32     }, {
33         # no uploader
34         'url': 'http://spankbang.com/lklg/video/sex+with+anyone+wedding+edition+2',
35         'only_matching': True,
36     }, {
37         # mobile page
38         'url': 'http://m.spankbang.com/1o2de/video/can+t+remember+her+name',
39         'only_matching': True,
40     }, {
41         # 4k
42         'url': 'https://spankbang.com/1vwqx/video/jade+kush+solo+4k',
43         'only_matching': True,
44     }]
45
46     def _real_extract(self, url):
47         video_id = self._match_id(url)
48         webpage = self._download_webpage(url, video_id, headers={
49             'Cookie': 'country=US'
50         })
51
52         if re.search(r'<[^>]+\bid=["\']video_removed', webpage):
53             raise ExtractorError(
54                 'Video %s is not available' % video_id, expected=True)
55
56         formats = []
57         for mobj in re.finditer(
58                 r'stream_url_(?P<id>[^\s=]+)\s*=\s*(["\'])(?P<url>(?:(?!\2).)+)\2',
59                 webpage):
60             format_id, format_url = mobj.group('id', 'url')
61             f = parse_resolution(format_id)
62             f.update({
63                 'url': format_url,
64                 'format_id': format_id,
65             })
66             formats.append(f)
67         self._sort_formats(formats)
68
69         title = self._html_search_regex(
70             r'(?s)<h1[^>]*>(.+?)</h1>', webpage, 'title')
71         description = self._search_regex(
72             r'<div[^>]+\bclass=["\']bottom[^>]+>\s*<p>[^<]*</p>\s*<p>([^<]+)',
73             webpage, 'description', fatal=False)
74         thumbnail = self._og_search_thumbnail(webpage)
75         uploader = self._search_regex(
76             r'class="user"[^>]*><img[^>]+>([^<]+)',
77             webpage, 'uploader', default=None)
78         duration = parse_duration(self._search_regex(
79             r'<div[^>]+\bclass=["\']right_side[^>]+>\s*<span>([^<]+)',
80             webpage, 'duration', fatal=False))
81         view_count = str_to_int(self._search_regex(
82             r'([\d,.]+)\s+plays', webpage, 'view count', fatal=False))
83
84         age_limit = self._rta_search(webpage)
85
86         return {
87             'id': video_id,
88             'title': title,
89             'description': description,
90             'thumbnail': thumbnail,
91             'uploader': uploader,
92             'duration': duration,
93             'view_count': view_count,
94             'formats': formats,
95             'age_limit': age_limit,
96         }