[vessel] Add new extractor (Closes #5275)

This commit is contained in:
Naglis Jonaitis 2015-03-26 19:48:22 +02:00
parent 425142be60
commit 223b27f46c
2 changed files with 128 additions and 0 deletions

View File

@ -551,6 +551,7 @@ from .ustream import UstreamIE, UstreamChannelIE
from .vbox7 import Vbox7IE
from .veehd import VeeHDIE
from .veoh import VeohIE
from .vessel import VesselIE
from .vesti import VestiIE
from .vevo import VevoIE
from .vgtv import VGTVIE

View File

@ -0,0 +1,127 @@
# coding: utf-8
from __future__ import unicode_literals
import json
from .common import InfoExtractor
from ..compat import compat_urllib_request
from ..utils import (
ExtractorError,
parse_iso8601,
)
class VesselIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?vessel\.com/videos/(?P<id>[0-9a-zA-Z]+)'
_API_URL_TEMPLATE = 'https://www.vessel.com/api/view/items/%s'
_LOGIN_URL = 'https://www.vessel.com/api/account/login'
_NETRC_MACHINE = 'vessel'
_TEST = {
'url': 'https://www.vessel.com/videos/HDN7G5UMs',
'md5': '455cdf8beb71c6dd797fd2f3818d05c4',
'info_dict': {
'id': 'HDN7G5UMs',
'ext': 'mp4',
'title': 'Nvidia GeForce GTX Titan X - The Best Video Card on the Market?',
'thumbnail': 're:^https?://.*\.jpg$',
'upload_date': '20150317',
'description': 'Did Nvidia pull out all the stops on the Titan X, or does its performance leave something to be desired?',
'timestamp': int,
},
}
@staticmethod
def make_json_request(url, data):
payload = json.dumps(data).encode('utf-8')
req = compat_urllib_request.Request(url, payload)
req.add_header('Content-Type', 'application/json; charset=utf-8')
return req
@staticmethod
def find_assets(data, asset_type):
for asset in data.get('assets', []):
if asset.get('type') == asset_type:
yield asset
def _check_access_rights(self, data):
access_info = data.get('__view', {})
if access_info.get('allow_access') == False:
err_code = access_info.get('error_code') or ''
if err_code == 'ITEM_PAID_ONLY':
raise ExtractorError(
'This video requires subscription.', expected=True)
else:
raise ExtractorError(
'Access to this content is restricted. (%s said: %s)' % (self.IE_NAME, err_code), expected=True)
def _login(self):
(username, password) = self._get_login_info()
if username is None:
return
self.report_login()
data = {
'client_id': 'web',
'type': 'password',
'user_key': username,
'password': password,
}
login_request = VesselIE.make_json_request(self._LOGIN_URL, data)
self._download_webpage(login_request, None, False, 'Wrong login info')
def _real_initialize(self):
self._login()
def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
data = self._parse_json(self._search_regex(
r'App\.bootstrapData\((.*?)\);', webpage, 'data'), video_id)
asset_id = data['model']['data']['id']
req = VesselIE.make_json_request(
self._API_URL_TEMPLATE % asset_id, {'client': 'web'})
data = self._download_json(req, video_id)
self._check_access_rights(data)
try:
video_asset = next(VesselIE.find_assets(data, 'video'))
except StopIteration:
raise ExtractorError('No video assets found')
formats = []
for f in video_asset.get('sources', []):
if f['name'] == 'hls-index':
formats.extend(self._extract_m3u8_formats(
f['location'], video_id, ext='mp4', m3u8_id='m3u8'))
else:
formats.append({
'format_id': f['name'],
'tbr': f.get('bitrate'),
'height': f.get('height'),
'width': f.get('width'),
'url': f['location'],
})
self._sort_formats(formats)
thumbnails = []
for im_asset in VesselIE.find_assets(data, 'image'):
thumbnails.append({
'url': im_asset['location'],
'width': im_asset.get('width', 0),
'height': im_asset.get('height', 0),
})
return {
'id': video_id,
'title': data['title'],
'formats': formats,
'thumbnails': thumbnails,
'description': data.get('short_description'),
'duration': data.get('duration'),
'comment_count': data.get('comment_count'),
'like_count': data.get('like_count'),
'view_count': data.get('view_count'),
'timestamp': parse_iso8601(data.get('released_at')),
}