You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
8.2 KiB

10 years ago
  1. from __future__ import unicode_literals
  2. import re
  3. from .common import InfoExtractor
  4. from ..compat import compat_urlparse
  5. from ..utils import (
  6. parse_duration,
  7. parse_iso8601,
  8. str_to_int,
  9. )
  10. class FourTubeBaseIE(InfoExtractor):
  11. def _real_extract(self, url):
  12. mobj = re.match(self._VALID_URL, url)
  13. kind, video_id, display_id = mobj.group('kind', 'id', 'display_id')
  14. if kind == 'm' or not display_id:
  15. url = self._URL_TEMPLATE % video_id
  16. webpage = self._download_webpage(url, video_id)
  17. title = self._html_search_meta('name', webpage)
  18. timestamp = parse_iso8601(self._html_search_meta(
  19. 'uploadDate', webpage))
  20. thumbnail = self._html_search_meta('thumbnailUrl', webpage)
  21. uploader_id = self._html_search_regex(
  22. r'<a class="item-to-subscribe" href="[^"]+/(?:channel|user)s?/([^/"]+)" title="Go to [^"]+ page">',
  23. webpage, 'uploader id', fatal=False)
  24. uploader = self._html_search_regex(
  25. r'<a class="item-to-subscribe" href="[^"]+/(?:channel|user)s?/[^/"]+" title="Go to ([^"]+) page">',
  26. webpage, 'uploader', fatal=False)
  27. categories_html = self._search_regex(
  28. r'(?s)><i class="icon icon-tag"></i>\s*Categories / Tags\s*.*?<ul class="[^"]*?list[^"]*?">(.*?)</ul>',
  29. webpage, 'categories', fatal=False)
  30. categories = None
  31. if categories_html:
  32. categories = [
  33. c.strip() for c in re.findall(
  34. r'(?s)<li><a.*?>(.*?)</a>', categories_html)]
  35. view_count = str_to_int(self._search_regex(
  36. r'<meta[^>]+itemprop="interactionCount"[^>]+content="UserPlays:([0-9,]+)">',
  37. webpage, 'view count', default=None))
  38. like_count = str_to_int(self._search_regex(
  39. r'<meta[^>]+itemprop="interactionCount"[^>]+content="UserLikes:([0-9,]+)">',
  40. webpage, 'like count', default=None))
  41. duration = parse_duration(self._html_search_meta('duration', webpage))
  42. media_id = self._search_regex(
  43. r'<button[^>]+data-id=(["\'])(?P<id>\d+)\1[^>]+data-quality=', webpage,
  44. 'media id', default=None, group='id')
  45. sources = [
  46. quality
  47. for _, quality in re.findall(r'<button[^>]+data-quality=(["\'])(.+?)\1', webpage)]
  48. if not (media_id and sources):
  49. player_js = self._download_webpage(
  50. self._search_regex(
  51. r'<script[^>]id=(["\'])playerembed\1[^>]+src=(["\'])(?P<url>.+?)\2',
  52. webpage, 'player JS', group='url'),
  53. video_id, 'Downloading player JS')
  54. params_js = self._search_regex(
  55. r'\$\.ajax\(url,\ opts\);\s*\}\s*\}\)\(([0-9,\[\] ]+)\)',
  56. player_js, 'initialization parameters')
  57. params = self._parse_json('[%s]' % params_js, video_id)
  58. media_id = params[0]
  59. sources = ['%s' % p for p in params[2]]
  60. token_url = 'https://tkn.kodicdn.com/{0}/desktop/{1}'.format(
  61. media_id, '+'.join(sources))
  62. parsed_url = compat_urlparse.urlparse(url)
  63. tokens = self._download_json(token_url, video_id, data=b'', headers={
  64. 'Origin': '%s://%s' % (parsed_url.scheme, parsed_url.hostname),
  65. 'Referer': url,
  66. })
  67. formats = [{
  68. 'url': tokens[format]['token'],
  69. 'format_id': format + 'p',
  70. 'resolution': format + 'p',
  71. 'quality': int(format),
  72. } for format in sources]
  73. self._sort_formats(formats)
  74. return {
  75. 'id': video_id,
  76. 'title': title,
  77. 'formats': formats,
  78. 'categories': categories,
  79. 'thumbnail': thumbnail,
  80. 'uploader': uploader,
  81. 'uploader_id': uploader_id,
  82. 'timestamp': timestamp,
  83. 'like_count': like_count,
  84. 'view_count': view_count,
  85. 'duration': duration,
  86. 'age_limit': 18,
  87. }
  88. class FourTubeIE(FourTubeBaseIE):
  89. IE_NAME = '4tube'
  90. _VALID_URL = r'https?://(?:(?P<kind>www|m)\.)?4tube\.com/(?:videos|embed)/(?P<id>\d+)(?:/(?P<display_id>[^/?#&]+))?'
  91. _URL_TEMPLATE = 'https://www.4tube.com/videos/%s/video'
  92. _TESTS = [{
  93. 'url': 'http://www.4tube.com/videos/209733/hot-babe-holly-michaels-gets-her-ass-stuffed-by-black',
  94. 'md5': '6516c8ac63b03de06bc8eac14362db4f',
  95. 'info_dict': {
  96. 'id': '209733',
  97. 'ext': 'mp4',
  98. 'title': 'Hot Babe Holly Michaels gets her ass stuffed by black',
  99. 'uploader': 'WCP Club',
  100. 'uploader_id': 'wcp-club',
  101. 'upload_date': '20131031',
  102. 'timestamp': 1383263892,
  103. 'duration': 583,
  104. 'view_count': int,
  105. 'like_count': int,
  106. 'categories': list,
  107. 'age_limit': 18,
  108. },
  109. }, {
  110. 'url': 'http://www.4tube.com/embed/209733',
  111. 'only_matching': True,
  112. }, {
  113. 'url': 'http://m.4tube.com/videos/209733/hot-babe-holly-michaels-gets-her-ass-stuffed-by-black',
  114. 'only_matching': True,
  115. }]
  116. class FuxIE(FourTubeBaseIE):
  117. _VALID_URL = r'https?://(?:(?P<kind>www|m)\.)?fux\.com/(?:video|embed)/(?P<id>\d+)(?:/(?P<display_id>[^/?#&]+))?'
  118. _URL_TEMPLATE = 'https://www.fux.com/video/%s/video'
  119. _TESTS = [{
  120. 'url': 'https://www.fux.com/video/195359/awesome-fucking-kitchen-ends-cum-swallow',
  121. 'info_dict': {
  122. 'id': '195359',
  123. 'ext': 'mp4',
  124. 'title': 'Awesome fucking in the kitchen ends with cum swallow',
  125. 'uploader': 'alenci2342',
  126. 'uploader_id': 'alenci2342',
  127. 'upload_date': '20131230',
  128. 'timestamp': 1388361660,
  129. 'duration': 289,
  130. 'view_count': int,
  131. 'like_count': int,
  132. 'categories': list,
  133. 'age_limit': 18,
  134. },
  135. 'params': {
  136. 'skip_download': True,
  137. },
  138. }, {
  139. 'url': 'https://www.fux.com/embed/195359',
  140. 'only_matching': True,
  141. }, {
  142. 'url': 'https://www.fux.com/video/195359/awesome-fucking-kitchen-ends-cum-swallow',
  143. 'only_matching': True,
  144. }]
  145. class PornTubeIE(FourTubeBaseIE):
  146. _VALID_URL = r'https?://(?:(?P<kind>www|m)\.)?porntube\.com/(?:videos/(?P<display_id>[^/]+)_|embed/)(?P<id>\d+)'
  147. _URL_TEMPLATE = 'https://www.porntube.com/videos/video_%s'
  148. _TESTS = [{
  149. 'url': 'https://www.porntube.com/videos/teen-couple-doing-anal_7089759',
  150. 'info_dict': {
  151. 'id': '7089759',
  152. 'ext': 'mp4',
  153. 'title': 'Teen couple doing anal',
  154. 'uploader': 'Alexy',
  155. 'uploader_id': 'Alexy',
  156. 'upload_date': '20150606',
  157. 'timestamp': 1433595647,
  158. 'duration': 5052,
  159. 'view_count': int,
  160. 'like_count': int,
  161. 'categories': list,
  162. 'age_limit': 18,
  163. },
  164. 'params': {
  165. 'skip_download': True,
  166. },
  167. }, {
  168. 'url': 'https://www.porntube.com/embed/7089759',
  169. 'only_matching': True,
  170. }, {
  171. 'url': 'https://m.porntube.com/videos/teen-couple-doing-anal_7089759',
  172. 'only_matching': True,
  173. }]
  174. class PornerBrosIE(FourTubeBaseIE):
  175. _VALID_URL = r'https?://(?:(?P<kind>www|m)\.)?pornerbros\.com/(?:videos/(?P<display_id>[^/]+)_|embed/)(?P<id>\d+)'
  176. _URL_TEMPLATE = 'https://www.pornerbros.com/videos/video_%s'
  177. _TESTS = [{
  178. 'url': 'https://www.pornerbros.com/videos/skinny-brunette-takes-big-cock-down-her-anal-hole_181369',
  179. 'md5': '6516c8ac63b03de06bc8eac14362db4f',
  180. 'info_dict': {
  181. 'id': '181369',
  182. 'ext': 'mp4',
  183. 'title': 'Skinny brunette takes big cock down her anal hole',
  184. 'uploader': 'PornerBros HD',
  185. 'uploader_id': 'pornerbros-hd',
  186. 'upload_date': '20130130',
  187. 'timestamp': 1359527401,
  188. 'duration': 1224,
  189. 'view_count': int,
  190. 'categories': list,
  191. 'age_limit': 18,
  192. },
  193. 'params': {
  194. 'skip_download': True,
  195. },
  196. }, {
  197. 'url': 'https://www.pornerbros.com/embed/181369',
  198. 'only_matching': True,
  199. }, {
  200. 'url': 'https://m.pornerbros.com/videos/skinny-brunette-takes-big-cock-down-her-anal-hole_181369',
  201. 'only_matching': True,
  202. }]