Compare commits
22 Commits
2013.06.30
...
2013.06.33
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81b42336ad | ||
|
|
c6c1974672 | ||
|
|
a545d1d262 | ||
|
|
037fcd0047 | ||
|
|
318452bc0c | ||
|
|
d746cd88c2 | ||
|
|
9c42603b5a | ||
|
|
ea93cce4f6 | ||
|
|
f4daa18152 | ||
|
|
9caa687d81 | ||
|
|
3b58c6fb54 | ||
|
|
5926c10690 | ||
|
|
df725153d2 | ||
|
|
d662896090 | ||
|
|
db241e8645 | ||
|
|
ead28ff30a | ||
|
|
515d7a5e73 | ||
|
|
14fbdc9cdd | ||
|
|
98bcd2834a | ||
|
|
f7ab6cbe16 | ||
|
|
28ef06f7c2 | ||
|
|
d18596baf4 |
@@ -130,6 +130,7 @@ which means you can modify it, redistribute it or use it however you like.
|
||||
-u, --username USERNAME account username
|
||||
-p, --password PASSWORD account password
|
||||
-n, --netrc use .netrc authentication data
|
||||
--video-password PASSWORD video password (vimeo only)
|
||||
|
||||
## Post-processing Options:
|
||||
-x, --extract-audio convert video files to audio-only files (requires
|
||||
|
||||
@@ -69,7 +69,9 @@ git checkout HEAD -- youtube-dl youtube-dl.exe
|
||||
|
||||
/bin/echo -e "\n### Signing and uploading the new binaries to youtube-dl.org..."
|
||||
for f in $RELEASE_FILES; do gpg --detach-sig "build/$version/$f"; done
|
||||
scp -r "build/$version" ytdl@youtube-dl.org:html/downloads/
|
||||
scp -r "build/$version" ytdl@yt-dl.org:html/tmp/
|
||||
ssh ytdl@yt-dl.org "mv html/tmp/$version html/downloads/"
|
||||
ssh ytdl@yt-dl.org "sh html/update_latest.sh $version"
|
||||
|
||||
/bin/echo -e "\n### Now switching to gh-pages..."
|
||||
git clone --branch gh-pages --single-branch . build/gh-pages
|
||||
|
||||
@@ -153,9 +153,11 @@ def generator(test_case):
|
||||
return test_template
|
||||
|
||||
### And add them to TestDownload
|
||||
for test_case in defs:
|
||||
for n, test_case in enumerate(defs):
|
||||
test_method = generator(test_case)
|
||||
test_method.__name__ = "test_{0}".format(test_case["name"])
|
||||
if getattr(TestDownload, test_method.__name__, False):
|
||||
test_method.__name__ = "test_{0}_{1}".format(test_case["name"], n)
|
||||
setattr(TestDownload, test_method.__name__, test_method)
|
||||
del test_method
|
||||
|
||||
|
||||
@@ -11,6 +11,32 @@
|
||||
"description": "test chars: \"'/\\ä↭𝕐\n\nThis is a test video for youtube-dl.\n\nFor more information, contact phihag@phihag.de ."
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Youtube",
|
||||
"url": "http://www.youtube.com/watch?v=1ltcDfZMA3U",
|
||||
"file": "1ltcDfZMA3U.flv",
|
||||
"note": "Test VEVO video (#897)",
|
||||
"info_dict": {
|
||||
"upload_date": "20070518",
|
||||
"title": "Maps - It Will Find You",
|
||||
"description": "Music video by Maps performing It Will Find You.",
|
||||
"uploader": "MuteUSA",
|
||||
"uploader_id": "MuteUSA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Youtube",
|
||||
"url": "http://www.youtube.com/watch?v=UxxajLWwzqY",
|
||||
"file": "UxxajLWwzqY.mp4",
|
||||
"note": "Test generic use_cipher_signature video (#897)",
|
||||
"info_dict": {
|
||||
"upload_date": "20120506",
|
||||
"title": "Icona Pop - I Love It (feat. Charli XCX) [OFFICIAL VIDEO]",
|
||||
"description": "md5:b085c9804f5ab69f4adea963a2dceb3c",
|
||||
"uploader": "IconaPop",
|
||||
"uploader_id": "IconaPop"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Dailymotion",
|
||||
"md5": "392c4b85a60a90dc4792da41ce3144eb",
|
||||
@@ -660,5 +686,14 @@
|
||||
"upload_date": "20130624",
|
||||
"uploader": "Hurts"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Tudou",
|
||||
"url": "http://www.tudou.com/listplay/zzdE77v6Mmo/2xN2duXMxmw.html",
|
||||
"file": "159447792.f4v",
|
||||
"md5": "ad7c358a01541e926a1e413612c6b10a",
|
||||
"info_dict": {
|
||||
"title": "卡马乔国足开大脚长传冲吊集锦"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -46,6 +46,7 @@ class YoutubeDL(object):
|
||||
|
||||
username: Username for authentication purposes.
|
||||
password: Password for authentication purposes.
|
||||
videopassword: Password for acces a video.
|
||||
usenetrc: Use netrc for authentication instead.
|
||||
verbose: Print additional info to stdout.
|
||||
quiet: Do not print messages to stdout.
|
||||
|
||||
@@ -25,6 +25,7 @@ __authors__ = (
|
||||
'M. Yasoob Ullah Khalid',
|
||||
'Julien Fraichard',
|
||||
'Johny Mo Swag',
|
||||
'Axel Noack',
|
||||
)
|
||||
|
||||
__license__ = 'Public Domain'
|
||||
@@ -172,6 +173,8 @@ def parseOpts(overrideArguments=None):
|
||||
dest='password', metavar='PASSWORD', help='account password')
|
||||
authentication.add_option('-n', '--netrc',
|
||||
action='store_true', dest='usenetrc', help='use .netrc authentication data', default=False)
|
||||
authentication.add_option('--video-password',
|
||||
dest='videopassword', metavar='PASSWORD', help='video password (vimeo only)')
|
||||
|
||||
|
||||
video_format.add_option('-f', '--format',
|
||||
@@ -421,7 +424,7 @@ def _real_main(argv=None):
|
||||
if opts.usenetrc and (opts.username is not None or opts.password is not None):
|
||||
parser.error(u'using .netrc conflicts with giving username/password')
|
||||
if opts.password is not None and opts.username is None:
|
||||
sys.stderr.write(u'WARNING: account username missing\n')
|
||||
parser.error(u' account username missing\n')
|
||||
if opts.outtmpl is not None and (opts.usetitle or opts.autonumber or opts.useid):
|
||||
parser.error(u'using output template conflicts with using title, video ID or auto number')
|
||||
if opts.usetitle and opts.useid:
|
||||
@@ -498,6 +501,7 @@ def _real_main(argv=None):
|
||||
'usenetrc': opts.usenetrc,
|
||||
'username': opts.username,
|
||||
'password': opts.password,
|
||||
'videopassword': opts.videopassword,
|
||||
'quiet': (opts.quiet or opts.geturl or opts.gettitle or opts.getid or opts.getthumbnail or opts.getdescription or opts.getfilename or opts.getformat),
|
||||
'forceurl': opts.geturl,
|
||||
'forcetitle': opts.gettitle,
|
||||
|
||||
@@ -4,8 +4,8 @@ from .arte import ArteTvIE
|
||||
from .bandcamp import BandcampIE
|
||||
from .bliptv import BlipTVIE, BlipTVUserIE
|
||||
from .breakcom import BreakIE
|
||||
from .comedycentral import ComedyCentralIE
|
||||
from .collegehumor import CollegeHumorIE
|
||||
from .comedycentral import ComedyCentralIE
|
||||
from .dailymotion import DailymotionIE
|
||||
from .depositfiles import DepositFilesIE
|
||||
from .eighttracks import EightTracksIE
|
||||
@@ -21,6 +21,7 @@ from .howcast import HowcastIE
|
||||
from .hypem import HypemIE
|
||||
from .ina import InaIE
|
||||
from .infoq import InfoQIE
|
||||
from .jukebox import JukeboxIE
|
||||
from .justintv import JustinTVIE
|
||||
from .keek import KeekIE
|
||||
from .liveleak import LiveLeakIE
|
||||
@@ -30,7 +31,6 @@ from .mtv import MTVIE
|
||||
from .myspass import MySpassIE
|
||||
from .myvideo import MyVideoIE
|
||||
from .nba import NBAIE
|
||||
from .statigram import StatigramIE
|
||||
from .photobucket import PhotobucketIE
|
||||
from .pornotube import PornotubeIE
|
||||
from .rbmaradio import RBMARadioIE
|
||||
@@ -38,9 +38,11 @@ from .redtube import RedTubeIE
|
||||
from .soundcloud import SoundcloudIE, SoundcloudSetIE
|
||||
from .spiegel import SpiegelIE
|
||||
from .stanfordoc import StanfordOpenClassroomIE
|
||||
from .statigram import StatigramIE
|
||||
from .steam import SteamIE
|
||||
from .teamcoco import TeamcocoIE
|
||||
from .ted import TEDIE
|
||||
from .tudou import TudouIE
|
||||
from .tumblr import TumblrIE
|
||||
from .ustream import UstreamIE
|
||||
from .vbox7 import Vbox7IE
|
||||
@@ -48,8 +50,8 @@ from .vevo import VevoIE
|
||||
from .vimeo import VimeoIE
|
||||
from .vine import VineIE
|
||||
from .worldstarhiphop import WorldStarHipHopIE
|
||||
from .xnxx import XNXXIE
|
||||
from .xhamster import XHamsterIE
|
||||
from .xnxx import XNXXIE
|
||||
from .xvideos import XVideosIE
|
||||
from .yahoo import YahooIE, YahooSearchIE
|
||||
from .youjizz import YouJizzIE
|
||||
@@ -58,6 +60,7 @@ from .youporn import YouPornIE
|
||||
from .youtube import YoutubeIE, YoutubePlaylistIE, YoutubeSearchIE, YoutubeUserIE, YoutubeChannelIE
|
||||
from .zdf import ZDFIE
|
||||
|
||||
|
||||
def gen_extractors():
|
||||
""" Return a list of an instance of every supported extractor.
|
||||
The order does matter; the first extractor matched is the one handling the URL.
|
||||
@@ -127,6 +130,8 @@ def gen_extractors():
|
||||
StatigramIE(),
|
||||
BreakIE(),
|
||||
VevoIE(),
|
||||
JukeboxIE(),
|
||||
TudouIE(),
|
||||
GenericIE()
|
||||
]
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ class InfoExtractor(object):
|
||||
raise ExtractorError(u'Unable to extract %s' % _name)
|
||||
else:
|
||||
self._downloader.report_warning(u'unable to extract %s; '
|
||||
u'please report this issue on GitHub.' % _name)
|
||||
u'please report this issue on http://yt-dl.org/bug' % _name)
|
||||
return None
|
||||
|
||||
def _html_search_regex(self, pattern, string, name, default=None, fatal=True, flags=0):
|
||||
|
||||
@@ -46,14 +46,18 @@ class GooglePlusIE(InfoExtractor):
|
||||
video_title = self._html_search_regex(r'<meta name\=\"Description\" content\=\"(.*?)[\n<"]',
|
||||
webpage, 'title', default=u'NA')
|
||||
|
||||
# Step 2, Stimulate clicking the image box to launch video
|
||||
video_page = self._search_regex('"(https\://plus\.google\.com/photos/.*?)",,"image/jpeg","video"\]',
|
||||
# Step 2, Simulate clicking the image box to launch video
|
||||
DOMAIN = 'https://plus.google.com'
|
||||
video_page = self._search_regex(r'<a href="((?:%s)?/photos/.*?)"' % re.escape(DOMAIN),
|
||||
webpage, u'video page URL')
|
||||
if not video_page.startswith(DOMAIN):
|
||||
video_page = DOMAIN + video_page
|
||||
|
||||
webpage = self._download_webpage(video_page, video_id, u'Downloading video page')
|
||||
|
||||
# Extract video links on video page
|
||||
"""Extract video links of all sizes"""
|
||||
pattern = '\d+,\d+,(\d+),"(http\://redirector\.googlevideo\.com.*?)"'
|
||||
pattern = r'\d+,\d+,(\d+),"(http\://redirector\.googlevideo\.com.*?)"'
|
||||
mobj = re.findall(pattern, webpage)
|
||||
if len(mobj) == 0:
|
||||
raise ExtractorError(u'Unable to extract video links')
|
||||
|
||||
56
youtube_dl/extractor/jukebox.py
Normal file
56
youtube_dl/extractor/jukebox.py
Normal file
@@ -0,0 +1,56 @@
|
||||
# coding: utf-8
|
||||
import re
|
||||
|
||||
from .common import InfoExtractor
|
||||
from ..utils import (
|
||||
ExtractorError,
|
||||
unescapeHTML,
|
||||
)
|
||||
|
||||
class JukeboxIE(InfoExtractor):
|
||||
_VALID_URL = r'^http://www\.jukebox?\..+?\/.+[,](?P<video_id>[a-z0-9\-]+).html'
|
||||
_IFRAME = r'<iframe .*src="(?P<iframe>[^"]*)".*>'
|
||||
_VIDEO_URL = r'"config":{"file":"(?P<video_url>http:[^"]+[.](?P<video_ext>[^.?]+)[?]mdtk=[0-9]+)"'
|
||||
_TITLE = r'<h1 class="inline">(?P<title>[^<]+)</h1>.*<span id="infos_article_artist">(?P<artist>[^<]+)</span>'
|
||||
_IS_YOUTUBE = r'config":{"file":"(?P<youtube_url>http:[\\][/][\\][/]www[.]youtube[.]com[\\][/]watch[?]v=[^"]+)"'
|
||||
|
||||
def _real_extract(self, url):
|
||||
mobj = re.match(self._VALID_URL, url)
|
||||
video_id = mobj.group('video_id')
|
||||
|
||||
html = self._download_webpage(url, video_id)
|
||||
|
||||
mobj = re.search(self._IFRAME, html)
|
||||
if mobj is None:
|
||||
raise ExtractorError(u'Cannot extract iframe url')
|
||||
iframe_url = unescapeHTML(mobj.group('iframe'))
|
||||
|
||||
iframe_html = self._download_webpage(iframe_url, video_id, 'Downloading iframe')
|
||||
mobj = re.search(r'class="jkb_waiting"', iframe_html)
|
||||
if mobj is not None:
|
||||
raise ExtractorError(u'Video is not available(in your country?)!')
|
||||
|
||||
self.report_extraction(video_id)
|
||||
|
||||
mobj = re.search(self._VIDEO_URL, iframe_html)
|
||||
if mobj is None:
|
||||
mobj = re.search(self._IS_YOUTUBE, iframe_html)
|
||||
if mobj is None:
|
||||
raise ExtractorError(u'Cannot extract video url')
|
||||
youtube_url = unescapeHTML(mobj.group('youtube_url')).replace('\/','/')
|
||||
self.to_screen(u'Youtube video detected')
|
||||
return self.url_result(youtube_url,ie='Youtube')
|
||||
video_url = unescapeHTML(mobj.group('video_url')).replace('\/','/')
|
||||
video_ext = unescapeHTML(mobj.group('video_ext'))
|
||||
|
||||
mobj = re.search(self._TITLE, html)
|
||||
if mobj is None:
|
||||
raise ExtractorError(u'Cannot extract title')
|
||||
title = unescapeHTML(mobj.group('title'))
|
||||
artist = unescapeHTML(mobj.group('artist'))
|
||||
|
||||
return [{'id': video_id,
|
||||
'url': video_url,
|
||||
'title': artist + '-' + title,
|
||||
'ext': video_ext
|
||||
}]
|
||||
32
youtube_dl/extractor/tudou.py
Normal file
32
youtube_dl/extractor/tudou.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import re
|
||||
|
||||
from .common import InfoExtractor
|
||||
|
||||
|
||||
class TudouIE(InfoExtractor):
|
||||
_VALID_URL = r'(?:http://)?(?:www\.)?tudou\.com/(?:listplay|programs)/(?:view|(.+?))/(?:([^/]+)|([^/]+)\.html)'
|
||||
|
||||
def _real_extract(self, url):
|
||||
mobj = re.match(self._VALID_URL, url)
|
||||
video_id = mobj.group(2).replace('.html','')
|
||||
webpage = self._download_webpage(url, video_id)
|
||||
video_id = re.search('"k":(.+?),',webpage).group(1)
|
||||
title = re.search(",kw:\"(.+)\"",webpage)
|
||||
if title is None:
|
||||
title = re.search(",kw: \'(.+)\'",webpage)
|
||||
title = title.group(1)
|
||||
thumbnail_url = re.search(",pic: \'(.+?)\'",webpage)
|
||||
if thumbnail_url is None:
|
||||
thumbnail_url = re.search(",pic:\"(.+?)\"",webpage)
|
||||
thumbnail_url = thumbnail_url.group(1)
|
||||
info_url = "http://v2.tudou.com/f?id="+str(video_id)
|
||||
webpage = self._download_webpage(info_url, video_id, "Opening the info webpage")
|
||||
final_url = re.search('\>(.+?)\<\/f\>',webpage).group(1)
|
||||
ext = (final_url.split('?')[0]).split('.')[-1]
|
||||
return [{
|
||||
'id': video_id,
|
||||
'url': final_url,
|
||||
'ext': ext,
|
||||
'title': title,
|
||||
'thumbnail': thumbnail_url,
|
||||
}]
|
||||
@@ -20,9 +20,9 @@ class VimeoIE(InfoExtractor):
|
||||
IE_NAME = u'vimeo'
|
||||
|
||||
def _verify_video_password(self, url, video_id, webpage):
|
||||
password = self._downloader.params.get('password', None)
|
||||
password = self._downloader.params.get('videopassword', None)
|
||||
if password is None:
|
||||
raise ExtractorError(u'This video is protected by a password, use the --password option')
|
||||
raise ExtractorError(u'This video is protected by a password, use the --video-password option')
|
||||
token = re.search(r'xsrft: \'(.*?)\'', webpage).group(1)
|
||||
data = compat_urllib_parse.urlencode({'password': password,
|
||||
'token': token})
|
||||
|
||||
@@ -16,6 +16,10 @@ class WorldStarHipHopIE(InfoExtractor):
|
||||
video_url = self._search_regex(r'so\.addVariable\("file","(.*?)"\)',
|
||||
webpage_src, u'video URL')
|
||||
|
||||
if 'youtube' in video_url:
|
||||
self.to_screen(u'Youtube video detected:')
|
||||
return self.url_result(video_url, ie='Youtube')
|
||||
|
||||
if 'mp4' in video_url:
|
||||
ext = 'mp4'
|
||||
else:
|
||||
|
||||
@@ -129,12 +129,13 @@ class YoutubeIE(InfoExtractor):
|
||||
"""Indicate the download will use the RTMP protocol."""
|
||||
self.to_screen(u'RTMP download detected')
|
||||
|
||||
@staticmethod
|
||||
def _decrypt_signature(s):
|
||||
def _decrypt_signature(self, s):
|
||||
"""Decrypt the key the two subkeys must have a length of 43"""
|
||||
(a,b) = s.split('.')
|
||||
if len(a) != 43 or len(b) != 43:
|
||||
raise ExtractorError(u'Unable to decrypt signature, subkeys lengths not valid')
|
||||
raise ExtractorError(u'Unable to decrypt signature, subkeys lengths %d.%d not supported; retrying might work' % (len(a), len(b)))
|
||||
if self._downloader.params.get('verbose'):
|
||||
self.to_screen('encrypted signature length %d.%d' % (len(a), len(b)))
|
||||
b = ''.join([b[:8],a[0],b[9:18],b[-4],b[19:39], b[18]])[0:40]
|
||||
a = a[-40:]
|
||||
s_dec = '.'.join((a,b))[::-1]
|
||||
|
||||
@@ -474,7 +474,7 @@ class ExtractorError(Exception):
|
||||
""" tb, if given, is the original traceback (so that it can be printed out). """
|
||||
|
||||
if not sys.exc_info()[0] in (compat_urllib_error.URLError, socket.timeout, UnavailableVideoError):
|
||||
msg = msg + u'; please report this issue on GitHub.'
|
||||
msg = msg + u'; please report this issue on http://yt-dl.org/bug'
|
||||
super(ExtractorError, self).__init__(msg)
|
||||
|
||||
self.traceback = tb
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
|
||||
__version__ = '2013.06.30'
|
||||
__version__ = '2013.06.33'
|
||||
|
||||
Reference in New Issue
Block a user