mirror of
https://github.com/ytdl-org/youtube-dl.git
synced 2024-01-07 17:16:08 +00:00
parent
8c17afc471
commit
d0d838638c
|
@ -4,25 +4,28 @@ import re
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
determine_ext,
|
clean_html,
|
||||||
|
ExtractorError,
|
||||||
int_or_none,
|
int_or_none,
|
||||||
js_to_json,
|
str_or_none,
|
||||||
unescapeHTML,
|
try_get,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class StitcherIE(InfoExtractor):
|
class StitcherIE(InfoExtractor):
|
||||||
_VALID_URL = r'https?://(?:www\.)?stitcher\.com/podcast/(?:[^/]+/)+e/(?:(?P<display_id>[^/#?&]+?)-)?(?P<id>\d+)(?:[/#?&]|$)'
|
_VALID_URL = r'https?://(?:www\.)?stitcher\.com/(?:podcast|show)/(?:[^/]+/)+e(?:pisode)?/(?:(?P<display_id>[^/#?&]+?)-)?(?P<id>\d+)(?:[/#?&]|$)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
'url': 'http://www.stitcher.com/podcast/the-talking-machines/e/40789481?autoplay=true',
|
'url': 'http://www.stitcher.com/podcast/the-talking-machines/e/40789481?autoplay=true',
|
||||||
'md5': '391dd4e021e6edeb7b8e68fbf2e9e940',
|
'md5': 'e9635098e0da10b21a0e2b85585530f6',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '40789481',
|
'id': '40789481',
|
||||||
'ext': 'mp3',
|
'ext': 'mp3',
|
||||||
'title': 'Machine Learning Mastery and Cancer Clusters',
|
'title': 'Machine Learning Mastery and Cancer Clusters',
|
||||||
'description': 'md5:55163197a44e915a14a1ac3a1de0f2d3',
|
'description': 'md5:547adb4081864be114ae3831b4c2b42f',
|
||||||
'duration': 1604,
|
'duration': 1604,
|
||||||
'thumbnail': r're:^https?://.*\.jpg',
|
'thumbnail': r're:^https?://.*\.jpg',
|
||||||
|
'upload_date': '20180126',
|
||||||
|
'timestamp': 1516989316,
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'url': 'http://www.stitcher.com/podcast/panoply/vulture-tv/e/the-rare-hourlong-comedy-plus-40846275?autoplay=true',
|
'url': 'http://www.stitcher.com/podcast/panoply/vulture-tv/e/the-rare-hourlong-comedy-plus-40846275?autoplay=true',
|
||||||
|
@ -38,6 +41,7 @@ class StitcherIE(InfoExtractor):
|
||||||
'params': {
|
'params': {
|
||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
},
|
},
|
||||||
|
'skip': 'Page Not Found',
|
||||||
}, {
|
}, {
|
||||||
# escaped title
|
# escaped title
|
||||||
'url': 'http://www.stitcher.com/podcast/marketplace-on-stitcher/e/40910226?autoplay=true',
|
'url': 'http://www.stitcher.com/podcast/marketplace-on-stitcher/e/40910226?autoplay=true',
|
||||||
|
@ -45,37 +49,39 @@ class StitcherIE(InfoExtractor):
|
||||||
}, {
|
}, {
|
||||||
'url': 'http://www.stitcher.com/podcast/panoply/getting-in/e/episode-2a-how-many-extracurriculars-should-i-have-40876278?autoplay=true',
|
'url': 'http://www.stitcher.com/podcast/panoply/getting-in/e/episode-2a-how-many-extracurriculars-should-i-have-40876278?autoplay=true',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.stitcher.com/show/threedom/episode/circles-on-a-stick-200212584',
|
||||||
|
'only_matching': True,
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
mobj = re.match(self._VALID_URL, url)
|
display_id, audio_id = re.match(self._VALID_URL, url).groups()
|
||||||
audio_id = mobj.group('id')
|
|
||||||
display_id = mobj.group('display_id') or audio_id
|
|
||||||
|
|
||||||
webpage = self._download_webpage(url, display_id)
|
resp = self._download_json(
|
||||||
|
'https://api.prod.stitcher.com/episode/' + audio_id,
|
||||||
|
display_id or audio_id)
|
||||||
|
episode = try_get(resp, lambda x: x['data']['episodes'][0], dict)
|
||||||
|
if not episode:
|
||||||
|
raise ExtractorError(resp['errors'][0]['message'], expected=True)
|
||||||
|
|
||||||
episode = self._parse_json(
|
title = episode['title'].strip()
|
||||||
js_to_json(self._search_regex(
|
audio_url = episode['audio_url']
|
||||||
r'(?s)var\s+stitcher(?:Config)?\s*=\s*({.+?});\n', webpage, 'episode config')),
|
|
||||||
display_id)['config']['episode']
|
|
||||||
|
|
||||||
title = unescapeHTML(episode['title'])
|
thumbnail = None
|
||||||
formats = [{
|
show_id = episode.get('show_id')
|
||||||
'url': episode[episode_key],
|
if show_id and episode.get('classic_id') != -1:
|
||||||
'ext': determine_ext(episode[episode_key]) or 'mp3',
|
thumbnail = 'https://stitcher-classic.imgix.net/feedimages/%s.jpg' % show_id
|
||||||
'vcodec': 'none',
|
|
||||||
} for episode_key in ('episodeURL',) if episode.get(episode_key)]
|
|
||||||
description = self._search_regex(
|
|
||||||
r'Episode Info:\s*</span>([^<]+)<', webpage, 'description', fatal=False)
|
|
||||||
duration = int_or_none(episode.get('duration'))
|
|
||||||
thumbnail = episode.get('episodeImage')
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'id': audio_id,
|
'id': audio_id,
|
||||||
'display_id': display_id,
|
'display_id': display_id,
|
||||||
'title': title,
|
'title': title,
|
||||||
'description': description,
|
'description': clean_html(episode.get('html_description') or episode.get('description')),
|
||||||
'duration': duration,
|
'duration': int_or_none(episode.get('duration')),
|
||||||
'thumbnail': thumbnail,
|
'thumbnail': thumbnail,
|
||||||
'formats': formats,
|
'url': audio_url,
|
||||||
|
'vcodec': 'none',
|
||||||
|
'timestamp': int_or_none(episode.get('date_created')),
|
||||||
|
'season_number': int_or_none(episode.get('season')),
|
||||||
|
'season_id': str_or_none(episode.get('season_id')),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue