aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulio Napurí <julionc@gmail.com>2024-11-11 12:42:05 -0500
committerGitHub <noreply@github.com>2024-11-11 18:42:05 +0100
commitc39016f66df76d14284c705736ca73db8055d8de (patch)
treeb561dc141c4b09f1422214e4c443cd04c6d03e6a
parentb83ca24eb72e1e558b0185bd73975586c0bc0546 (diff)
[ie/spreaker] Support episode pages and access keys (#11489)
Authored by: julionc
-rw-r--r--yt_dlp/extractor/_extractors.py1
-rw-r--r--yt_dlp/extractor/spreaker.py63
2 files changed, 34 insertions, 30 deletions
diff --git a/yt_dlp/extractor/_extractors.py b/yt_dlp/extractor/_extractors.py
index fc3ffeef0..4543c8587 100644
--- a/yt_dlp/extractor/_extractors.py
+++ b/yt_dlp/extractor/_extractors.py
@@ -1939,7 +1939,6 @@ from .spotify import (
)
from .spreaker import (
SpreakerIE,
- SpreakerPageIE,
SpreakerShowIE,
SpreakerShowPageIE,
)
diff --git a/yt_dlp/extractor/spreaker.py b/yt_dlp/extractor/spreaker.py
index d1df45969..ff6e1f423 100644
--- a/yt_dlp/extractor/spreaker.py
+++ b/yt_dlp/extractor/spreaker.py
@@ -4,11 +4,13 @@ from .common import InfoExtractor
from ..utils import (
float_or_none,
int_or_none,
+ parse_qs,
str_or_none,
try_get,
unified_timestamp,
url_or_none,
)
+from ..utils.traversal import traverse_obj
def _extract_episode(data, episode_id=None):
@@ -58,15 +60,10 @@ def _extract_episode(data, episode_id=None):
class SpreakerIE(InfoExtractor):
- _VALID_URL = r'''(?x)
- https?://
- api\.spreaker\.com/
- (?:
- (?:download/)?episode|
- v2/episodes
- )/
- (?P<id>\d+)
- '''
+ _VALID_URL = [
+ r'https?://api\.spreaker\.com/(?:(?:download/)?episode|v2/episodes)/(?P<id>\d+)',
+ r'https?://(?:www\.)?spreaker\.com/episode/[^#?/]*?(?P<id>\d+)/?(?:[?#]|$)',
+ ]
_TESTS = [{
'url': 'https://api.spreaker.com/episode/12534508',
'info_dict': {
@@ -83,7 +80,9 @@ class SpreakerIE(InfoExtractor):
'view_count': int,
'like_count': int,
'comment_count': int,
- 'series': 'Success With Music (SWM)',
+ 'series': 'Success With Music | SWM',
+ 'thumbnail': 'https://d3wo5wojvuv7l.cloudfront.net/t_square_limited_160/images.spreaker.com/original/777ce4f96b71b0e1b7c09a5e625210e3.jpg',
+ 'creators': ['SWM'],
},
}, {
'url': 'https://api.spreaker.com/download/episode/12534508/swm_ep15_how_to_market_your_music_part_2.mp3',
@@ -91,34 +90,40 @@ class SpreakerIE(InfoExtractor):
}, {
'url': 'https://api.spreaker.com/v2/episodes/12534508?export=episode_segments',
'only_matching': True,
+ }, {
+ 'note': 'episode',
+ 'url': 'https://www.spreaker.com/episode/grunge-music-origins-the-raw-sound-that-defined-a-generation--60269615',
+ 'info_dict': {
+ 'id': '60269615',
+ 'display_id': 'grunge-music-origins-the-raw-sound-that-',
+ 'ext': 'mp3',
+ 'title': 'Grunge Music Origins - The Raw Sound that Defined a Generation',
+ 'description': str,
+ 'timestamp': 1717468905,
+ 'upload_date': '20240604',
+ 'uploader': 'Katie Brown 2',
+ 'uploader_id': '17733249',
+ 'duration': 818.83,
+ 'view_count': int,
+ 'like_count': int,
+ 'comment_count': int,
+ 'series': '90s Grunge',
+ 'thumbnail': 'https://d3wo5wojvuv7l.cloudfront.net/t_square_limited_160/images.spreaker.com/original/bb0d4178f7cf57cc8786dedbd9c5d969.jpg',
+ 'creators': ['Katie Brown 2'],
+ },
+ }, {
+ 'url': 'https://www.spreaker.com/episode/60269615',
+ 'only_matching': True,
}]
def _real_extract(self, url):
episode_id = self._match_id(url)
data = self._download_json(
f'https://api.spreaker.com/v2/episodes/{episode_id}',
- episode_id)['response']['episode']
+ episode_id, query=traverse_obj(parse_qs(url), {'key': ('key', 0)}))['response']['episode']
return _extract_episode(data, episode_id)
-class SpreakerPageIE(InfoExtractor):
- _VALID_URL = r'https?://(?:www\.)?spreaker\.com/user/[^/]+/(?P<id>[^/?#&]+)'
- _TESTS = [{
- 'url': 'https://www.spreaker.com/user/9780658/swm-ep15-how-to-market-your-music-part-2',
- 'only_matching': True,
- }]
-
- def _real_extract(self, url):
- display_id = self._match_id(url)
- webpage = self._download_webpage(url, display_id)
- episode_id = self._search_regex(
- (r'data-episode_id=["\'](?P<id>\d+)',
- r'episode_id\s*:\s*(?P<id>\d+)'), webpage, 'episode id')
- return self.url_result(
- f'https://api.spreaker.com/episode/{episode_id}',
- ie=SpreakerIE.ie_key(), video_id=episode_id)
-
-
class SpreakerShowIE(InfoExtractor):
_VALID_URL = r'https?://api\.spreaker\.com/show/(?P<id>\d+)'
_TESTS = [{