]>
Commit | Line | Data |
---|---|---|
1461d7be | 1 | # coding: utf-8 |
2 | from __future__ import unicode_literals | |
3 | ||
4 | import functools | |
5 | import re | |
6 | ||
7 | from .common import InfoExtractor | |
8 | from ..utils import ( | |
9 | parse_count, | |
10 | unified_strdate, | |
11 | js_to_json, | |
12 | OnDemandPagedList, | |
13 | ) | |
14 | ||
15 | ||
16 | class TokentubeIE(InfoExtractor): | |
17 | _VALID_URL = r'https?://(?:www\.)?tokentube\.net/(?:view\?[vl]=|[vl]/)(?P<id>\d+)' | |
18 | _TESTS = [{ | |
19 | 'url': 'https://tokentube.net/l/3236632011/Praise-A-Thon-Pastori-Chrisin-ja-Pastori-Bennyn-kanssa-27-8-2021', | |
20 | 'info_dict': { | |
21 | 'id': '3236632011', | |
22 | 'ext': 'mp4', | |
23 | 'title': 'Praise-A-Thon Pastori Chrisin ja Pastori Bennyn kanssa 27.8.2021', | |
24 | 'description': '', | |
25 | 'uploader': 'Pastori Chris - Rapsodia.fi', | |
26 | 'upload_date': '20210827', | |
27 | }, | |
28 | 'params': { | |
29 | 'skip_download': True, | |
30 | }, | |
31 | }, { | |
32 | 'url': 'https://tokentube.net/v/3950239124/Linux-Ubuntu-Studio-perus-k%C3%A4ytt%C3%B6', | |
33 | 'md5': '0e1f00421f501f5eada9890d38fcfb56', | |
34 | 'info_dict': { | |
35 | 'id': '3950239124', | |
36 | 'ext': 'mp4', | |
37 | 'title': 'Linux Ubuntu Studio perus käyttö', | |
38 | 'description': 'md5:854ff1dc732ff708976de2880ea32050', | |
39 | 'uploader': 'jyrilehtonen', | |
40 | 'upload_date': '20210825', | |
41 | }, | |
42 | }, { | |
43 | 'url': 'https://tokentube.net/view?v=3582463289', | |
44 | 'info_dict': { | |
45 | 'id': '3582463289', | |
46 | 'ext': 'mp4', | |
47 | 'title': 'Police for Freedom - toiminta aloitetaan Suomessa ❤️??', | |
48 | 'description': 'md5:cd92e620d7f5fa162e8410d0fc9a08be', | |
49 | 'uploader': 'Voitontie', | |
50 | 'upload_date': '20210428', | |
51 | } | |
52 | }] | |
53 | ||
54 | def _real_extract(self, url): | |
55 | video_id = self._match_id(url) | |
56 | webpage = self._download_webpage(url, video_id) | |
57 | ||
58 | title = self._html_search_regex(r'<h1\s*class=["\']title-text["\']>(.+?)</h1>', webpage, 'title') | |
59 | ||
60 | data_json = self._html_search_regex(r'({["\']html5["\'].+?}}}+)', webpage, 'data json') | |
61 | data_json = self._parse_json(js_to_json(data_json), video_id, fatal=False) | |
62 | ||
63 | sources = data_json.get('sources') or self._parse_json( | |
64 | self._html_search_regex(r'updateSrc\(([^\)]+)\)', webpage, 'sources'), | |
65 | video_id, transform_source=js_to_json) | |
66 | ||
67 | formats = [{ | |
68 | 'url': format.get('src'), | |
69 | 'format_id': format.get('label'), | |
70 | 'height': format.get('res'), | |
71 | } for format in sources] | |
72 | ||
73 | view_count = parse_count(self._html_search_regex( | |
74 | r'<p\s*class=["\']views_counter["\']>\s*([\d\.,]+)\s*<span>views?</span></p>', | |
75 | webpage, 'view_count', fatal=False)) | |
76 | ||
77 | like_count = parse_count(self._html_search_regex( | |
78 | r'<div\s*class="sh_button\s*likes_count">\s*(\d+)\s*</div>', | |
79 | webpage, 'like count', fatal=False)) | |
80 | ||
81 | dislike_count = parse_count(self._html_search_regex( | |
82 | r'<div\s*class="sh_button\s*dislikes_count">\s*(\d+)\s*</div>', | |
83 | webpage, 'dislike count', fatal=False)) | |
84 | ||
85 | upload_date = unified_strdate(self._html_search_regex( | |
86 | r'<span\s*class="p-date">Published\s*on\s+([^<]+)', | |
87 | webpage, 'upload date', fatal=False)) | |
88 | ||
89 | uploader = self._html_search_regex( | |
90 | r'<a\s*class="place-left"[^>]+>(.+?)</a>', | |
91 | webpage, 'uploader', fatal=False) | |
92 | ||
93 | description = self._html_search_meta('description', webpage) | |
94 | ||
95 | self._sort_formats(formats) | |
96 | ||
97 | return { | |
98 | 'id': video_id, | |
99 | 'formats': formats, | |
100 | 'title': title, | |
101 | 'view_count': view_count, | |
102 | 'like_count': like_count, | |
103 | 'dislike_count': dislike_count, | |
104 | 'upload_date': upload_date, | |
105 | 'description': description, | |
106 | 'uploader': uploader, | |
107 | } | |
108 | ||
109 | ||
110 | class TokentubeChannelIE(InfoExtractor): | |
111 | _PAGE_SIZE = 20 | |
112 | IE_NAME = 'Tokentube:channel' | |
113 | _VALID_URL = r'https?://(?:www\.)?tokentube\.net/channel/(?P<id>\d+)/[^/]+(?:/videos)?' | |
114 | _TESTS = [{ | |
115 | 'url': 'https://tokentube.net/channel/3697658904/TokenTube', | |
116 | 'info_dict': { | |
117 | 'id': '3697658904', | |
118 | }, | |
119 | 'playlist_mincount': 7, | |
120 | }, { | |
121 | 'url': 'https://tokentube.net/channel/3353234420/Linux/videos', | |
122 | 'info_dict': { | |
123 | 'id': '3353234420', | |
124 | }, | |
125 | 'playlist_mincount': 20, | |
126 | }, { | |
127 | 'url': 'https://tokentube.net/channel/3475834195/Voitontie', | |
128 | 'info_dict': { | |
129 | 'id': '3475834195', | |
130 | }, | |
131 | 'playlist_mincount': 150, | |
132 | }] | |
133 | ||
134 | def _fetch_page(self, channel_id, page): | |
135 | page += 1 | |
136 | videos_info = self._download_webpage( | |
137 | f'https://tokentube.net/videos?p=0&m=1&sort=recent&u={channel_id}&page={page}', | |
138 | channel_id, headers={'X-Requested-With': 'XMLHttpRequest'}, | |
139 | note=f'Downloading page {page}', fatal=False) | |
140 | if '</i> Sorry, no results were found.' not in videos_info: | |
141 | for path, media_id in re.findall( | |
142 | r'<a[^>]+\bhref=["\']([^"\']+/[lv]/(\d+)/\S+)["\'][^>]+>', | |
143 | videos_info): | |
144 | yield self.url_result(path, ie=TokentubeIE.ie_key(), video_id=media_id) | |
145 | ||
146 | def _real_extract(self, url): | |
147 | channel_id = self._match_id(url) | |
148 | ||
149 | entries = OnDemandPagedList(functools.partial( | |
150 | self._fetch_page, channel_id), self._PAGE_SIZE) | |
151 | ||
152 | return self.playlist_result(entries, channel_id) |