diff options
Diffstat (limited to 'youtube_dl')
-rw-r--r-- | youtube_dl/extractor/bilibili.py | 74 | ||||
-rw-r--r-- | youtube_dl/extractor/niconico.py | 17 | ||||
-rw-r--r-- | youtube_dl/extractor/veehd.py | 36 |
3 files changed, 97 insertions, 30 deletions
diff --git a/youtube_dl/extractor/bilibili.py b/youtube_dl/extractor/bilibili.py index 904d9a8b4..7ca835e31 100644 --- a/youtube_dl/extractor/bilibili.py +++ b/youtube_dl/extractor/bilibili.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import re +import itertools from .common import InfoExtractor from ..utils import ( @@ -14,18 +15,25 @@ from ..utils import ( class BiliBiliIE(InfoExtractor): _VALID_URL = r'http://www\.bilibili\.(?:tv|com)/video/av(?P<id>[0-9]+)/' - _TEST = { + _TESTS = [{ 'url': 'http://www.bilibili.tv/video/av1074402/', 'md5': '2c301e4dab317596e837c3e7633e7d86', 'info_dict': { - 'id': '1074402', + 'id': '1074402_part1', 'ext': 'flv', 'title': '【金坷垃】金泡沫', 'duration': 308, 'upload_date': '20140420', 'thumbnail': 're:^https?://.+\.jpg', }, - } + }, { + 'url': 'http://www.bilibili.com/video/av1041170/', + 'info_dict': { + 'id': '1041170', + 'title': '【BD1080P】刀语【诸神&异域】', + }, + 'playlist_count': 9, + }] def _real_extract(self, url): video_id = self._match_id(url) @@ -57,19 +65,14 @@ class BiliBiliIE(InfoExtractor): cid = self._search_regex(r'cid=(\d+)', webpage, 'cid') + entries = [] + lq_doc = self._download_xml( 'http://interface.bilibili.com/v_cdn_play?appkey=1&cid=%s' % cid, video_id, note='Downloading LQ video info' ) - lq_durl = lq_doc.find('./durl') - formats = [{ - 'format_id': 'lq', - 'quality': 1, - 'url': lq_durl.find('./url').text, - 'filesize': int_or_none( - lq_durl.find('./size'), get_attr='text'), - }] + lq_durls = lq_doc.findall('./durl') hq_doc = self._download_xml( 'http://interface.bilibili.com/playurl?appkey=1&cid=%s' % cid, @@ -77,23 +80,44 @@ class BiliBiliIE(InfoExtractor): note='Downloading HQ video info', fatal=False, ) - if hq_doc is not False: - hq_durl = hq_doc.find('./durl') - formats.append({ - 'format_id': 'hq', - 'quality': 2, - 'ext': 'flv', - 'url': hq_durl.find('./url').text, + hq_durls = hq_doc.findall('./durl') if hq_doc is not False else itertools.repeat(None) + + assert len(lq_durls) == len(hq_durls) + + i = 1 + for lq_durl, hq_durl in zip(lq_durls, hq_durls): + formats = [{ + 'format_id': 'lq', + 'quality': 1, + 'url': lq_durl.find('./url').text, 'filesize': int_or_none( - hq_durl.find('./size'), get_attr='text'), + lq_durl.find('./size'), get_attr='text'), + }] + if hq_durl: + formats.append({ + 'format_id': 'hq', + 'quality': 2, + 'ext': 'flv', + 'url': hq_durl.find('./url').text, + 'filesize': int_or_none( + hq_durl.find('./size'), get_attr='text'), + }) + self._sort_formats(formats) + + entries.append({ + 'id': '%s_part%d' % (video_id, i), + 'title': title, + 'formats': formats, + 'duration': duration, + 'upload_date': upload_date, + 'thumbnail': thumbnail, }) - self._sort_formats(formats) + i += 1 + return { + '_type': 'multi_video', + 'entries': entries, 'id': video_id, - 'title': title, - 'formats': formats, - 'duration': duration, - 'upload_date': upload_date, - 'thumbnail': thumbnail, + 'title': title } diff --git a/youtube_dl/extractor/niconico.py b/youtube_dl/extractor/niconico.py index dd16d0042..3cecebf95 100644 --- a/youtube_dl/extractor/niconico.py +++ b/youtube_dl/extractor/niconico.py @@ -67,6 +67,18 @@ class NiconicoIE(InfoExtractor): 'timestamp': 1198527840, # timestamp field has different value if logged in 'duration': 304, }, + }, { + 'url': 'http://www.nicovideo.jp/watch/so22543406', + 'info_dict': { + 'id': '1388129933', + 'ext': 'mp4', + 'title': '【第1回】RADIOアニメロミックス ラブライブ!~のぞえりRadio Garden~', + 'description': 'md5:b27d224bb0ff53d3c8269e9f8b561cf1', + 'timestamp': 1388851200, + 'upload_date': '20140104', + 'uploader': 'アニメロチャンネル', + 'uploader_id': '312', + } }] _VALID_URL = r'https?://(?:www\.|secure\.)?nicovideo\.jp/watch/(?P<id>(?:[a-z]{2})?[0-9]+)' @@ -109,7 +121,10 @@ class NiconicoIE(InfoExtractor): # Get video webpage. We are not actually interested in it for normal # cases, but need the cookies in order to be able to download the # info webpage - webpage = self._download_webpage('http://www.nicovideo.jp/watch/' + video_id, video_id) + webpage, handle = self._download_webpage_handle( + 'http://www.nicovideo.jp/watch/' + video_id, video_id) + if video_id.startswith('so'): + video_id = self._match_id(handle.geturl()) video_info = self._download_xml( 'http://ext.nicovideo.jp/api/getthumbinfo/' + video_id, video_id, diff --git a/youtube_dl/extractor/veehd.py b/youtube_dl/extractor/veehd.py index 96353f525..7fdeb784d 100644 --- a/youtube_dl/extractor/veehd.py +++ b/youtube_dl/extractor/veehd.py @@ -17,7 +17,9 @@ from ..utils import ( class VeeHDIE(InfoExtractor): _VALID_URL = r'https?://veehd\.com/video/(?P<id>\d+)' - _TEST = { + # Seems VeeHD videos have multiple copies on several servers, all of + # whom have different MD5 checksums, so omit md5 field in all tests + _TESTS = [{ 'url': 'http://veehd.com/video/4639434_Solar-Sinter', 'info_dict': { 'id': '4639434', @@ -26,7 +28,26 @@ class VeeHDIE(InfoExtractor): 'uploader_id': 'VideoEyes', 'description': 'md5:46a840e8692ddbaffb5f81d9885cb457', }, - } + 'skip': 'Video deleted', + }, { + 'url': 'http://veehd.com/video/4905758_Elysian-Fields-Channeling', + 'info_dict': { + 'id': '4905758', + 'ext': 'mp4', + 'title': 'Elysian Fields - Channeling', + 'description': 'md5:360e4e95fdab58aefbea0f2a19e5604b', + 'uploader_id': 'spotted', + } + }, { + 'url': 'http://veehd.com/video/4665804_Tell-No-One-Ne-le-dis-a-personne-2006-French-EngSoftSubs-Re-Up', + 'info_dict': { + 'id': '4665804', + 'ext': 'avi', + 'title': 'Tell No One (Ne le dis a personne) 2006 French(EngSoftSubs) Re-Up', + 'description': 'md5:d660cca685549776f37165e9a10b60ba', + 'uploader_id': 'belial2549', + } + }] def _real_extract(self, url): video_id = self._match_id(url) @@ -48,13 +69,21 @@ class VeeHDIE(InfoExtractor): player_page = self._download_webpage( player_url, video_id, 'Downloading player page') + video_url = None + config_json = self._search_regex( r'value=\'config=({.+?})\'', player_page, 'config json', default=None) if config_json: config = json.loads(config_json) video_url = compat_urlparse.unquote(config['clip']['url']) - else: + + if not video_url: + video_url = self._html_search_regex( + r'<embed[^>]+type="video/divx"[^>]+src="([^"]+)"', + player_page, 'video url', default=None) + + if not video_url: iframe_src = self._search_regex( r'<iframe[^>]+src="/?([^"]+)"', player_page, 'iframe url') iframe_url = 'http://veehd.com/%s' % iframe_src @@ -82,7 +111,6 @@ class VeeHDIE(InfoExtractor): 'id': video_id, 'title': title, 'url': video_url, - 'ext': 'mp4', 'uploader_id': uploader_id, 'thumbnail': thumbnail, 'description': description, |