diff --git a/yt_dlp/extractor/_extractors.py b/yt_dlp/extractor/_extractors.py index ff441d5ee..c03d4b3f5 100644 --- a/yt_dlp/extractor/_extractors.py +++ b/yt_dlp/extractor/_extractors.py @@ -256,6 +256,7 @@ from .bilibili import ( BilibiliCheeseIE, BilibiliCheeseSeasonIE, BilibiliCollectionListIE, + BiliBiliDynamicIE, BilibiliFavoritesListIE, BiliBiliIE, BiliBiliPlayerIE, diff --git a/yt_dlp/extractor/bilibili.py b/yt_dlp/extractor/bilibili.py index 2db951a60..33d9d92a0 100644 --- a/yt_dlp/extractor/bilibili.py +++ b/yt_dlp/extractor/bilibili.py @@ -32,6 +32,7 @@ from ..utils import ( parse_qs, parse_resolution, qualities, + sanitize_url, smuggle_url, srt_subtitles_timecode, str_or_none, @@ -1861,6 +1862,47 @@ class BiliBiliPlayerIE(InfoExtractor): ie=BiliBiliIE.ie_key(), video_id=video_id) +class BiliBiliDynamicIE(InfoExtractor): + _VALID_URL = r'https?://(?:t\.bilibili\.com|(?:www\.)?bilibili\.com/opus)/(?P\d+)' + _TESTS = [{ + 'url': 'https://t.bilibili.com/998134289197432852', + 'info_dict': { + 'id': 'BV1TAmBYVEJr', + 'ext': 'mp4', + 'uploader_id': '1192648858', + 'comment_count': int, + '_old_archive_ids': ['bilibili 113457567568273_part1'], + 'thumbnail': 'http://i2.hdslb.com/bfs/archive/50091efd965d9f13ff6814f7ad374f90ab21e77d.jpg', + 'duration': 929.238, + 'upload_date': '20241110', + 'uploader': '何同学工作室', + 'like_count': int, + 'view_count': int, + 'title': '美国小朋友就玩这个?!何同学工作室11月开箱', + 'description': '本期产品信息:\n机器狗\n气味模拟器\nCloudboom Strike LS\n无弦吉他\n蓝牙磁带音箱\n神奇画板', + 'timestamp': 1731232800, + 'tags': list, + 'chapters': list, + }, + }] + + def _real_extract(self, url): + post_id = self._match_id(url) + # Without the newer chrome UA, the API will return an error (-352) + post_data = self._download_json( + 'https://api.bilibili.com/x/polymer/web-dynamic/v1/detail', post_id, + query={'id': post_id}, headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', + }) + video_url = traverse_obj(post_data, ( + 'data', 'item', (None, 'orig'), 'modules', 'module_dynamic', + (('major', ('archive', 'pgc')), ('additional', ('reserve', 'common'))), + 'jump_url', {url_or_none}, any, {sanitize_url})) + if not video_url or (self.suitable(video_url) and post_id == self._match_id(video_url)): + raise ExtractorError('No valid video URL found', expected=True) + return self.url_result(video_url) + + class BiliIntlBaseIE(InfoExtractor): _API_URL = 'https://api.bilibili.tv/intl/gateway' _NETRC_MACHINE = 'biliintl'