mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2026-07-02 16:28:52 +00:00
[ie/mxplayer] Rework extractors (#17018)
Closes #3705 Closes #6115 Closes #7428 Closes #15371 Closes #15382 Closes #15968 Authored by: doe1080
This commit is contained in:
parent
f49b551a0c
commit
55a58debec
@ -1109,6 +1109,8 @@ from .mx3 import (
|
|||||||
)
|
)
|
||||||
from .mxplayer import (
|
from .mxplayer import (
|
||||||
MxplayerIE,
|
MxplayerIE,
|
||||||
|
MxplayerRedirectIE,
|
||||||
|
MxplayerSeasonIE,
|
||||||
MxplayerShowIE,
|
MxplayerShowIE,
|
||||||
)
|
)
|
||||||
from .myspace import (
|
from .myspace import (
|
||||||
|
|||||||
@ -1,242 +1,450 @@
|
|||||||
|
import itertools
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
|
ExtractorError,
|
||||||
|
UnsupportedError,
|
||||||
|
clean_html,
|
||||||
|
determine_ext,
|
||||||
|
float_or_none,
|
||||||
int_or_none,
|
int_or_none,
|
||||||
traverse_obj,
|
join_nonempty,
|
||||||
try_get,
|
orderedSet,
|
||||||
|
parse_iso8601,
|
||||||
|
str_or_none,
|
||||||
|
url_or_none,
|
||||||
urljoin,
|
urljoin,
|
||||||
)
|
)
|
||||||
|
from ..utils.traversal import find_element, traverse_obj
|
||||||
|
|
||||||
|
|
||||||
class MxplayerIE(InfoExtractor):
|
class MxplayerBaseIE(InfoExtractor):
|
||||||
_VALID_URL = r'https?://(?:www\.)?mxplayer\.in/(?P<type>movie|show/[-\w]+/[-\w]+)/(?P<display_id>[-\w]+)-(?P<id>\w+)'
|
_BASE_URL = 'https://www.mxplayer.in'
|
||||||
|
_GEO_BYPASS = False
|
||||||
|
_GEO_COUNTRIES = ['IN']
|
||||||
|
|
||||||
|
def _extract_mxs(self, url, item_id):
|
||||||
|
webpage = self._download_webpage(url, item_id)
|
||||||
|
if error_msg := traverse_obj(webpage, (
|
||||||
|
{find_element(cls='sub-message')}, {clean_html}, filter,
|
||||||
|
)):
|
||||||
|
self.raise_geo_restricted(error_msg, countries=self._GEO_COUNTRIES)
|
||||||
|
|
||||||
|
return self._search_json(r'window\.__mxs__\s*=', webpage, 'mxs', item_id)
|
||||||
|
|
||||||
|
|
||||||
|
class MxplayerIE(MxplayerBaseIE):
|
||||||
|
IE_NAME = 'mxplayer'
|
||||||
|
IE_DESC = 'Amazon MX Player'
|
||||||
|
|
||||||
|
_VALID_URL = r'''(?x)
|
||||||
|
https?://(?:www\.)?mxplayer\.in/
|
||||||
|
(?:movie|shorts|show/[\w-]+/(?!seasons/)[\w-]+)/
|
||||||
|
(?P<display_id>[\w-]+)-(?P<id>[0-9a-f]{32})(?:[/?#]|$)
|
||||||
|
'''
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
'url': 'https://www.mxplayer.in/show/watch-my-girlfriend-is-an-alien-hindi-dubbed/season-1/episode-1-online-9d2013d31d5835bb8400e3b3c5e7bb72',
|
# show, mxplay
|
||||||
|
'url': 'https://www.mxplayer.in/show/watch-my-girlfriend-is-an-alien/season-1/episode-1-online-9d2013d31d5835bb8400e3b3c5e7bb72',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '9d2013d31d5835bb8400e3b3c5e7bb72',
|
'id': '9d2013d31d5835bb8400e3b3c5e7bb72',
|
||||||
'display_id': 'episode-1-online',
|
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'title': 'Episode 1',
|
'title': 'Episode 1',
|
||||||
|
'age_limit': 16,
|
||||||
|
'cast': 'count:10',
|
||||||
|
'creators': 'count:2',
|
||||||
'description': 'md5:e90dc55a393f557049284eb36efdb773',
|
'description': 'md5:e90dc55a393f557049284eb36efdb773',
|
||||||
'season_number': 1,
|
'display_id': 'episode-1-online',
|
||||||
|
'episode': 'Episode 1',
|
||||||
'episode_number': 1,
|
'episode_number': 1,
|
||||||
'duration': 2451,
|
'duration': 2451,
|
||||||
|
'genres': 'count:8',
|
||||||
|
'release_date': '20241201',
|
||||||
|
'release_timestamp': 1733077800,
|
||||||
'season': 'Season 1',
|
'season': 'Season 1',
|
||||||
|
'season_number': 1,
|
||||||
'series': 'My Girlfriend Is An Alien',
|
'series': 'My Girlfriend Is An Alien',
|
||||||
'episode': 'Episode 1',
|
'tags': 'count:31',
|
||||||
},
|
'thumbnail': r're:https?://.+',
|
||||||
'params': {
|
'timestamp': 1732435849,
|
||||||
'format': 'bv',
|
'upload_date': '20241124',
|
||||||
'skip_download': True,
|
'view_count': int,
|
||||||
},
|
},
|
||||||
|
'params': {'skip_download': True},
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://www.mxplayer.in/movie/watch-knock-knock-hindi-dubbed-movie-online-b9fa28df3bfb8758874735bbd7d2655a?watch=true',
|
# show, mxplay, NFSW
|
||||||
|
'url': 'https://www.mxplayer.in/show/watch-miya-biwi-aur-murder/season-1/episode-1-online-ca17972f052449de6633129ddd7db90b',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'b9fa28df3bfb8758874735bbd7d2655a',
|
'id': 'ca17972f052449de6633129ddd7db90b',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Episode 1',
|
||||||
|
'age_limit': 18,
|
||||||
|
'cast': 'count:10',
|
||||||
|
'creators': 'count:1',
|
||||||
|
'description': 'md5:bd8e55b81094e55026eb0c4f702c32cc',
|
||||||
'display_id': 'episode-1-online',
|
'display_id': 'episode-1-online',
|
||||||
'ext': 'mp4',
|
|
||||||
'title': 'Knock Knock (Hindi Dubbed)',
|
|
||||||
'description': 'md5:4160f2dfc3b87c524261366f6b736329',
|
|
||||||
'duration': 5970,
|
|
||||||
},
|
|
||||||
'params': {
|
|
||||||
'format': 'bv',
|
|
||||||
'skip_download': True,
|
|
||||||
},
|
|
||||||
'skip': 'No longer available',
|
|
||||||
}, {
|
|
||||||
'url': 'https://www.mxplayer.in/show/watch-shaitaan/season-1/the-infamous-taxi-gang-of-meerut-online-45055d5bcff169ad48f2ad7552a83d6c',
|
|
||||||
'info_dict': {
|
|
||||||
'id': '45055d5bcff169ad48f2ad7552a83d6c',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'title': 'The infamous taxi gang of Meerut',
|
|
||||||
'description': 'md5:033a0a7e3fd147be4fb7e07a01a3dc28',
|
|
||||||
'season_number': 1,
|
|
||||||
'episode_number': 1,
|
|
||||||
'duration': 2332,
|
|
||||||
'season': 'Season 1',
|
|
||||||
'series': 'Shaitaan',
|
|
||||||
'episode': 'Episode 1',
|
'episode': 'Episode 1',
|
||||||
},
|
|
||||||
'params': {
|
|
||||||
'format': 'best',
|
|
||||||
'skip_download': True,
|
|
||||||
},
|
|
||||||
'skip': 'No longer available.',
|
|
||||||
}, {
|
|
||||||
'url': 'https://www.mxplayer.in/show/watch-aashram/chapter-1/duh-swapna-online-d445579792b0135598ba1bc9088a84cb',
|
|
||||||
'info_dict': {
|
|
||||||
'id': 'd445579792b0135598ba1bc9088a84cb',
|
|
||||||
'display_id': 'duh-swapna-online',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'title': 'Duh Swapna',
|
|
||||||
'description': 'md5:35ff39c4bdac403c53be1e16a04192d8',
|
|
||||||
'season_number': 1,
|
|
||||||
'episode_number': 3,
|
|
||||||
'duration': 2568,
|
|
||||||
'season': 'Season 1',
|
|
||||||
'series': 'Ek Badnaam Aashram',
|
|
||||||
'episode': 'Episode 3',
|
|
||||||
},
|
|
||||||
'params': {
|
|
||||||
'format': 'bv',
|
|
||||||
'skip_download': True,
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
'url': 'https://www.mxplayer.in/show/watch-dangerous/season-1/chapter-1-online-5a351b4f9fb69436f6bd6ae3a1a75292',
|
|
||||||
'info_dict': {
|
|
||||||
'id': '5a351b4f9fb69436f6bd6ae3a1a75292',
|
|
||||||
'display_id': 'chapter-1-online',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'title': 'Chapter 1',
|
|
||||||
'description': 'md5:233886b8598bc91648ac098abe1d288f',
|
|
||||||
'season_number': 1,
|
|
||||||
'episode_number': 1,
|
'episode_number': 1,
|
||||||
'duration': 1305,
|
'duration': 1348,
|
||||||
|
'genres': 'count:4',
|
||||||
|
'release_date': '20220630',
|
||||||
|
'release_timestamp': 1656613800,
|
||||||
'season': 'Season 1',
|
'season': 'Season 1',
|
||||||
'series': 'Dangerous',
|
'season_number': 1,
|
||||||
'episode': 'Episode 1',
|
'series': 'Miya Biwi Aur Murder',
|
||||||
},
|
'tags': 'count:12',
|
||||||
'params': {
|
'thumbnail': r're:https?://.+',
|
||||||
'format': 'bv',
|
'timestamp': 1656581738,
|
||||||
'skip_download': True,
|
'upload_date': '20220630',
|
||||||
|
'view_count': int,
|
||||||
},
|
},
|
||||||
|
'params': {'skip_download': True},
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://www.mxplayer.in/movie/watch-the-attacks-of-2611-movie-online-0452f0d80226c398d63ce7e3ea40fa2d',
|
# shorts, mxplay
|
||||||
|
'url': 'https://www.mxplayer.in/shorts/watch-official-trailer-made-in-india-a-titan-story-online-c36b0ad18e56f1da0743ad826fe9e14b',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '0452f0d80226c398d63ce7e3ea40fa2d',
|
'id': 'c36b0ad18e56f1da0743ad826fe9e14b',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'title': 'The Attacks of 26/11',
|
'title': 'Official Trailer | Made In India: A Titan Story',
|
||||||
'description': 'md5:689bacd29e97b3f31eaf519eb14127e5',
|
'age_limit': 13,
|
||||||
'duration': 6085,
|
'description': 'md5:37924586e54d6e86a6e991048aec5442',
|
||||||
|
'display_id': 'watch-official-trailer-made-in-india-a-titan-story-online',
|
||||||
|
'episode': 'Episode 0',
|
||||||
|
'episode_number': 0,
|
||||||
|
'duration': 125,
|
||||||
|
'genres': 'count:2',
|
||||||
|
'release_date': '20260525',
|
||||||
|
'release_timestamp': 1779733800,
|
||||||
|
'tags': 'count:3',
|
||||||
|
'thumbnail': r're:https?://.+',
|
||||||
|
'view_count': int,
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {'skip_download': True},
|
||||||
'format': 'best',
|
|
||||||
'skip_download': True,
|
|
||||||
},
|
|
||||||
'skip': 'No longer available. Cannot be played on browser',
|
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://www.mxplayer.in/movie/watch-kitne-door-kitne-paas-movie-online-a9e9c76c566205955f70d8b2cb88a6a2',
|
# movie, mxplay
|
||||||
|
'url': 'https://www.mxplayer.in/movie/watch-thiruchitrambalam-movie-online-fbba39c1fdf8b14cffcea05f0635da84',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'a9e9c76c566205955f70d8b2cb88a6a2',
|
'id': 'fbba39c1fdf8b14cffcea05f0635da84',
|
||||||
'display_id': 'watch-kitne-door-kitne-paas-movie-online',
|
|
||||||
'title': 'Kitne Door Kitne Paas',
|
|
||||||
'duration': 8458,
|
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'description': 'md5:fb825f3c542513088024dcafef0921b4',
|
'title': 'Thiruchitrambalam',
|
||||||
|
'age_limit': 13,
|
||||||
|
'cast': 'count:7',
|
||||||
|
'creators': 'count:1',
|
||||||
|
'description': 'md5:66c24674756099adbecd1e56cfa9d6e6',
|
||||||
|
'display_id': 'watch-thiruchitrambalam-movie-online',
|
||||||
|
'episode': 'Episode 0',
|
||||||
|
'episode_number': 0,
|
||||||
|
'duration': 7894,
|
||||||
|
'genres': 'count:3',
|
||||||
|
'release_date': '20220817',
|
||||||
|
'release_timestamp': 1660761000,
|
||||||
|
'tags': 'count:8',
|
||||||
|
'thumbnail': r're:https?://.+',
|
||||||
|
'timestamp': 1759808876,
|
||||||
|
'upload_date': '20251007',
|
||||||
|
'view_count': int,
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {'skip_download': True},
|
||||||
'format': 'bv',
|
|
||||||
'skip_download': True,
|
|
||||||
},
|
|
||||||
'skip': 'video removed',
|
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://www.mxplayer.in/show/watch-ek-thi-begum-hindi/season-2/game-of-power-online-5e5305c28f1409847cdc4520b6ad77cf',
|
# movie, thirdParty
|
||||||
|
'url': 'https://www.mxplayer.in/movie/watch-drishyam-2-hindi-movie-online-2c580670b2104d156e2d9a3fd42a413e',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '5e5305c28f1409847cdc4520b6ad77cf',
|
'id': '2c580670b2104d156e2d9a3fd42a413e',
|
||||||
'display_id': 'game-of-power-online',
|
|
||||||
'title': 'Game Of Power',
|
|
||||||
'duration': 1851,
|
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'description': 'md5:1d0948d2a5312d7013792d53542407f9',
|
'title': 'Drishyam 2 (Hindi)',
|
||||||
'series': 'Ek Thi Begum',
|
'age_limit': 13,
|
||||||
'season': 'Season 2',
|
'cast': 'count:10',
|
||||||
'season_number': 2,
|
'creators': 'count:1',
|
||||||
'episode': 'Episode 2',
|
'description': 'md5:b4f803532ea357b78ca183d0829eca2a',
|
||||||
'episode_number': 2,
|
'display_id': 'watch-drishyam-2-hindi-movie-online',
|
||||||
|
'episode': 'Episode 0',
|
||||||
|
'episode_number': 0,
|
||||||
|
'duration': 8399,
|
||||||
|
'genres': 'count:3',
|
||||||
|
'release_date': '20221117',
|
||||||
|
'release_timestamp': 1668709800,
|
||||||
|
'tags': 'count:4',
|
||||||
|
'thumbnail': r're:https?://.+',
|
||||||
|
'timestamp': 1736823124,
|
||||||
|
'upload_date': '20250114',
|
||||||
|
'view_count': int,
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {'skip_download': True},
|
||||||
'format': 'bv',
|
|
||||||
'skip_download': True,
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
'url': 'https://www.mxplayer.in/movie/watch-deewane-huye-paagal-movie-online-4f9175c40a11c3994182a65afdd37ec6?watch=true',
|
|
||||||
'info_dict': {
|
|
||||||
'id': '4f9175c40a11c3994182a65afdd37ec6',
|
|
||||||
'display_id': 'watch-deewane-huye-paagal-movie-online',
|
|
||||||
'title': 'Deewane Huye Paagal',
|
|
||||||
'duration': 9037,
|
|
||||||
'ext': 'mp4',
|
|
||||||
'description': 'md5:d17bd5c651016c4ed2e6f8a4ace15534',
|
|
||||||
},
|
|
||||||
'params': {'skip_download': 'm3u8'},
|
|
||||||
'skip': 'video removed',
|
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
video_type, display_id, video_id = self._match_valid_url(url).group('type', 'display_id', 'id')
|
display_id, video_id = self._match_valid_url(url).group('display_id', 'id')
|
||||||
if 'show' in video_type:
|
mxs = self._extract_mxs(url, video_id)
|
||||||
video_type = 'episode'
|
|
||||||
|
|
||||||
data_json = self._download_json(
|
config = traverse_obj(mxs, ('config', {dict}))
|
||||||
f'https://api.mxplayer.in/v1/web/detail/video?type={video_type}&id={video_id}', display_id)
|
cdn_base = traverse_obj(config, (
|
||||||
|
'videoCdnBaseUrl', {url_or_none}, {lambda x: f'{x.rstrip("/")}/'}))
|
||||||
|
img_base = traverse_obj(config, (
|
||||||
|
'imageBaseUrl', {url_or_none}, {lambda x: f'{x.rstrip("/")}/'}))
|
||||||
|
|
||||||
|
entities = traverse_obj(mxs, ('entities', video_id, {dict}))
|
||||||
|
stream = traverse_obj(entities, ('stream', {dict}))
|
||||||
|
if traverse_obj(stream, ('drmProtect', {bool})):
|
||||||
|
self.report_drm(video_id)
|
||||||
|
|
||||||
formats, subtitles = [], {}
|
formats, subtitles = [], {}
|
||||||
m3u8_url = urljoin('https://llvod.mxplay.com/', traverse_obj(
|
for manifest_url in traverse_obj(stream, ((
|
||||||
data_json, ('stream', (('thirdParty', 'hlsUrl'), ('hls', 'high'))), get_all=False))
|
('thirdParty', ..., {url_or_none}),
|
||||||
if m3u8_url:
|
((None, 'mxplay'), ('hls', 'dash'), 'high', {urljoin(cdn_base)}),
|
||||||
formats, subtitles = self._extract_m3u8_formats_and_subtitles(m3u8_url, display_id, 'mp4', fatal=False)
|
), all, {orderedSet})):
|
||||||
mpd_url = urljoin('https://llvod.mxplay.com/', traverse_obj(
|
ext = determine_ext(manifest_url)
|
||||||
data_json, ('stream', (('thirdParty', 'dashUrl'), ('dash', 'high'))), get_all=False))
|
if ext == 'm3u8':
|
||||||
if mpd_url:
|
fmts, subs = self._extract_m3u8_formats_and_subtitles(
|
||||||
fmts, subs = self._extract_mpd_formats_and_subtitles(mpd_url, display_id, fatal=False)
|
manifest_url, video_id, 'mp4', m3u8_id='hls', fatal=False)
|
||||||
|
elif ext == 'mpd':
|
||||||
|
fmts, subs = self._extract_mpd_formats_and_subtitles(
|
||||||
|
manifest_url, video_id, mpd_id='dash', fatal=False)
|
||||||
|
for fmt in fmts:
|
||||||
|
if tbr := traverse_obj(fmt, ('tbr', {float_or_none})):
|
||||||
|
fmt['tbr'] = tbr / 4.2
|
||||||
|
else:
|
||||||
|
self.report_warning(f'Unsupported stream type: {ext}')
|
||||||
|
continue
|
||||||
|
|
||||||
formats.extend(fmts)
|
formats.extend(fmts)
|
||||||
self._merge_subtitles(subs, target=subtitles)
|
self._merge_subtitles(subs, target=subtitles)
|
||||||
|
self._remove_duplicate_formats(formats)
|
||||||
|
|
||||||
season = traverse_obj(data_json, ('container', 'title'))
|
|
||||||
return {
|
return {
|
||||||
'id': video_id,
|
'id': video_id,
|
||||||
'title': data_json.get('title'),
|
'display_id': display_id,
|
||||||
'formats': formats,
|
'formats': formats,
|
||||||
'subtitles': subtitles,
|
'subtitles': subtitles,
|
||||||
'display_id': display_id,
|
**traverse_obj(entities, {
|
||||||
'duration': data_json.get('duration'),
|
'title': ('title', {clean_html}, filter),
|
||||||
'series': traverse_obj(data_json, ('container', 'container', 'title')),
|
'age_limit': ('rating', {int_or_none}),
|
||||||
'description': data_json.get('description'),
|
'description': ('description', {clean_html}, filter),
|
||||||
'season': season,
|
'duration': ('duration', {int_or_none}),
|
||||||
'season_number': int_or_none(
|
'episode_number': ('sequence', {int_or_none}),
|
||||||
self._search_regex(r'Season (\d+)', season, 'Season Number', default=None)),
|
'genres': ('genres', ..., {clean_html}, filter, all, filter),
|
||||||
'episode_number': data_json.get('sequence') or None,
|
'release_timestamp': ('releaseDate', {parse_iso8601}),
|
||||||
|
'tags': ('tags', ..., 'name', {clean_html}, filter, all, filter),
|
||||||
|
'thumbnails': (('imageInfo', 'titleContentImageInfo'), ..., {
|
||||||
|
'id': ('type', {str_or_none}),
|
||||||
|
'height': ('height', {int_or_none}),
|
||||||
|
'url': ('url', {urljoin(img_base)}),
|
||||||
|
'width': ('width', {int_or_none}),
|
||||||
|
}),
|
||||||
|
'timestamp': ('publishTime', {parse_iso8601}),
|
||||||
|
'view_count': ('viewCount', {int_or_none}),
|
||||||
|
}),
|
||||||
|
**traverse_obj(entities, ('container', {
|
||||||
|
'season': ('title', {clean_html}, filter),
|
||||||
|
'season_number': ('sequence', {int_or_none}),
|
||||||
|
'series': ('container', 'title', {clean_html}, filter),
|
||||||
|
})),
|
||||||
|
**traverse_obj(entities, ('contributors', {
|
||||||
|
'cast': (lambda _, v: v['type'] == 'actor', 'name', {clean_html}, filter, all, filter),
|
||||||
|
'creators': (lambda _, v: v['type'] == 'director', 'name', {clean_html}, filter, all, filter),
|
||||||
|
})),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class MxplayerShowIE(InfoExtractor):
|
class MxplayerSeasonIE(MxplayerBaseIE):
|
||||||
_VALID_URL = r'https?://(?:www\.)?mxplayer\.in/show/(?P<display_id>[-\w]+)-(?P<id>\w+)/?(?:$|[#?])'
|
IE_NAME = 'mxplayer:season'
|
||||||
|
|
||||||
|
_PAGE_SIZE = 10
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?mxplayer\.in/show/[\w-]+/seasons/[\w-]+-(?P<id>[0-9a-f]{32})(?:[/?#]|$)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
'url': 'https://www.mxplayer.in/show/watch-chakravartin-ashoka-samrat-series-online-a8f44e3cc0814b5601d17772cedf5417',
|
'url': 'https://www.mxplayer.in/show/watch-campus-beats/seasons/season-4-925794ae840c597b3c36f2d8f2f138b8',
|
||||||
'playlist_mincount': 440,
|
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'a8f44e3cc0814b5601d17772cedf5417',
|
'id': '925794ae840c597b3c36f2d8f2f138b8',
|
||||||
'title': 'Watch Chakravartin Ashoka Samrat Series Online',
|
'title': 'Campus Beats - Season 4',
|
||||||
},
|
},
|
||||||
|
'playlist_mincount': 15,
|
||||||
}]
|
}]
|
||||||
|
|
||||||
_API_SHOW_URL = 'https://api.mxplayer.in/v1/web/detail/tab/tvshowseasons?type=tv_show&id={}&device-density=2&platform=com.mxplay.desktop&content-languages=hi,en'
|
def _entries(self, entities, season_id):
|
||||||
_API_EPISODES_URL = 'https://api.mxplayer.in/v1/web/detail/tab/tvshowepisodes?type=season&id={}&device-density=1&platform=com.mxplay.desktop&content-languages=hi,en&{}'
|
query = None
|
||||||
|
api_url = traverse_obj(entities, (
|
||||||
|
'tabs', ..., 'api', {urljoin('https://api.mxplayer.in/v1/web/')}, any))
|
||||||
|
|
||||||
def _entries(self, show_id):
|
for page in itertools.count(1):
|
||||||
show_json = self._download_json(
|
season_data = self._download_json(
|
||||||
self._API_SHOW_URL.format(show_id),
|
api_url, season_id, f'Downloading Page {page}', query=query)
|
||||||
video_id=show_id, headers={'Referer': 'https://mxplayer.in'})
|
|
||||||
page_num = 0
|
share_urls = traverse_obj(season_data, (
|
||||||
for season in show_json.get('items') or []:
|
'items', ..., 'shareUrl', {urljoin(f'{self._BASE_URL}/')}))
|
||||||
season_id = try_get(season, lambda x: x['id'], str)
|
for share_url in share_urls:
|
||||||
next_url = ''
|
yield self.url_result(share_url, MxplayerRedirectIE)
|
||||||
while next_url is not None:
|
if len(share_urls) < self._PAGE_SIZE:
|
||||||
page_num += 1
|
break
|
||||||
season_json = self._download_json(
|
|
||||||
self._API_EPISODES_URL.format(season_id, next_url),
|
query = traverse_obj(season_data, ('next', {urllib.parse.parse_qs}))
|
||||||
video_id=season_id,
|
if not query:
|
||||||
headers={'Referer': 'https://mxplayer.in'},
|
break
|
||||||
note=f'Downloading JSON metadata page {page_num}')
|
|
||||||
for episode in season_json.get('items') or []:
|
|
||||||
video_url = episode['webUrl']
|
|
||||||
yield self.url_result(
|
|
||||||
f'https://mxplayer.in{video_url}',
|
|
||||||
ie=MxplayerIE.ie_key(), video_id=video_url.split('-')[-1])
|
|
||||||
next_url = season_json.get('next')
|
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
display_id, show_id = self._match_valid_url(url).groups()
|
season_id = self._match_id(url)
|
||||||
|
mxs = self._extract_mxs(url, season_id)
|
||||||
|
|
||||||
|
entities = traverse_obj(mxs, ('entities', season_id, {dict}))
|
||||||
|
series_title = traverse_obj(entities, ('container', 'title', {clean_html}))
|
||||||
|
season_title = traverse_obj(entities, ('title', {clean_html}))
|
||||||
|
|
||||||
return self.playlist_result(
|
return self.playlist_result(
|
||||||
self._entries(show_id), playlist_id=show_id,
|
self._entries(entities, season_id),
|
||||||
playlist_title=display_id.replace('-', ' ').title())
|
season_id, join_nonempty(series_title, season_title, delim=' - '))
|
||||||
|
|
||||||
|
|
||||||
|
class MxplayerShowIE(MxplayerBaseIE):
|
||||||
|
IE_NAME = 'mxplayer:show'
|
||||||
|
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?mxplayer\.in/show/[\w-]+-(?P<id>[0-9a-f]{32})(?:[/?#]|$)'
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://www.mxplayer.in/show/watch-bhaukaal-series-online-775ad3b682fde6a608559a60986b230d',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '775ad3b682fde6a608559a60986b230d',
|
||||||
|
'title': 'Bhaukaal',
|
||||||
|
},
|
||||||
|
'playlist_mincount': 2,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _entries(self, entities):
|
||||||
|
for season_id in traverse_obj(entities, (
|
||||||
|
'tabs', ..., 'containers', ..., 'id', {str_or_none},
|
||||||
|
)):
|
||||||
|
yield self.url_result(
|
||||||
|
f'{self._BASE_URL}/detail/season/{season_id}', MxplayerRedirectIE)
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
show_id = self._match_id(url)
|
||||||
|
mxs = self._extract_mxs(url, show_id)
|
||||||
|
|
||||||
|
entities = traverse_obj(mxs, ('entities', show_id, {dict}))
|
||||||
|
|
||||||
|
return self.playlist_result(
|
||||||
|
self._entries(entities), show_id,
|
||||||
|
traverse_obj(entities, ('title', {clean_html}, filter)))
|
||||||
|
|
||||||
|
|
||||||
|
class MxplayerRedirectIE(MxplayerBaseIE):
|
||||||
|
IE_NAME = 'mxplayer:redirect'
|
||||||
|
IE_DESC = False
|
||||||
|
|
||||||
|
_IE_MAP = {
|
||||||
|
'episode': MxplayerIE,
|
||||||
|
'movie': MxplayerIE,
|
||||||
|
'season': MxplayerSeasonIE,
|
||||||
|
'shorts': MxplayerIE,
|
||||||
|
'tvshow': MxplayerShowIE,
|
||||||
|
}
|
||||||
|
_VALID_URL = rf'https?://(?:www\.)?mxplayer\.in/detail/(?P<type>{"|".join(_IE_MAP)})/(?P<id>[0-9a-f]{{32}})(?:[/?#]|$)'
|
||||||
|
_TESTS = [{
|
||||||
|
# episode
|
||||||
|
# https://www.mxplayer.in/show/watch-that-time-i-got-reincarnated-as-a-slime/season-2/megiddo-online-3eda0b3baf27f2892d3fca2fd650fb95
|
||||||
|
'url': 'https://www.mxplayer.in/detail/episode/3eda0b3baf27f2892d3fca2fd650fb95',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '3eda0b3baf27f2892d3fca2fd650fb95',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Megiddo',
|
||||||
|
'age_limit': 16,
|
||||||
|
'cast': 'count:6',
|
||||||
|
'creators': 'count:11',
|
||||||
|
'description': 'md5:f4ac8210c2e7bdcaab3b34636cf754b4',
|
||||||
|
'display_id': 'megiddo-online',
|
||||||
|
'episode': 'Episode 10',
|
||||||
|
'episode_number': 10,
|
||||||
|
'duration': 1427,
|
||||||
|
'genres': 'count:6',
|
||||||
|
'release_date': '20210315',
|
||||||
|
'release_timestamp': 1615833000,
|
||||||
|
'season': 'Season 2',
|
||||||
|
'season_number': 2,
|
||||||
|
'series': 'That Time I Got Reincarnated As A Slime',
|
||||||
|
'tags': 'count:21',
|
||||||
|
'thumbnail': r're:https?://.+',
|
||||||
|
'timestamp': 1774843170,
|
||||||
|
'upload_date': '20260330',
|
||||||
|
'view_count': int,
|
||||||
|
},
|
||||||
|
'params': {'skip_download': True},
|
||||||
|
}, {
|
||||||
|
# movie
|
||||||
|
# https://www.mxplayer.in/movie/watch-sardar-udham-movie-online-0c586053d7ac563ca911ddfe08cf922f
|
||||||
|
'url': 'https://www.mxplayer.in/detail/movie/0c586053d7ac563ca911ddfe08cf922f',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '0c586053d7ac563ca911ddfe08cf922f',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Sardar Udham',
|
||||||
|
'age_limit': 13,
|
||||||
|
'cast': 'count:6',
|
||||||
|
'creators': 'count:1',
|
||||||
|
'description': 'md5:58f0d90f802898aaf328ac2942e878e5',
|
||||||
|
'display_id': 'watch-sardar-udham-movie-online',
|
||||||
|
'episode': 'Episode 0',
|
||||||
|
'episode_number': 0,
|
||||||
|
'duration': 9770,
|
||||||
|
'genres': 'count:3',
|
||||||
|
'release_date': '20211015',
|
||||||
|
'release_timestamp': 1634322600,
|
||||||
|
'tags': 'count:4',
|
||||||
|
'thumbnail': r're:https?://.+',
|
||||||
|
'timestamp': 1739952608,
|
||||||
|
'upload_date': '20250219',
|
||||||
|
'view_count': int,
|
||||||
|
},
|
||||||
|
'params': {'skip_download': True},
|
||||||
|
}, {
|
||||||
|
# shorts
|
||||||
|
# https://www.mxplayer.in/shorts/watch-official-trailer-lafangey-sapne-dosti-duniya-online-55c77863e406c7b71f6bab28f7fbbe85
|
||||||
|
'url': 'https://www.mxplayer.in/detail/shorts/55c77863e406c7b71f6bab28f7fbbe85',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '55c77863e406c7b71f6bab28f7fbbe85',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Official Trailer| Lafangey - Sapne, Dosti, Duniya',
|
||||||
|
'age_limit': 18,
|
||||||
|
'description': 'md5:623d53e4543155dd732e96587711481c',
|
||||||
|
'display_id': 'watch-official-trailer-lafangey-sapne-dosti-duniya-online',
|
||||||
|
'episode': 'Episode 0',
|
||||||
|
'episode_number': 0,
|
||||||
|
'duration': 118,
|
||||||
|
'genres': 'count:2',
|
||||||
|
'release_date': '20250601',
|
||||||
|
'release_timestamp': 1748802600,
|
||||||
|
'tags': 'count:3',
|
||||||
|
'thumbnail': r're:https?://.+',
|
||||||
|
'view_count': int,
|
||||||
|
},
|
||||||
|
'params': {'skip_download': True},
|
||||||
|
}, {
|
||||||
|
# season
|
||||||
|
# https://www.mxplayer.in/show/watch-demon-slayer/seasons/season-3-41a6d7432bea96f2f0d06a625b39d9b1
|
||||||
|
'url': 'https://www.mxplayer.in/detail/season/41a6d7432bea96f2f0d06a625b39d9b1',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '41a6d7432bea96f2f0d06a625b39d9b1',
|
||||||
|
'title': 'Demon Slayer - Season 3',
|
||||||
|
},
|
||||||
|
'playlist_mincount': 11,
|
||||||
|
}, {
|
||||||
|
# tvshow
|
||||||
|
# https://www.mxplayer.in/show/watch-my-hero-academia-series-online-e7c68fb3951e61986af073a719c2ee4f
|
||||||
|
'url': 'https://www.mxplayer.in/detail/tvshow/e7c68fb3951e61986af073a719c2ee4f',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'e7c68fb3951e61986af073a719c2ee4f',
|
||||||
|
'title': 'My Hero Academia',
|
||||||
|
},
|
||||||
|
'playlist_mincount': 4,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
redirect_type, redirect_id = self._match_valid_url(url).group('type', 'id')
|
||||||
|
ie = self._IE_MAP[redirect_type]
|
||||||
|
|
||||||
|
detail = self._download_json(
|
||||||
|
'https://seo.mxplayer.in/v1/api/seo/get-url-details',
|
||||||
|
redirect_id, query={'url': urllib.parse.urlsplit(url).path})
|
||||||
|
|
||||||
|
if redirect_url := traverse_obj(detail, (
|
||||||
|
'data', 'redirect', {urljoin(f'{self._BASE_URL}/')},
|
||||||
|
)):
|
||||||
|
if self.suitable(redirect_url):
|
||||||
|
raise UnsupportedError(redirect_url)
|
||||||
|
return self.url_result(redirect_url, ie)
|
||||||
|
|
||||||
|
raise ExtractorError('Unable to resolve redirect URL')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user