|
|
@ -2,12 +2,14 @@ |
|
|
|
from __future__ import unicode_literals |
|
|
|
|
|
|
|
import base64 |
|
|
|
import functools |
|
|
|
import json |
|
|
|
import re |
|
|
|
import itertools |
|
|
|
|
|
|
|
from .common import InfoExtractor |
|
|
|
from ..compat import ( |
|
|
|
compat_kwargs, |
|
|
|
compat_HTTPError, |
|
|
|
compat_str, |
|
|
|
compat_urlparse, |
|
|
@ -19,6 +21,7 @@ from ..utils import ( |
|
|
|
int_or_none, |
|
|
|
merge_dicts, |
|
|
|
NO_DEFAULT, |
|
|
|
OnDemandPagedList, |
|
|
|
parse_filesize, |
|
|
|
qualities, |
|
|
|
RegexNotFoundError, |
|
|
@ -98,6 +101,13 @@ class VimeoBaseInfoExtractor(InfoExtractor): |
|
|
|
webpage, 'vuid', group='vuid') |
|
|
|
return xsrft, vuid |
|
|
|
|
|
|
|
def _extract_vimeo_config(self, webpage, video_id, *args, **kwargs): |
|
|
|
vimeo_config = self._search_regex( |
|
|
|
r'vimeo\.config\s*=\s*(?:({.+?})|_extend\([^,]+,\s+({.+?})\));', |
|
|
|
webpage, 'vimeo config', *args, **compat_kwargs(kwargs)) |
|
|
|
if vimeo_config: |
|
|
|
return self._parse_json(vimeo_config, video_id) |
|
|
|
|
|
|
|
def _set_vimeo_cookie(self, name, value): |
|
|
|
self._set_cookie('vimeo.com', name, value) |
|
|
|
|
|
|
@ -253,7 +263,7 @@ class VimeoIE(VimeoBaseInfoExtractor): |
|
|
|
\. |
|
|
|
)? |
|
|
|
vimeo(?P<pro>pro)?\.com/ |
|
|
|
(?!(?:channels|album)/[^/?#]+/?(?:$|[?#])|[^/]+/review/|ondemand/) |
|
|
|
(?!(?:channels|album|showcase)/[^/?#]+/?(?:$|[?#])|[^/]+/review/|ondemand/) |
|
|
|
(?:.*?/)? |
|
|
|
(?: |
|
|
|
(?: |
|
|
@ -580,11 +590,9 @@ class VimeoIE(VimeoBaseInfoExtractor): |
|
|
|
# and latter we extract those that are Vimeo specific. |
|
|
|
self.report_extraction(video_id) |
|
|
|
|
|
|
|
vimeo_config = self._search_regex( |
|
|
|
r'vimeo\.config\s*=\s*(?:({.+?})|_extend\([^,]+,\s+({.+?})\));', webpage, |
|
|
|
'vimeo config', default=None) |
|
|
|
vimeo_config = self._extract_vimeo_config(webpage, video_id, default=None) |
|
|
|
if vimeo_config: |
|
|
|
seed_status = self._parse_json(vimeo_config, video_id).get('seed_status', {}) |
|
|
|
seed_status = vimeo_config.get('seed_status', {}) |
|
|
|
if seed_status.get('state') == 'failed': |
|
|
|
raise ExtractorError( |
|
|
|
'%s said: %s' % (self.IE_NAME, seed_status['title']), |
|
|
@ -905,7 +913,7 @@ class VimeoUserIE(VimeoChannelIE): |
|
|
|
|
|
|
|
class VimeoAlbumIE(VimeoChannelIE): |
|
|
|
IE_NAME = 'vimeo:album' |
|
|
|
_VALID_URL = r'https://vimeo\.com/album/(?P<id>\d+)(?:$|[?#]|/(?!video))' |
|
|
|
_VALID_URL = r'https://vimeo\.com/(?:album|showcase)/(?P<id>\d+)(?:$|[?#]|/(?!video))' |
|
|
|
_TITLE_RE = r'<header id="page_header">\n\s*<h1>(.*?)</h1>' |
|
|
|
_TESTS = [{ |
|
|
|
'url': 'https://vimeo.com/album/2632481', |
|
|
@ -925,21 +933,39 @@ class VimeoAlbumIE(VimeoChannelIE): |
|
|
|
'params': { |
|
|
|
'videopassword': 'youtube-dl', |
|
|
|
} |
|
|
|
}, { |
|
|
|
'url': 'https://vimeo.com/album/2632481/sort:plays/format:thumbnail', |
|
|
|
'only_matching': True, |
|
|
|
}, { |
|
|
|
# TODO: respect page number |
|
|
|
'url': 'https://vimeo.com/album/2632481/page:2/sort:plays/format:thumbnail', |
|
|
|
'only_matching': True, |
|
|
|
}] |
|
|
|
|
|
|
|
def _page_url(self, base_url, pagenum): |
|
|
|
return '%s/page:%d/' % (base_url, pagenum) |
|
|
|
_PAGE_SIZE = 100 |
|
|
|
|
|
|
|
def _fetch_page(self, album_id, authorizaion, hashed_pass, page): |
|
|
|
api_page = page + 1 |
|
|
|
query = { |
|
|
|
'fields': 'link', |
|
|
|
'page': api_page, |
|
|
|
'per_page': self._PAGE_SIZE, |
|
|
|
} |
|
|
|
if hashed_pass: |
|
|
|
query['_hashed_pass'] = hashed_pass |
|
|
|
videos = self._download_json( |
|
|
|
'https://api.vimeo.com/albums/%s/videos' % album_id, |
|
|
|
album_id, 'Downloading page %d' % api_page, query=query, headers={ |
|
|
|
'Authorization': 'jwt ' + authorizaion, |
|
|
|
})['data'] |
|
|
|
for video in videos: |
|
|
|
link = video.get('link') |
|
|
|
if not link: |
|
|
|
continue |
|
|
|
yield self.url_result(link, VimeoIE.ie_key(), VimeoIE._match_id(link)) |
|
|
|
|
|
|
|
def _real_extract(self, url): |
|
|
|
album_id = self._match_id(url) |
|
|
|
return self._extract_videos(album_id, 'https://vimeo.com/album/%s' % album_id) |
|
|
|
webpage = self._download_webpage(url, album_id) |
|
|
|
webpage = self._login_list_password(url, album_id, webpage) |
|
|
|
api_config = self._extract_vimeo_config(webpage, album_id)['api'] |
|
|
|
entries = OnDemandPagedList(functools.partial( |
|
|
|
self._fetch_page, album_id, api_config['jwt'], |
|
|
|
api_config.get('hashed_pass')), self._PAGE_SIZE) |
|
|
|
return self.playlist_result(entries, album_id, self._html_search_regex( |
|
|
|
r'<title>\s*(.+?)(?:\s+on Vimeo)?</title>', webpage, 'title', fatal=False)) |
|
|
|
|
|
|
|
|
|
|
|
class VimeoGroupsIE(VimeoAlbumIE): |
|
|
|