mirror of
https://github.com/ytdl-org/youtube-dl
synced 2025-04-01 04:37:27 +09:00
Compare commits
No commits in common. "bfa345744d055b2420f82336b339a51a9d73b28a" and "c0d9eb7043b739936f936a7c854bae0195cc1763" have entirely different histories.
bfa345744d
...
c0d9eb7043
77
youtube_dl/extractor/everyonesmixtape.py
Normal file
77
youtube_dl/extractor/everyonesmixtape.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..utils import (
|
||||||
|
ExtractorError,
|
||||||
|
sanitized_Request,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class EveryonesMixtapeIE(InfoExtractor):
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?everyonesmixtape\.com/#/mix/(?P<id>[0-9a-zA-Z]+)(?:/(?P<songnr>[0-9]))?$'
|
||||||
|
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'http://everyonesmixtape.com/#/mix/m7m0jJAbMQi/5',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '5bfseWNmlds',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': "Passion Pit - \"Sleepyhead\" (Official Music Video)",
|
||||||
|
'uploader': 'FKR.TV',
|
||||||
|
'uploader_id': 'frenchkissrecords',
|
||||||
|
'description': "Music video for \"Sleepyhead\" from Passion Pit's debut EP Chunk Of Change.\nBuy on iTunes: https://itunes.apple.com/us/album/chunk-of-change-ep/id300087641\n\nDirected by The Wilderness.\n\nhttp://www.passionpitmusic.com\nhttp://www.frenchkissrecords.com",
|
||||||
|
'upload_date': '20081015'
|
||||||
|
},
|
||||||
|
'params': {
|
||||||
|
'skip_download': True, # This is simply YouTube
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
'url': 'http://everyonesmixtape.com/#/mix/m7m0jJAbMQi',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'm7m0jJAbMQi',
|
||||||
|
'title': 'Driving',
|
||||||
|
},
|
||||||
|
'playlist_count': 24
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
mobj = re.match(self._VALID_URL, url)
|
||||||
|
playlist_id = mobj.group('id')
|
||||||
|
|
||||||
|
pllist_url = 'http://everyonesmixtape.com/mixtape.php?a=getMixes&u=-1&linked=%s&explore=' % playlist_id
|
||||||
|
pllist_req = sanitized_Request(pllist_url)
|
||||||
|
pllist_req.add_header('X-Requested-With', 'XMLHttpRequest')
|
||||||
|
|
||||||
|
playlist_list = self._download_json(
|
||||||
|
pllist_req, playlist_id, note='Downloading playlist metadata')
|
||||||
|
try:
|
||||||
|
playlist_no = next(playlist['id']
|
||||||
|
for playlist in playlist_list
|
||||||
|
if playlist['code'] == playlist_id)
|
||||||
|
except StopIteration:
|
||||||
|
raise ExtractorError('Playlist id not found')
|
||||||
|
|
||||||
|
pl_url = 'http://everyonesmixtape.com/mixtape.php?a=getMix&id=%s&userId=null&code=' % playlist_no
|
||||||
|
pl_req = sanitized_Request(pl_url)
|
||||||
|
pl_req.add_header('X-Requested-With', 'XMLHttpRequest')
|
||||||
|
playlist = self._download_json(
|
||||||
|
pl_req, playlist_id, note='Downloading playlist info')
|
||||||
|
|
||||||
|
entries = [{
|
||||||
|
'_type': 'url',
|
||||||
|
'url': t['url'],
|
||||||
|
'title': t['title'],
|
||||||
|
} for t in playlist['tracks']]
|
||||||
|
|
||||||
|
if mobj.group('songnr'):
|
||||||
|
songnr = int(mobj.group('songnr')) - 1
|
||||||
|
return entries[songnr]
|
||||||
|
|
||||||
|
playlist_title = playlist['mixData']['name']
|
||||||
|
return {
|
||||||
|
'_type': 'playlist',
|
||||||
|
'id': playlist_id,
|
||||||
|
'title': playlist_title,
|
||||||
|
'entries': entries,
|
||||||
|
}
|
@ -327,6 +327,7 @@ from .espn import (
|
|||||||
)
|
)
|
||||||
from .esri import EsriVideoIE
|
from .esri import EsriVideoIE
|
||||||
from .europa import EuropaIE
|
from .europa import EuropaIE
|
||||||
|
from .everyonesmixtape import EveryonesMixtapeIE
|
||||||
from .expotv import ExpoTVIE
|
from .expotv import ExpoTVIE
|
||||||
from .expressen import ExpressenIE
|
from .expressen import ExpressenIE
|
||||||
from .extremetube import ExtremeTubeIE
|
from .extremetube import ExtremeTubeIE
|
||||||
@ -1128,6 +1129,7 @@ from .tagesschau import (
|
|||||||
TagesschauIE,
|
TagesschauIE,
|
||||||
)
|
)
|
||||||
from .tass import TassIE
|
from .tass import TassIE
|
||||||
|
from .tastytrade import TastyTradeIE
|
||||||
from .tbs import TBSIE
|
from .tbs import TBSIE
|
||||||
from .tdslifeway import TDSLifewayIE
|
from .tdslifeway import TDSLifewayIE
|
||||||
from .teachable import (
|
from .teachable import (
|
||||||
|
@ -1,23 +1,20 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import datetime
|
|
||||||
import functools
|
|
||||||
import json
|
import json
|
||||||
import math
|
import datetime
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from ..compat import (
|
from ..compat import (
|
||||||
compat_parse_qs,
|
compat_parse_qs,
|
||||||
compat_urllib_parse_urlparse,
|
compat_urlparse,
|
||||||
)
|
)
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
determine_ext,
|
determine_ext,
|
||||||
dict_get,
|
dict_get,
|
||||||
ExtractorError,
|
ExtractorError,
|
||||||
float_or_none,
|
|
||||||
InAdvancePagedList,
|
|
||||||
int_or_none,
|
int_or_none,
|
||||||
|
float_or_none,
|
||||||
parse_duration,
|
parse_duration,
|
||||||
parse_iso8601,
|
parse_iso8601,
|
||||||
remove_start,
|
remove_start,
|
||||||
@ -184,7 +181,7 @@ class NiconicoIE(InfoExtractor):
|
|||||||
if urlh is False:
|
if urlh is False:
|
||||||
login_ok = False
|
login_ok = False
|
||||||
else:
|
else:
|
||||||
parts = compat_urllib_parse_urlparse(urlh.geturl())
|
parts = compat_urlparse.urlparse(urlh.geturl())
|
||||||
if compat_parse_qs(parts.query).get('message', [None])[0] == 'cant_login':
|
if compat_parse_qs(parts.query).get('message', [None])[0] == 'cant_login':
|
||||||
login_ok = False
|
login_ok = False
|
||||||
if not login_ok:
|
if not login_ok:
|
||||||
@ -295,7 +292,7 @@ class NiconicoIE(InfoExtractor):
|
|||||||
'http://flapi.nicovideo.jp/api/getflv/' + video_id + '?as3=1',
|
'http://flapi.nicovideo.jp/api/getflv/' + video_id + '?as3=1',
|
||||||
video_id, 'Downloading flv info')
|
video_id, 'Downloading flv info')
|
||||||
|
|
||||||
flv_info = compat_parse_qs(flv_info_webpage)
|
flv_info = compat_urlparse.parse_qs(flv_info_webpage)
|
||||||
if 'url' not in flv_info:
|
if 'url' not in flv_info:
|
||||||
if 'deleted' in flv_info:
|
if 'deleted' in flv_info:
|
||||||
raise ExtractorError('The video has been deleted.',
|
raise ExtractorError('The video has been deleted.',
|
||||||
@ -440,76 +437,34 @@ class NiconicoIE(InfoExtractor):
|
|||||||
|
|
||||||
|
|
||||||
class NiconicoPlaylistIE(InfoExtractor):
|
class NiconicoPlaylistIE(InfoExtractor):
|
||||||
_VALID_URL = r'https?://(?:www\.)?nicovideo\.jp/(?:user/\d+/)?mylist/(?P<id>\d+)'
|
_VALID_URL = r'https?://(?:www\.)?nicovideo\.jp/mylist/(?P<id>\d+)'
|
||||||
|
|
||||||
_TESTS = [{
|
_TEST = {
|
||||||
'url': 'http://www.nicovideo.jp/mylist/27411728',
|
'url': 'http://www.nicovideo.jp/mylist/27411728',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '27411728',
|
'id': '27411728',
|
||||||
'title': 'AKB48のオールナイトニッポン',
|
'title': 'AKB48のオールナイトニッポン',
|
||||||
'description': 'md5:d89694c5ded4b6c693dea2db6e41aa08',
|
|
||||||
'uploader': 'のっく',
|
|
||||||
'uploader_id': '805442',
|
|
||||||
},
|
},
|
||||||
'playlist_mincount': 225,
|
'playlist_mincount': 225,
|
||||||
}, {
|
|
||||||
'url': 'https://www.nicovideo.jp/user/805442/mylist/27411728',
|
|
||||||
'only_matching': True,
|
|
||||||
}]
|
|
||||||
_PAGE_SIZE = 100
|
|
||||||
|
|
||||||
def _call_api(self, list_id, resource, query):
|
|
||||||
return self._download_json(
|
|
||||||
'https://nvapi.nicovideo.jp/v2/mylists/' + list_id, list_id,
|
|
||||||
'Downloading %s JSON metatdata' % resource, query=query,
|
|
||||||
headers={'X-Frontend-Id': 6})['data']['mylist']
|
|
||||||
|
|
||||||
def _parse_owner(self, item):
|
|
||||||
owner = item.get('owner') or {}
|
|
||||||
if owner:
|
|
||||||
return {
|
|
||||||
'uploader': owner.get('name'),
|
|
||||||
'uploader_id': owner.get('id'),
|
|
||||||
}
|
}
|
||||||
return {}
|
|
||||||
|
|
||||||
def _fetch_page(self, list_id, page):
|
|
||||||
page += 1
|
|
||||||
items = self._call_api(list_id, 'page %d' % page, {
|
|
||||||
'page': page,
|
|
||||||
'pageSize': self._PAGE_SIZE,
|
|
||||||
})['items']
|
|
||||||
for item in items:
|
|
||||||
video = item.get('video') or {}
|
|
||||||
video_id = video.get('id')
|
|
||||||
if not video_id:
|
|
||||||
continue
|
|
||||||
count = video.get('count') or {}
|
|
||||||
get_count = lambda x: int_or_none(count.get(x))
|
|
||||||
info = {
|
|
||||||
'_type': 'url',
|
|
||||||
'id': video_id,
|
|
||||||
'title': video.get('title'),
|
|
||||||
'url': 'https://www.nicovideo.jp/watch/' + video_id,
|
|
||||||
'description': video.get('shortDescription'),
|
|
||||||
'duration': int_or_none(video.get('duration')),
|
|
||||||
'view_count': get_count('view'),
|
|
||||||
'comment_count': get_count('comment'),
|
|
||||||
'ie_key': NiconicoIE.ie_key(),
|
|
||||||
}
|
|
||||||
info.update(self._parse_owner(video))
|
|
||||||
yield info
|
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
list_id = self._match_id(url)
|
list_id = self._match_id(url)
|
||||||
mylist = self._call_api(list_id, 'list', {
|
webpage = self._download_webpage(url, list_id)
|
||||||
'pageSize': 1,
|
|
||||||
})
|
entries_json = self._search_regex(r'Mylist\.preload\(\d+, (\[.*\])\);',
|
||||||
entries = InAdvancePagedList(
|
webpage, 'entries')
|
||||||
functools.partial(self._fetch_page, list_id),
|
entries = json.loads(entries_json)
|
||||||
math.ceil(mylist['totalItemCount'] / self._PAGE_SIZE),
|
entries = [{
|
||||||
self._PAGE_SIZE)
|
'_type': 'url',
|
||||||
result = self.playlist_result(
|
'ie_key': NiconicoIE.ie_key(),
|
||||||
entries, list_id, mylist.get('name'), mylist.get('description'))
|
'url': ('http://www.nicovideo.jp/watch/%s' %
|
||||||
result.update(self._parse_owner(mylist))
|
entry['item_data']['video_id']),
|
||||||
return result
|
} for entry in entries]
|
||||||
|
|
||||||
|
return {
|
||||||
|
'_type': 'playlist',
|
||||||
|
'title': self._search_regex(r'\s+name: "(.*?)"', webpage, 'title'),
|
||||||
|
'id': list_id,
|
||||||
|
'entries': entries,
|
||||||
|
}
|
||||||
|
43
youtube_dl/extractor/tastytrade.py
Normal file
43
youtube_dl/extractor/tastytrade.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from .ooyala import OoyalaIE
|
||||||
|
|
||||||
|
|
||||||
|
class TastyTradeIE(InfoExtractor):
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?tastytrade\.com/tt/shows/[^/]+/episodes/(?P<id>[^/?#&]+)'
|
||||||
|
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://www.tastytrade.com/tt/shows/market-measures/episodes/correlation-in-short-volatility-06-28-2017',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'F3bnlzbToeI6pLEfRyrlfooIILUjz4nM',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'A History of Teaming',
|
||||||
|
'description': 'md5:2a9033db8da81f2edffa4c99888140b3',
|
||||||
|
'duration': 422.255,
|
||||||
|
},
|
||||||
|
'params': {
|
||||||
|
'skip_download': True,
|
||||||
|
},
|
||||||
|
'add_ie': ['Ooyala'],
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.tastytrade.com/tt/shows/daily-dose/episodes/daily-dose-06-30-2017',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
display_id = self._match_id(url)
|
||||||
|
webpage = self._download_webpage(url, display_id)
|
||||||
|
|
||||||
|
ooyala_code = self._search_regex(
|
||||||
|
r'data-media-id=(["\'])(?P<code>(?:(?!\1).)+)\1',
|
||||||
|
webpage, 'ooyala code', group='code')
|
||||||
|
|
||||||
|
info = self._search_json_ld(webpage, display_id, fatal=False)
|
||||||
|
info.update({
|
||||||
|
'_type': 'url_transparent',
|
||||||
|
'ie_key': OoyalaIE.ie_key(),
|
||||||
|
'url': 'ooyala:%s' % ooyala_code,
|
||||||
|
'display_id': display_id,
|
||||||
|
})
|
||||||
|
return info
|
Loading…
Reference in New Issue
Block a user