This commit is contained in:
Gilles Habran 2016-03-31 09:10:53 +02:00
commit 05db7b8fbb
135 changed files with 833 additions and 398 deletions

58
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,58 @@
## Please follow the guide below
- You will be asked some questions and requested to provide some information, please read them **carefully** and answer honestly
- Put an `x` into all the boxes [ ] relevant to your *issue* (like that [x])
- Use *Preview* tab to see how your issue will actually look like
---
### Make sure you are using the *latest* version: run `youtube-dl --version` and ensure your version is *2016.03.27*. If it's not read [this FAQ entry](https://github.com/rg3/youtube-dl/blob/master/README.md#how-do-i-update-youtube-dl) and update. Issues with outdated version will be rejected.
- [ ] I've **verified** and **I assure** that I'm running youtube-dl **2016.03.27**
### Before submitting an *issue* make sure you have:
- [ ] At least skimmed through [README](https://github.com/rg3/youtube-dl/blob/master/README.md) and **most notably** [FAQ](https://github.com/rg3/youtube-dl#faq) and [BUGS](https://github.com/rg3/youtube-dl#bugs) sections
- [ ] [Searched](https://github.com/rg3/youtube-dl/search?type=Issues) the bugtracker for similar issues including closed ones
### What is the purpose of your *issue*?
- [ ] Bug report (encountered problems with youtube-dl)
- [ ] Site support request (request for adding support for a new site)
- [ ] Feature request (request for a new functionality)
- [ ] Question
- [ ] Other
---
### The following sections concretize particular purposed issues, you can erase any section (the contents between triple ---) not applicable to your *issue*
---
### If the purpose of this *issue* is a *bug report*, *site support request* or you are not completely sure provide the full verbose output as follows:
Add `-v` flag to **your command line** you run youtube-dl with, copy the **whole** output and insert it here. It should look similar to one below (replace it with **your** log inserted between triple ```):
```
$ youtube-dl -v <your command line>
[debug] System config: []
[debug] User config: []
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
[debug] youtube-dl version 2016.03.27
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
[debug] Proxy map: {}
...
<end of log>
```
---
### If the purpose of this *issue* is a *site support request* please provide all kinds of example URLs support for which should be included (replace following example URLs by **yours**):
- Single video: https://www.youtube.com/watch?v=BaW_jenozKc
- Single video: https://youtu.be/BaW_jenozKc
- Playlist: https://www.youtube.com/playlist?list=PL4lCao7KL_QFVb7Iudeipvc2BCavECqzc
---
### Description of your *issue*, suggested solution and other information
Explanation of your *issue* in arbitrary form goes here. Please make sure the [description is worded well enough to be understood](https://github.com/rg3/youtube-dl#is-the-description-of-the-issue-itself-sufficient). Provide as much context and examples as possible.
If work on your *issue* required an account credentials please provide them or explain how one can obtain them.

58
.github/ISSUE_TEMPLATE_tmpl.md vendored Normal file
View File

@ -0,0 +1,58 @@
## Please follow the guide below
- You will be asked some questions and requested to provide some information, please read them **carefully** and answer honestly
- Put an `x` into all the boxes [ ] relevant to your *issue* (like that [x])
- Use *Preview* tab to see how your issue will actually look like
---
### Make sure you are using the *latest* version: run `youtube-dl --version` and ensure your version is *%(version)s*. If it's not read [this FAQ entry](https://github.com/rg3/youtube-dl/blob/master/README.md#how-do-i-update-youtube-dl) and update. Issues with outdated version will be rejected.
- [ ] I've **verified** and **I assure** that I'm running youtube-dl **%(version)s**
### Before submitting an *issue* make sure you have:
- [ ] At least skimmed through [README](https://github.com/rg3/youtube-dl/blob/master/README.md) and **most notably** [FAQ](https://github.com/rg3/youtube-dl#faq) and [BUGS](https://github.com/rg3/youtube-dl#bugs) sections
- [ ] [Searched](https://github.com/rg3/youtube-dl/search?type=Issues) the bugtracker for similar issues including closed ones
### What is the purpose of your *issue*?
- [ ] Bug report (encountered problems with youtube-dl)
- [ ] Site support request (request for adding support for a new site)
- [ ] Feature request (request for a new functionality)
- [ ] Question
- [ ] Other
---
### The following sections concretize particular purposed issues, you can erase any section (the contents between triple ---) not applicable to your *issue*
---
### If the purpose of this *issue* is a *bug report*, *site support request* or you are not completely sure provide the full verbose output as follows:
Add `-v` flag to **your command line** you run youtube-dl with, copy the **whole** output and insert it here. It should look similar to one below (replace it with **your** log inserted between triple ```):
```
$ youtube-dl -v <your command line>
[debug] System config: []
[debug] User config: []
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
[debug] youtube-dl version %(version)s
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
[debug] Proxy map: {}
...
<end of log>
```
---
### If the purpose of this *issue* is a *site support request* please provide all kinds of example URLs support for which should be included (replace following example URLs by **yours**):
- Single video: https://www.youtube.com/watch?v=BaW_jenozKc
- Single video: https://youtu.be/BaW_jenozKc
- Playlist: https://www.youtube.com/playlist?list=PL4lCao7KL_QFVb7Iudeipvc2BCavECqzc
---
### Description of your *issue*, suggested solution and other information
Explanation of your *issue* in arbitrary form goes here. Please make sure the [description is worded well enough to be understood](https://github.com/rg3/youtube-dl#is-the-description-of-the-issue-itself-sufficient). Provide as much context and examples as possible.
If work on your *issue* required an account credentials please provide them or explain how one can obtain them.

View File

@ -1,7 +1,7 @@
all: youtube-dl README.md CONTRIBUTING.md README.txt youtube-dl.1 youtube-dl.bash-completion youtube-dl.zsh youtube-dl.fish supportedsites all: youtube-dl README.md CONTRIBUTING.md ISSUE_TEMPLATE.md README.txt youtube-dl.1 youtube-dl.bash-completion youtube-dl.zsh youtube-dl.fish supportedsites
clean: clean:
rm -rf youtube-dl.1.temp.md youtube-dl.1 youtube-dl.bash-completion README.txt MANIFEST build/ dist/ .coverage cover/ youtube-dl.tar.gz youtube-dl.zsh youtube-dl.fish *.dump *.part *.info.json *.mp4 *.flv *.mp3 *.avi CONTRIBUTING.md.tmp youtube-dl youtube-dl.exe rm -rf youtube-dl.1.temp.md youtube-dl.1 youtube-dl.bash-completion README.txt MANIFEST build/ dist/ .coverage cover/ youtube-dl.tar.gz youtube-dl.zsh youtube-dl.fish *.dump *.part *.info.json *.mp4 *.flv *.mp3 *.avi CONTRIBUTING.md.tmp ISSUE_TEMPLATE.md.tmp youtube-dl youtube-dl.exe
find . -name "*.pyc" -delete find . -name "*.pyc" -delete
find . -name "*.class" -delete find . -name "*.class" -delete
@ -59,6 +59,9 @@ README.md: youtube_dl/*.py youtube_dl/*/*.py
CONTRIBUTING.md: README.md CONTRIBUTING.md: README.md
$(PYTHON) devscripts/make_contributing.py README.md CONTRIBUTING.md $(PYTHON) devscripts/make_contributing.py README.md CONTRIBUTING.md
ISSUE_TEMPLATE.md:
$(PYTHON) devscripts/make_issue_template.py .github/ISSUE_TEMPLATE_tmpl.md .github/ISSUE_TEMPLATE.md
supportedsites: supportedsites:
$(PYTHON) devscripts/make_supportedsites.py docs/supportedsites.md $(PYTHON) devscripts/make_supportedsites.py docs/supportedsites.md

View File

@ -610,6 +610,7 @@ Also filtering work for comparisons `=` (equals), `!=` (not equals), `^=` (begin
- `vcodec`: Name of the video codec in use - `vcodec`: Name of the video codec in use
- `container`: Name of the container format - `container`: Name of the container format
- `protocol`: The protocol that will be used for the actual download, lower-case. `http`, `https`, `rtsp`, `rtmp`, `rtmpe`, `m3u8`, or `m3u8_native` - `protocol`: The protocol that will be used for the actual download, lower-case. `http`, `https`, `rtsp`, `rtmp`, `rtmpe`, `m3u8`, or `m3u8_native`
- `format_id`: A short description of the format
Note that none of the aforementioned meta fields are guaranteed to be present since this solely depends on the metadata obtained by particular extractor, i.e. the metadata offered by video hoster. Note that none of the aforementioned meta fields are guaranteed to be present since this solely depends on the metadata obtained by particular extractor, i.e. the metadata offered by video hoster.

View File

@ -0,0 +1,29 @@
#!/usr/bin/env python
from __future__ import unicode_literals
import io
import optparse
def main():
parser = optparse.OptionParser(usage='%prog INFILE OUTFILE')
options, args = parser.parse_args()
if len(args) != 2:
parser.error('Expected an input and an output filename')
infile, outfile = args
with io.open(infile, encoding='utf-8') as inf:
issue_template_tmpl = inf.read()
# Get the version from youtube_dl/version.py without importing the package
exec(compile(open('youtube_dl/version.py').read(),
'youtube_dl/version.py', 'exec'))
out = issue_template_tmpl % {'version': locals()['__version__']}
with io.open(outfile, 'w', encoding='utf-8') as outf:
outf.write(out)
if __name__ == '__main__':
main()

View File

@ -45,9 +45,9 @@ fi
/bin/echo -e "\n### Changing version in version.py..." /bin/echo -e "\n### Changing version in version.py..."
sed -i "s/__version__ = '.*'/__version__ = '$version'/" youtube_dl/version.py sed -i "s/__version__ = '.*'/__version__ = '$version'/" youtube_dl/version.py
/bin/echo -e "\n### Committing documentation and youtube_dl/version.py..." /bin/echo -e "\n### Committing documentation, templates and youtube_dl/version.py..."
make README.md CONTRIBUTING.md supportedsites make README.md CONTRIBUTING.md ISSUE_TEMPLATE.md supportedsites
git add README.md CONTRIBUTING.md docs/supportedsites.md youtube_dl/version.py git add README.md CONTRIBUTING.md .github/ISSUE_TEMPLATE.md docs/supportedsites.md youtube_dl/version.py
git commit -m "release $version" git commit -m "release $version"
/bin/echo -e "\n### Now tagging, signing and pushing..." /bin/echo -e "\n### Now tagging, signing and pushing..."

View File

@ -2,5 +2,5 @@
universal = True universal = True
[flake8] [flake8]
exclude = youtube_dl/extractor/__init__.py,devscripts/buildserver.py,setup.py,build,.git exclude = youtube_dl/extractor/__init__.py,devscripts/buildserver.py,devscripts/make_issue_template.py,setup.py,build,.git
ignore = E402,E501,E731 ignore = E402,E501,E731

View File

@ -19,6 +19,7 @@ from youtube_dl.compat import (
compat_str, compat_str,
compat_urllib_parse_unquote, compat_urllib_parse_unquote,
compat_urllib_parse_unquote_plus, compat_urllib_parse_unquote_plus,
compat_urllib_parse_urlencode,
) )
@ -70,6 +71,12 @@ class TestCompat(unittest.TestCase):
self.assertEqual(compat_urllib_parse_unquote_plus('abc%20def'), 'abc def') self.assertEqual(compat_urllib_parse_unquote_plus('abc%20def'), 'abc def')
self.assertEqual(compat_urllib_parse_unquote_plus('%7e/abc+def'), '~/abc def') self.assertEqual(compat_urllib_parse_unquote_plus('%7e/abc+def'), '~/abc def')
def test_compat_urllib_parse_urlencode(self):
self.assertEqual(compat_urllib_parse_urlencode({'abc': 'def'}), 'abc=def')
self.assertEqual(compat_urllib_parse_urlencode({'abc': b'def'}), 'abc=def')
self.assertEqual(compat_urllib_parse_urlencode({b'abc': 'def'}), 'abc=def')
self.assertEqual(compat_urllib_parse_urlencode({b'abc': b'def'}), 'abc=def')
def test_compat_shlex_split(self): def test_compat_shlex_split(self):
self.assertEqual(compat_shlex_split('-option "one two"'), ['-option', 'one two']) self.assertEqual(compat_shlex_split('-option "one two"'), ['-option', 'one two'])

View File

@ -39,6 +39,8 @@ from .compat import (
compat_urllib_request_DataHandler, compat_urllib_request_DataHandler,
) )
from .utils import ( from .utils import (
age_restricted,
args_to_str,
ContentTooShortError, ContentTooShortError,
date_from_str, date_from_str,
DateRange, DateRange,
@ -58,13 +60,16 @@ from .utils import (
PagedList, PagedList,
parse_filesize, parse_filesize,
PerRequestProxyHandler, PerRequestProxyHandler,
PostProcessingError,
platform_name, platform_name,
PostProcessingError,
preferredencoding, preferredencoding,
prepend_extension,
render_table, render_table,
replace_extension,
SameFileError, SameFileError,
sanitize_filename, sanitize_filename,
sanitize_path, sanitize_path,
sanitize_url,
sanitized_Request, sanitized_Request,
std_headers, std_headers,
subtitles_filename, subtitles_filename,
@ -75,10 +80,6 @@ from .utils import (
write_string, write_string,
YoutubeDLCookieProcessor, YoutubeDLCookieProcessor,
YoutubeDLHandler, YoutubeDLHandler,
prepend_extension,
replace_extension,
args_to_str,
age_restricted,
) )
from .cache import Cache from .cache import Cache
from .extractor import get_info_extractor, gen_extractors from .extractor import get_info_extractor, gen_extractors
@ -1229,6 +1230,7 @@ class YoutubeDL(object):
t.get('preference'), t.get('width'), t.get('height'), t.get('preference'), t.get('width'), t.get('height'),
t.get('id'), t.get('url'))) t.get('id'), t.get('url')))
for i, t in enumerate(thumbnails): for i, t in enumerate(thumbnails):
t['url'] = sanitize_url(t['url'])
if t.get('width') and t.get('height'): if t.get('width') and t.get('height'):
t['resolution'] = '%dx%d' % (t['width'], t['height']) t['resolution'] = '%dx%d' % (t['width'], t['height'])
if t.get('id') is None: if t.get('id') is None:
@ -1263,6 +1265,8 @@ class YoutubeDL(object):
if subtitles: if subtitles:
for _, subtitle in subtitles.items(): for _, subtitle in subtitles.items():
for subtitle_format in subtitle: for subtitle_format in subtitle:
if subtitle_format.get('url'):
subtitle_format['url'] = sanitize_url(subtitle_format['url'])
if 'ext' not in subtitle_format: if 'ext' not in subtitle_format:
subtitle_format['ext'] = determine_ext(subtitle_format['url']).lower() subtitle_format['ext'] = determine_ext(subtitle_format['url']).lower()
@ -1292,6 +1296,8 @@ class YoutubeDL(object):
if 'url' not in format: if 'url' not in format:
raise ExtractorError('Missing "url" key in result (index %d)' % i) raise ExtractorError('Missing "url" key in result (index %d)' % i)
format['url'] = sanitize_url(format['url'])
if format.get('format_id') is None: if format.get('format_id') is None:
format['format_id'] = compat_str(i) format['format_id'] = compat_str(i)
else: else:

View File

@ -169,6 +169,31 @@ except ImportError: # Python 2
string = string.replace('+', ' ') string = string.replace('+', ' ')
return compat_urllib_parse_unquote(string, encoding, errors) return compat_urllib_parse_unquote(string, encoding, errors)
try:
from urllib.parse import urlencode as compat_urllib_parse_urlencode
except ImportError: # Python 2
# Python 2 will choke in urlencode on mixture of byte and unicode strings.
# Possible solutions are to either port it from python 3 with all
# the friends or manually ensure input query contains only byte strings.
# We will stick with latter thus recursively encoding the whole query.
def compat_urllib_parse_urlencode(query, doseq=0, encoding='utf-8'):
def encode_elem(e):
if isinstance(e, dict):
e = encode_dict(e)
elif isinstance(e, (list, tuple,)):
e = encode_list(e)
elif isinstance(e, compat_str):
e = e.encode(encoding)
return e
def encode_dict(d):
return dict((encode_elem(k), encode_elem(v)) for k, v in d.items())
def encode_list(l):
return [encode_elem(e) for e in l]
return compat_urllib_parse.urlencode(encode_elem(query), doseq=doseq)
try: try:
from urllib.request import DataHandler as compat_urllib_request_DataHandler from urllib.request import DataHandler as compat_urllib_request_DataHandler
except ImportError: # Python < 3.4 except ImportError: # Python < 3.4
@ -588,6 +613,7 @@ __all__ = [
'compat_urllib_parse_unquote', 'compat_urllib_parse_unquote',
'compat_urllib_parse_unquote_plus', 'compat_urllib_parse_unquote_plus',
'compat_urllib_parse_unquote_to_bytes', 'compat_urllib_parse_unquote_to_bytes',
'compat_urllib_parse_urlencode',
'compat_urllib_parse_urlparse', 'compat_urllib_parse_urlparse',
'compat_urllib_request', 'compat_urllib_request',
'compat_urllib_request_DataHandler', 'compat_urllib_request_DataHandler',

View File

@ -223,6 +223,12 @@ def write_metadata_tag(stream, metadata):
write_unsigned_int(stream, FLV_TAG_HEADER_LEN + len(metadata)) write_unsigned_int(stream, FLV_TAG_HEADER_LEN + len(metadata))
def remove_encrypted_media(media):
return list(filter(lambda e: 'drmAdditionalHeaderId' not in e.attrib and
'drmAdditionalHeaderSetId' not in e.attrib,
media))
def _add_ns(prop): def _add_ns(prop):
return '{http://ns.adobe.com/f4m/1.0}%s' % prop return '{http://ns.adobe.com/f4m/1.0}%s' % prop
@ -244,9 +250,7 @@ class F4mFD(FragmentFD):
# without drmAdditionalHeaderId or drmAdditionalHeaderSetId attribute # without drmAdditionalHeaderId or drmAdditionalHeaderSetId attribute
if 'id' not in e.attrib: if 'id' not in e.attrib:
self.report_error('Missing ID in f4m DRM') self.report_error('Missing ID in f4m DRM')
media = list(filter(lambda e: 'drmAdditionalHeaderId' not in e.attrib and media = remove_encrypted_media(media)
'drmAdditionalHeaderSetId' not in e.attrib,
media))
if not media: if not media:
self.report_error('Unsupported DRM') self.report_error('Unsupported DRM')
return media return media

View File

@ -127,6 +127,7 @@ from .cloudy import CloudyIE
from .clubic import ClubicIE from .clubic import ClubicIE
from .clyp import ClypIE from .clyp import ClypIE
from .cmt import CMTIE from .cmt import CMTIE
from .cnbc import CNBCIE
from .cnet import CNETIE from .cnet import CNETIE
from .cnn import ( from .cnn import (
CNNIE, CNNIE,
@ -441,6 +442,7 @@ from .nationalgeographic import NationalGeographicIE
from .naver import NaverIE from .naver import NaverIE
from .nba import NBAIE from .nba import NBAIE
from .nbc import ( from .nbc import (
CSNNEIE,
NBCIE, NBCIE,
NBCNewsIE, NBCNewsIE,
NBCSportsIE, NBCSportsIE,

View File

@ -44,6 +44,7 @@ class Abc7NewsIE(InfoExtractor):
'contentURL', webpage, 'm3u8 url', fatal=True) 'contentURL', webpage, 'm3u8 url', fatal=True)
formats = self._extract_m3u8_formats(m3u8, display_id, 'mp4') formats = self._extract_m3u8_formats(m3u8, display_id, 'mp4')
self._sort_formats(formats)
title = self._og_search_title(webpage).strip() title = self._og_search_title(webpage).strip()
description = self._og_search_description(webpage).strip() description = self._og_search_description(webpage).strip()

View File

@ -6,7 +6,7 @@ from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_HTTPError, compat_HTTPError,
compat_str, compat_str,
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urllib_parse_urlparse, compat_urllib_parse_urlparse,
) )
from ..utils import ( from ..utils import (
@ -60,7 +60,7 @@ class AddAnimeIE(InfoExtractor):
confirm_url = ( confirm_url = (
parsed_url.scheme + '://' + parsed_url.netloc + parsed_url.scheme + '://' + parsed_url.netloc +
action + '?' + action + '?' +
compat_urllib_parse.urlencode({ compat_urllib_parse_urlencode({
'jschl_vc': vc, 'jschl_answer': compat_str(av_val)})) 'jschl_vc': vc, 'jschl_answer': compat_str(av_val)}))
self._download_webpage( self._download_webpage(
confirm_url, video_id, confirm_url, video_id,

View File

@ -69,12 +69,14 @@ class AMPIE(InfoExtractor):
self._sort_formats(formats) self._sort_formats(formats)
timestamp = parse_iso8601(item.get('pubDate'), ' ') or parse_iso8601(item.get('dc-date'))
return { return {
'id': video_id, 'id': video_id,
'title': get_media_node('title'), 'title': get_media_node('title'),
'description': get_media_node('description'), 'description': get_media_node('description'),
'thumbnails': thumbnails, 'thumbnails': thumbnails,
'timestamp': parse_iso8601(item.get('pubDate'), ' '), 'timestamp': timestamp,
'duration': int_or_none(media_content[0].get('@attributes', {}).get('duration')), 'duration': int_or_none(media_content[0].get('@attributes', {}).get('duration')),
'subtitles': subtitles, 'subtitles': subtitles,
'formats': formats, 'formats': formats,

View File

@ -9,7 +9,6 @@ from ..compat import (
) )
from ..utils import ( from ..utils import (
determine_ext, determine_ext,
encode_dict,
extract_attributes, extract_attributes,
ExtractorError, ExtractorError,
sanitized_Request, sanitized_Request,
@ -71,7 +70,7 @@ class AnimeOnDemandIE(InfoExtractor):
post_url = compat_urlparse.urljoin(self._LOGIN_URL, post_url) post_url = compat_urlparse.urljoin(self._LOGIN_URL, post_url)
request = sanitized_Request( request = sanitized_Request(
post_url, urlencode_postdata(encode_dict(login_form))) post_url, urlencode_postdata(login_form))
request.add_header('Referer', self._LOGIN_URL) request.add_header('Referer', self._LOGIN_URL)
response = self._download_webpage( response = self._download_webpage(

View File

@ -6,16 +6,14 @@ import hashlib
import re import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import compat_str
compat_str,
compat_urllib_parse,
)
from ..utils import ( from ..utils import (
int_or_none,
float_or_none,
sanitized_Request,
xpath_text,
ExtractorError, ExtractorError,
float_or_none,
int_or_none,
sanitized_Request,
urlencode_postdata,
xpath_text,
) )
@ -86,7 +84,7 @@ class AtresPlayerIE(InfoExtractor):
} }
request = sanitized_Request( request = sanitized_Request(
self._LOGIN_URL, compat_urllib_parse.urlencode(login_form).encode('utf-8')) self._LOGIN_URL, urlencode_postdata(login_form))
request.add_header('Content-Type', 'application/x-www-form-urlencoded') request.add_header('Content-Type', 'application/x-www-form-urlencoded')
response = self._download_webpage( response = self._download_webpage(
request, None, 'Logging in as %s' % username) request, None, 'Logging in as %s' % username)

View File

@ -120,6 +120,7 @@ class AzubuLiveIE(InfoExtractor):
bc_info = self._download_json(req, user) bc_info = self._download_json(req, user)
m3u8_url = next(source['src'] for source in bc_info['sources'] if source['container'] == 'M2TS') m3u8_url = next(source['src'] for source in bc_info['sources'] if source['container'] == 'M2TS')
formats = self._extract_m3u8_formats(m3u8_url, user, ext='mp4') formats = self._extract_m3u8_formats(m3u8_url, user, ext='mp4')
self._sort_formats(formats)
return { return {
'id': info['id'], 'id': info['id'],

View File

@ -4,15 +4,13 @@ import re
import itertools import itertools
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import compat_str
compat_urllib_parse,
compat_str,
)
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
int_or_none,
float_or_none, float_or_none,
int_or_none,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -58,7 +56,7 @@ class BambuserIE(InfoExtractor):
} }
request = sanitized_Request( request = sanitized_Request(
self._LOGIN_URL, compat_urllib_parse.urlencode(login_form).encode('utf-8')) self._LOGIN_URL, urlencode_postdata(login_form))
request.add_header('Referer', self._LOGIN_URL) request.add_header('Referer', self._LOGIN_URL)
response = self._download_webpage( response = self._download_webpage(
request, None, 'Logging in as %s' % username) request, None, 'Logging in as %s' % username)

View File

@ -688,6 +688,10 @@ class BBCIE(BBCCoUkIE):
# custom redirection to www.bbc.com # custom redirection to www.bbc.com
'url': 'http://www.bbc.co.uk/news/science-environment-33661876', 'url': 'http://www.bbc.co.uk/news/science-environment-33661876',
'only_matching': True, 'only_matching': True,
}, {
# single video article embedded with data-media-vpid
'url': 'http://www.bbc.co.uk/sport/rowing/35908187',
'only_matching': True,
}] }]
@classmethod @classmethod
@ -817,7 +821,7 @@ class BBCIE(BBCCoUkIE):
# single video story (e.g. http://www.bbc.com/travel/story/20150625-sri-lankas-spicy-secret) # single video story (e.g. http://www.bbc.com/travel/story/20150625-sri-lankas-spicy-secret)
programme_id = self._search_regex( programme_id = self._search_regex(
[r'data-video-player-vpid="(%s)"' % self._ID_REGEX, [r'data-(?:video-player|media)-vpid="(%s)"' % self._ID_REGEX,
r'<param[^>]+name="externalIdentifier"[^>]+value="(%s)"' % self._ID_REGEX, r'<param[^>]+name="externalIdentifier"[^>]+value="(%s)"' % self._ID_REGEX,
r'videoId\s*:\s*["\'](%s)["\']' % self._ID_REGEX], r'videoId\s*:\s*["\'](%s)["\']' % self._ID_REGEX],
webpage, 'vpid', default=None) webpage, 'vpid', default=None)

View File

@ -94,6 +94,7 @@ class BetIE(InfoExtractor):
xpath_with_ns('./media:thumbnail', NS_MAP)).get('url') xpath_with_ns('./media:thumbnail', NS_MAP)).get('url')
formats = self._extract_smil_formats(smil_url, display_id) formats = self._extract_smil_formats(smil_url, display_id)
self._sort_formats(formats)
return { return {
'id': video_id, 'id': video_id,

View File

@ -136,13 +136,16 @@ class BrightcoveLegacyIE(InfoExtractor):
else: else:
flashvars = {} flashvars = {}
data_url = object_doc.attrib.get('data', '')
data_url_params = compat_parse_qs(compat_urllib_parse_urlparse(data_url).query)
def find_param(name): def find_param(name):
if name in flashvars: if name in flashvars:
return flashvars[name] return flashvars[name]
node = find_xpath_attr(object_doc, './param', 'name', name) node = find_xpath_attr(object_doc, './param', 'name', name)
if node is not None: if node is not None:
return node.attrib['value'] return node.attrib['value']
return None return data_url_params.get(name)
params = {} params = {}
@ -294,7 +297,7 @@ class BrightcoveLegacyIE(InfoExtractor):
'uploader': video_info.get('publisherName'), 'uploader': video_info.get('publisherName'),
} }
renditions = video_info.get('renditions') renditions = video_info.get('renditions', []) + video_info.get('IOSRenditions', [])
if renditions: if renditions:
formats = [] formats = []
for rend in renditions: for rend in renditions:
@ -316,13 +319,23 @@ class BrightcoveLegacyIE(InfoExtractor):
if ext is None: if ext is None:
ext = determine_ext(url) ext = determine_ext(url)
size = rend.get('size') size = rend.get('size')
formats.append({ a_format = {
'url': url, 'url': url,
'ext': ext, 'ext': ext,
'height': rend.get('frameHeight'), 'height': rend.get('frameHeight'),
'width': rend.get('frameWidth'), 'width': rend.get('frameWidth'),
'filesize': size if size != 0 else None, 'filesize': size if size != 0 else None,
}) }
# m3u8 manifests with remote == false are media playlists
# Not calling _extract_m3u8_formats here to save network traffic
if ext == 'm3u8':
a_format.update({
'ext': 'mp4',
'protocol': 'm3u8',
})
formats.append(a_format)
self._sort_formats(formats) self._sort_formats(formats)
info['formats'] = formats info['formats'] = formats
elif video_info.get('FLVFullLengthURL') is not None: elif video_info.get('FLVFullLengthURL') is not None:

View File

@ -6,7 +6,7 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urlparse, compat_urlparse,
) )
from ..utils import ( from ..utils import (
@ -139,7 +139,7 @@ class CamdemyFolderIE(InfoExtractor):
parsed_url = list(compat_urlparse.urlparse(url)) parsed_url = list(compat_urlparse.urlparse(url))
query = dict(compat_urlparse.parse_qsl(parsed_url[4])) query = dict(compat_urlparse.parse_qsl(parsed_url[4]))
query.update({'displayMode': 'list'}) query.update({'displayMode': 'list'})
parsed_url[4] = compat_urllib_parse.urlencode(query) parsed_url[4] = compat_urllib_parse_urlencode(query)
final_url = compat_urlparse.urlunparse(parsed_url) final_url = compat_urlparse.urlunparse(parsed_url)
page = self._download_webpage(final_url, folder_id) page = self._download_webpage(final_url, folder_id)

View File

@ -122,6 +122,7 @@ class CBSNewsLiveVideoIE(InfoExtractor):
for entry in f4m_formats: for entry in f4m_formats:
# URLs without the extra param induce an 404 error # URLs without the extra param induce an 404 error
entry.update({'extra_param_to_segment_url': hdcore_sign}) entry.update({'extra_param_to_segment_url': hdcore_sign})
self._sort_formats(f4m_formats)
return { return {
'id': video_id, 'id': video_id,

View File

@ -5,7 +5,6 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse,
compat_urllib_parse_unquote, compat_urllib_parse_unquote,
compat_urllib_parse_urlparse, compat_urllib_parse_urlparse,
) )
@ -13,6 +12,7 @@ from ..utils import (
ExtractorError, ExtractorError,
float_or_none, float_or_none,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -102,7 +102,7 @@ class CeskaTelevizeIE(InfoExtractor):
req = sanitized_Request( req = sanitized_Request(
'http://www.ceskatelevize.cz/ivysilani/ajax/get-client-playlist', 'http://www.ceskatelevize.cz/ivysilani/ajax/get-client-playlist',
data=compat_urllib_parse.urlencode(data)) data=urlencode_postdata(data))
req.add_header('Content-type', 'application/x-www-form-urlencoded') req.add_header('Content-type', 'application/x-www-form-urlencoded')
req.add_header('x-addr', '127.0.0.1') req.add_header('x-addr', '127.0.0.1')

View File

@ -48,6 +48,7 @@ class ChaturbateIE(InfoExtractor):
raise ExtractorError('Unable to find stream URL') raise ExtractorError('Unable to find stream URL')
formats = self._extract_m3u8_formats(m3u8_url, video_id, ext='mp4') formats = self._extract_m3u8_formats(m3u8_url, video_id, ext='mp4')
self._sort_formats(formats)
return { return {
'id': video_id, 'id': video_id,

View File

@ -6,7 +6,7 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_parse_qs, compat_parse_qs,
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_HTTPError, compat_HTTPError,
) )
from ..utils import ( from ..utils import (
@ -64,7 +64,7 @@ class CloudyIE(InfoExtractor):
'errorUrl': error_url, 'errorUrl': error_url,
}) })
data_url = self._API_URL % (video_host, compat_urllib_parse.urlencode(form)) data_url = self._API_URL % (video_host, compat_urllib_parse_urlencode(form))
player_data = self._download_webpage( player_data = self._download_webpage(
data_url, video_id, 'Downloading player data') data_url, video_id, 'Downloading player data')
data = compat_parse_qs(player_data) data = compat_parse_qs(player_data)

View File

@ -0,0 +1,33 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor
from ..utils import smuggle_url
class CNBCIE(InfoExtractor):
_VALID_URL = r'https?://video\.cnbc\.com/gallery/\?video=(?P<id>[0-9]+)'
_TEST = {
'url': 'http://video.cnbc.com/gallery/?video=3000503714',
'info_dict': {
'id': '3000503714',
'ext': 'mp4',
'title': 'Fighting zombies is big business',
'description': 'md5:0c100d8e1a7947bd2feec9a5550e519e',
},
'params': {
# m3u8 download
'skip_download': True,
},
}
def _real_extract(self, url):
video_id = self._match_id(url)
return {
'_type': 'url_transparent',
'ie_key': 'ThePlatform',
'url': smuggle_url(
'http://link.theplatform.com/s/gZWlPC/media/guid/2408950221/%s?mbr=true&manifest=m3u' % video_id,
{'force_smil_url': True}),
'id': video_id,
}

View File

@ -41,7 +41,13 @@ class ComCarCoffIE(InfoExtractor):
display_id = full_data['activeVideo']['video'] display_id = full_data['activeVideo']['video']
video_data = full_data.get('videos', {}).get(display_id) or full_data['singleshots'][display_id] video_data = full_data.get('videos', {}).get(display_id) or full_data['singleshots'][display_id]
video_id = compat_str(video_data['mediaId']) video_id = compat_str(video_data['mediaId'])
title = video_data['title']
formats = self._extract_m3u8_formats(
video_data['mediaUrl'], video_id, 'mp4')
self._sort_formats(formats)
thumbnails = [{ thumbnails = [{
'url': video_data['images']['thumb'], 'url': video_data['images']['thumb'],
}, { }, {
@ -54,15 +60,14 @@ class ComCarCoffIE(InfoExtractor):
video_data.get('duration')) video_data.get('duration'))
return { return {
'_type': 'url_transparent',
'url': 'crackle:%s' % video_id,
'id': video_id, 'id': video_id,
'display_id': display_id, 'display_id': display_id,
'title': video_data['title'], 'title': title,
'description': video_data.get('description'), 'description': video_data.get('description'),
'timestamp': timestamp, 'timestamp': timestamp,
'duration': duration, 'duration': duration,
'thumbnails': thumbnails, 'thumbnails': thumbnails,
'formats': formats,
'season_number': int_or_none(video_data.get('season')), 'season_number': int_or_none(video_data.get('season')),
'episode_number': int_or_none(video_data.get('episode')), 'episode_number': int_or_none(video_data.get('episode')),
'webpage_url': 'http://comediansincarsgettingcoffee.com/%s' % (video_data.get('urlSlug', video_data.get('slug'))), 'webpage_url': 'http://comediansincarsgettingcoffee.com/%s' % (video_data.get('urlSlug', video_data.get('slug'))),

View File

@ -5,7 +5,7 @@ import re
from .mtv import MTVServicesInfoExtractor from .mtv import MTVServicesInfoExtractor
from ..compat import ( from ..compat import (
compat_str, compat_str,
compat_urllib_parse, compat_urllib_parse_urlencode,
) )
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
@ -201,7 +201,7 @@ class ComedyCentralShowsIE(MTVServicesInfoExtractor):
# Correct cc.com in uri # Correct cc.com in uri
uri = re.sub(r'(episode:[^.]+)(\.cc)?\.com', r'\1.com', uri) uri = re.sub(r'(episode:[^.]+)(\.cc)?\.com', r'\1.com', uri)
index_url = 'http://%s.cc.com/feeds/mrss?%s' % (show_name, compat_urllib_parse.urlencode({'uri': uri})) index_url = 'http://%s.cc.com/feeds/mrss?%s' % (show_name, compat_urllib_parse_urlencode({'uri': uri}))
idoc = self._download_xml( idoc = self._download_xml(
index_url, epTitle, index_url, epTitle,
'Downloading show index', 'Unable to download episode index') 'Downloading show index', 'Unable to download episode index')

View File

@ -21,9 +21,10 @@ from ..compat import (
compat_os_name, compat_os_name,
compat_str, compat_str,
compat_urllib_error, compat_urllib_error,
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urlparse, compat_urlparse,
) )
from ..downloader.f4m import remove_encrypted_media
from ..utils import ( from ..utils import (
NO_DEFAULT, NO_DEFAULT,
age_restricted, age_restricted,
@ -989,6 +990,11 @@ class InfoExtractor(object):
if not media_nodes: if not media_nodes:
manifest_version = '2.0' manifest_version = '2.0'
media_nodes = manifest.findall('{http://ns.adobe.com/f4m/2.0}media') media_nodes = manifest.findall('{http://ns.adobe.com/f4m/2.0}media')
# Remove unsupported DRM protected media from final formats
# rendition (see https://github.com/rg3/youtube-dl/issues/8573).
media_nodes = remove_encrypted_media(media_nodes)
if not media_nodes:
return formats
base_url = xpath_text( base_url = xpath_text(
manifest, ['{http://ns.adobe.com/f4m/1.0}baseURL', '{http://ns.adobe.com/f4m/2.0}baseURL'], manifest, ['{http://ns.adobe.com/f4m/1.0}baseURL', '{http://ns.adobe.com/f4m/2.0}baseURL'],
'base URL', default=None) 'base URL', default=None)
@ -1021,8 +1027,6 @@ class InfoExtractor(object):
'height': int_or_none(media_el.attrib.get('height')), 'height': int_or_none(media_el.attrib.get('height')),
'preference': preference, 'preference': preference,
}) })
self._sort_formats(formats)
return formats return formats
def _extract_m3u8_formats(self, m3u8_url, video_id, ext=None, def _extract_m3u8_formats(self, m3u8_url, video_id, ext=None,
@ -1143,7 +1147,6 @@ class InfoExtractor(object):
last_media = None last_media = None
formats.append(f) formats.append(f)
last_info = {} last_info = {}
self._sort_formats(formats)
return formats return formats
@staticmethod @staticmethod
@ -1300,7 +1303,7 @@ class InfoExtractor(object):
'plugin': 'flowplayer-3.2.0.1', 'plugin': 'flowplayer-3.2.0.1',
} }
f4m_url += '&' if '?' in f4m_url else '?' f4m_url += '&' if '?' in f4m_url else '?'
f4m_url += compat_urllib_parse.urlencode(f4m_params) f4m_url += compat_urllib_parse_urlencode(f4m_params)
formats.extend(self._extract_f4m_formats(f4m_url, video_id, f4m_id='hds', fatal=False)) formats.extend(self._extract_f4m_formats(f4m_url, video_id, f4m_id='hds', fatal=False))
continue continue
@ -1317,8 +1320,6 @@ class InfoExtractor(object):
}) })
continue continue
self._sort_formats(formats)
return formats return formats
def _parse_smil_subtitles(self, smil, namespace=None, subtitles_lang='en'): def _parse_smil_subtitles(self, smil, namespace=None, subtitles_lang='en'):
@ -1536,7 +1537,6 @@ class InfoExtractor(object):
existing_format.update(f) existing_format.update(f)
else: else:
self.report_warning('Unknown MIME type %s in DASH manifest' % mime_type) self.report_warning('Unknown MIME type %s in DASH manifest' % mime_type)
self._sort_formats(formats)
return formats return formats
def _live_title(self, name): def _live_title(self, name):

View File

@ -5,7 +5,7 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urllib_parse_urlparse, compat_urllib_parse_urlparse,
compat_urlparse, compat_urlparse,
) )
@ -97,7 +97,7 @@ class CondeNastIE(InfoExtractor):
video_id = self._search_regex(r'videoId: [\'"](.+?)[\'"]', params, 'video id') video_id = self._search_regex(r'videoId: [\'"](.+?)[\'"]', params, 'video id')
player_id = self._search_regex(r'playerId: [\'"](.+?)[\'"]', params, 'player id') player_id = self._search_regex(r'playerId: [\'"](.+?)[\'"]', params, 'player id')
target = self._search_regex(r'target: [\'"](.+?)[\'"]', params, 'target') target = self._search_regex(r'target: [\'"](.+?)[\'"]', params, 'target')
data = compat_urllib_parse.urlencode({'videoId': video_id, data = compat_urllib_parse_urlencode({'videoId': video_id,
'playerId': player_id, 'playerId': player_id,
'target': target, 'target': target,
}) })

View File

@ -11,8 +11,8 @@ from math import pow, sqrt, floor
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_etree_fromstring, compat_etree_fromstring,
compat_urllib_parse,
compat_urllib_parse_unquote, compat_urllib_parse_unquote,
compat_urllib_parse_urlencode,
compat_urllib_request, compat_urllib_request,
compat_urlparse, compat_urlparse,
) )
@ -78,7 +78,7 @@ class CrunchyrollBaseIE(InfoExtractor):
# See https://github.com/rg3/youtube-dl/issues/7202. # See https://github.com/rg3/youtube-dl/issues/7202.
qs['skip_wall'] = ['1'] qs['skip_wall'] = ['1']
return compat_urlparse.urlunparse( return compat_urlparse.urlunparse(
parsed_url._replace(query=compat_urllib_parse.urlencode(qs, True))) parsed_url._replace(query=compat_urllib_parse_urlencode(qs, True)))
class CrunchyrollIE(CrunchyrollBaseIE): class CrunchyrollIE(CrunchyrollBaseIE):
@ -308,7 +308,7 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
playerdata_url = compat_urllib_parse_unquote(self._html_search_regex(r'"config_url":"([^"]+)', webpage, 'playerdata_url')) playerdata_url = compat_urllib_parse_unquote(self._html_search_regex(r'"config_url":"([^"]+)', webpage, 'playerdata_url'))
playerdata_req = sanitized_Request(playerdata_url) playerdata_req = sanitized_Request(playerdata_url)
playerdata_req.data = compat_urllib_parse.urlencode({'current_page': webpage_url}) playerdata_req.data = urlencode_postdata({'current_page': webpage_url})
playerdata_req.add_header('Content-Type', 'application/x-www-form-urlencoded') playerdata_req.add_header('Content-Type', 'application/x-www-form-urlencoded')
playerdata = self._download_webpage(playerdata_req, video_id, note='Downloading media info') playerdata = self._download_webpage(playerdata_req, video_id, note='Downloading media info')
@ -322,7 +322,7 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
streamdata_req = sanitized_Request( streamdata_req = sanitized_Request(
'http://www.crunchyroll.com/xml/?req=RpcApiVideoPlayer_GetStandardConfig&media_id=%s&video_format=%s&video_quality=%s' 'http://www.crunchyroll.com/xml/?req=RpcApiVideoPlayer_GetStandardConfig&media_id=%s&video_format=%s&video_quality=%s'
% (stream_id, stream_format, stream_quality), % (stream_id, stream_format, stream_quality),
compat_urllib_parse.urlencode({'current_page': url}).encode('utf-8')) compat_urllib_parse_urlencode({'current_page': url}).encode('utf-8'))
streamdata_req.add_header('Content-Type', 'application/x-www-form-urlencoded') streamdata_req.add_header('Content-Type', 'application/x-www-form-urlencoded')
streamdata = self._download_xml( streamdata = self._download_xml(
streamdata_req, video_id, streamdata_req, video_id,

View File

@ -57,6 +57,7 @@ class CWTVIE(InfoExtractor):
formats = self._extract_m3u8_formats( formats = self._extract_m3u8_formats(
video_data['videos']['variantplaylist']['uri'], video_id, 'mp4') video_data['videos']['variantplaylist']['uri'], video_id, 'mp4')
self._sort_formats(formats)
thumbnails = [{ thumbnails = [{
'url': image['uri'], 'url': image['uri'],

View File

@ -8,8 +8,8 @@ import itertools
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_parse_qs, compat_parse_qs,
compat_urllib_parse,
compat_urllib_parse_unquote, compat_urllib_parse_unquote,
compat_urllib_parse_urlencode,
compat_urlparse, compat_urlparse,
) )
from ..utils import ( from ..utils import (
@ -70,7 +70,7 @@ class DaumIE(InfoExtractor):
def _real_extract(self, url): def _real_extract(self, url):
video_id = compat_urllib_parse_unquote(self._match_id(url)) video_id = compat_urllib_parse_unquote(self._match_id(url))
query = compat_urllib_parse.urlencode({'vid': video_id}) query = compat_urllib_parse_urlencode({'vid': video_id})
movie_data = self._download_json( movie_data = self._download_json(
'http://videofarm.daum.net/controller/api/closed/v1_2/IntegratedMovieData.json?' + query, 'http://videofarm.daum.net/controller/api/closed/v1_2/IntegratedMovieData.json?' + query,
video_id, 'Downloading video formats info') video_id, 'Downloading video formats info')
@ -86,7 +86,7 @@ class DaumIE(InfoExtractor):
formats = [] formats = []
for format_el in movie_data['output_list']['output_list']: for format_el in movie_data['output_list']['output_list']:
profile = format_el['profile'] profile = format_el['profile']
format_query = compat_urllib_parse.urlencode({ format_query = compat_urllib_parse_urlencode({
'vid': video_id, 'vid': video_id,
'profile': profile, 'profile': profile,
}) })

View File

@ -6,7 +6,7 @@ import base64
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_str, compat_str,
) )
from ..utils import ( from ..utils import (
@ -15,6 +15,7 @@ from ..utils import (
sanitized_Request, sanitized_Request,
smuggle_url, smuggle_url,
unsmuggle_url, unsmuggle_url,
urlencode_postdata,
) )
@ -106,7 +107,7 @@ class DCNVideoIE(DCNBaseIE):
webpage = self._download_webpage( webpage = self._download_webpage(
'http://admin.mangomolo.com/analytics/index.php/customers/embed/video?' + 'http://admin.mangomolo.com/analytics/index.php/customers/embed/video?' +
compat_urllib_parse.urlencode({ compat_urllib_parse_urlencode({
'id': video_data['id'], 'id': video_data['id'],
'user_id': video_data['user_id'], 'user_id': video_data['user_id'],
'signature': video_data['signature'], 'signature': video_data['signature'],
@ -133,7 +134,7 @@ class DCNLiveIE(DCNBaseIE):
webpage = self._download_webpage( webpage = self._download_webpage(
'http://admin.mangomolo.com/analytics/index.php/customers/embed/index?' + 'http://admin.mangomolo.com/analytics/index.php/customers/embed/index?' +
compat_urllib_parse.urlencode({ compat_urllib_parse_urlencode({
'id': base64.b64encode(channel_data['user_id'].encode()).decode(), 'id': base64.b64encode(channel_data['user_id'].encode()).decode(),
'channelid': base64.b64encode(channel_data['id'].encode()).decode(), 'channelid': base64.b64encode(channel_data['id'].encode()).decode(),
'signature': channel_data['signature'], 'signature': channel_data['signature'],
@ -174,7 +175,7 @@ class DCNSeasonIE(InfoExtractor):
data['show_id'] = show_id data['show_id'] = show_id
request = sanitized_Request( request = sanitized_Request(
'http://admin.mangomolo.com/analytics/index.php/plus/show', 'http://admin.mangomolo.com/analytics/index.php/plus/show',
compat_urllib_parse.urlencode(data), urlencode_postdata(data),
{ {
'Origin': 'http://www.dcndigital.ae', 'Origin': 'http://www.dcndigital.ae',
'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': 'application/x-www-form-urlencoded'

View File

@ -38,6 +38,7 @@ class DFBIE(InfoExtractor):
token_el = f4m_info.find('token') token_el = f4m_info.find('token')
manifest_url = token_el.attrib['url'] + '?' + 'hdnea=' + token_el.attrib['auth'] + '&hdcore=3.2.0' manifest_url = token_el.attrib['url'] + '?' + 'hdnea=' + token_el.attrib['auth'] + '&hdcore=3.2.0'
formats = self._extract_f4m_formats(manifest_url, display_id) formats = self._extract_f4m_formats(manifest_url, display_id)
self._sort_formats(formats)
return { return {
'id': video_id, 'id': video_id,

View File

@ -63,18 +63,23 @@ class DiscoveryIE(InfoExtractor):
video_title = info.get('playlist_title') or info.get('video_title') video_title = info.get('playlist_title') or info.get('video_title')
entries = [{ entries = []
'id': compat_str(video_info['id']),
'formats': self._extract_m3u8_formats( for idx, video_info in enumerate(info['playlist']):
formats = self._extract_m3u8_formats(
video_info['src'], display_id, 'mp4', 'm3u8_native', m3u8_id='hls', video_info['src'], display_id, 'mp4', 'm3u8_native', m3u8_id='hls',
note='Download m3u8 information for video %d' % (idx + 1)), note='Download m3u8 information for video %d' % (idx + 1))
'title': video_info['title'], self._sort_formats(formats)
'description': video_info.get('description'), entries.append({
'duration': parse_duration(video_info.get('video_length')), 'id': compat_str(video_info['id']),
'webpage_url': video_info.get('href') or video_info.get('url'), 'formats': formats,
'thumbnail': video_info.get('thumbnailURL'), 'title': video_info['title'],
'alt_title': video_info.get('secondary_title'), 'description': video_info.get('description'),
'timestamp': parse_iso8601(video_info.get('publishedDate')), 'duration': parse_duration(video_info.get('video_length')),
} for idx, video_info in enumerate(info['playlist'])] 'webpage_url': video_info.get('href') or video_info.get('url'),
'thumbnail': video_info.get('thumbnailURL'),
'alt_title': video_info.get('secondary_title'),
'timestamp': parse_iso8601(video_info.get('publishedDate')),
})
return self.playlist_result(entries, display_id, video_title) return self.playlist_result(entries, display_id, video_title)

View File

@ -118,6 +118,8 @@ class DPlayIE(InfoExtractor):
if info.get(protocol): if info.get(protocol):
extract_formats(protocol, info[protocol]) extract_formats(protocol, info[protocol])
self._sort_formats(formats)
return { return {
'id': video_id, 'id': video_id,
'display_id': display_id, 'display_id': display_id,

View File

@ -6,7 +6,6 @@ import itertools
from .amp import AMPIE from .amp import AMPIE
from ..compat import ( from ..compat import (
compat_HTTPError, compat_HTTPError,
compat_urllib_parse,
compat_urlparse, compat_urlparse,
) )
from ..utils import ( from ..utils import (
@ -14,6 +13,7 @@ from ..utils import (
clean_html, clean_html,
int_or_none, int_or_none,
sanitized_Request, sanitized_Request,
urlencode_postdata
) )
@ -50,7 +50,7 @@ class DramaFeverBaseIE(AMPIE):
} }
request = sanitized_Request( request = sanitized_Request(
self._LOGIN_URL, compat_urllib_parse.urlencode(login_form).encode('utf-8')) self._LOGIN_URL, urlencode_postdata(login_form))
response = self._download_webpage( response = self._download_webpage(
request, None, 'Logging in as %s' % username) request, None, 'Logging in as %s' % username)

View File

@ -39,13 +39,13 @@ class DWIE(InfoExtractor):
hidden_inputs = self._hidden_inputs(webpage) hidden_inputs = self._hidden_inputs(webpage)
title = hidden_inputs['media_title'] title = hidden_inputs['media_title']
formats = []
if hidden_inputs.get('player_type') == 'video' and hidden_inputs.get('stream_file') == '1': if hidden_inputs.get('player_type') == 'video' and hidden_inputs.get('stream_file') == '1':
formats = self._extract_smil_formats( formats = self._extract_smil_formats(
'http://www.dw.com/smil/v-%s' % media_id, media_id, 'http://www.dw.com/smil/v-%s' % media_id, media_id,
transform_source=lambda s: s.replace( transform_source=lambda s: s.replace(
'rtmp://tv-od.dw.de/flash/', 'rtmp://tv-od.dw.de/flash/',
'http://tv-download.dw.de/dwtv_video/flv/')) 'http://tv-download.dw.de/dwtv_video/flv/'))
self._sort_formats(formats)
else: else:
formats = [{'url': hidden_inputs['file_name']}] formats = [{'url': hidden_inputs['file_name']}]

View File

@ -3,7 +3,7 @@ from __future__ import unicode_literals
import re import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse from ..compat import compat_urllib_parse_urlencode
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
unescapeHTML unescapeHTML
@ -43,7 +43,7 @@ class EroProfileIE(InfoExtractor):
if username is None: if username is None:
return return
query = compat_urllib_parse.urlencode({ query = compat_urllib_parse_urlencode({
'username': username, 'username': username,
'password': password, 'password': password,
'url': 'http://www.eroprofile.com/', 'url': 'http://www.eroprofile.com/',

View File

@ -5,14 +5,13 @@ import hashlib
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse,
compat_urllib_request, compat_urllib_request,
compat_urlparse, compat_urlparse,
) )
from ..utils import ( from ..utils import (
encode_dict,
ExtractorError, ExtractorError,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -57,7 +56,7 @@ class FC2IE(InfoExtractor):
'Submit': ' Login ', 'Submit': ' Login ',
} }
login_data = compat_urllib_parse.urlencode(encode_dict(login_form_strs)).encode('utf-8') login_data = urlencode_postdata(login_form_strs)
request = sanitized_Request( request = sanitized_Request(
'https://secure.id.fc2.com/index.php?mode=login&switch_language=en', login_data) 'https://secure.id.fc2.com/index.php?mode=login&switch_language=en', login_data)

View File

@ -4,8 +4,8 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse,
compat_parse_qs, compat_parse_qs,
compat_urllib_parse_urlencode,
compat_urllib_parse_urlparse, compat_urllib_parse_urlparse,
compat_urlparse, compat_urlparse,
) )
@ -109,7 +109,7 @@ class FiveMinIE(InfoExtractor):
response = self._download_json( response = self._download_json(
'https://syn.5min.com/handlers/SenseHandler.ashx?' + 'https://syn.5min.com/handlers/SenseHandler.ashx?' +
compat_urllib_parse.urlencode({ compat_urllib_parse_urlencode({
'func': 'GetResults', 'func': 'GetResults',
'playlist': video_id, 'playlist': video_id,
'sid': sid, 'sid': sid,

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse from ..compat import compat_urllib_parse_urlencode
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
int_or_none, int_or_none,
@ -42,7 +42,7 @@ class FlickrIE(InfoExtractor):
} }
if secret: if secret:
query['secret'] = secret query['secret'] = secret
data = self._download_json(self._API_BASE_URL + compat_urllib_parse.urlencode(query), video_id, note) data = self._download_json(self._API_BASE_URL + compat_urllib_parse_urlencode(query), video_id, note)
if data['stat'] != 'ok': if data['stat'] != 'ok':
raise ExtractorError(data['message']) raise ExtractorError(data['message'])
return data return data

View File

@ -18,8 +18,8 @@ class FoxNewsIE(AMPIE):
'title': 'Frozen in Time', 'title': 'Frozen in Time',
'description': '16-year-old girl is size of toddler', 'description': '16-year-old girl is size of toddler',
'duration': 265, 'duration': 265,
# 'timestamp': 1304411491, 'timestamp': 1304411491,
# 'upload_date': '20110503', 'upload_date': '20110503',
'thumbnail': 're:^https?://.*\.jpg$', 'thumbnail': 're:^https?://.*\.jpg$',
}, },
}, },
@ -32,8 +32,8 @@ class FoxNewsIE(AMPIE):
'title': "Rep. Luis Gutierrez on if Obama's immigration plan is legal", 'title': "Rep. Luis Gutierrez on if Obama's immigration plan is legal",
'description': "Congressman discusses president's plan", 'description': "Congressman discusses president's plan",
'duration': 292, 'duration': 292,
# 'timestamp': 1417662047, 'timestamp': 1417662047,
# 'upload_date': '20141204', 'upload_date': '20141204',
'thumbnail': 're:^https?://.*\.jpg$', 'thumbnail': 're:^https?://.*\.jpg$',
}, },
'params': { 'params': {

View File

@ -5,7 +5,6 @@ from .common import InfoExtractor
from ..utils import ( from ..utils import (
clean_html, clean_html,
determine_ext, determine_ext,
encode_dict,
int_or_none, int_or_none,
sanitized_Request, sanitized_Request,
ExtractorError, ExtractorError,
@ -54,10 +53,10 @@ class FunimationIE(InfoExtractor):
(username, password) = self._get_login_info() (username, password) = self._get_login_info()
if username is None: if username is None:
return return
data = urlencode_postdata(encode_dict({ data = urlencode_postdata({
'email_field': username, 'email_field': username,
'password_field': password, 'password_field': password,
})) })
login_request = sanitized_Request('http://www.funimation.com/login', data, headers={ login_request = sanitized_Request('http://www.funimation.com/login', data, headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 5.2; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0', 'User-Agent': 'Mozilla/5.0 (Windows NT 5.2; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0',
'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': 'application/x-www-form-urlencoded'

View File

@ -3,11 +3,11 @@ from __future__ import unicode_literals
import re import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse
from ..utils import ( from ..utils import (
remove_end, remove_end,
HEADRequest, HEADRequest,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -123,7 +123,7 @@ class GDCVaultIE(InfoExtractor):
'password': password, 'password': password,
} }
request = sanitized_Request(login_url, compat_urllib_parse.urlencode(login_form)) request = sanitized_Request(login_url, urlencode_postdata(login_form))
request.add_header('Content-Type', 'application/x-www-form-urlencoded') request.add_header('Content-Type', 'application/x-www-form-urlencoded')
self._download_webpage(request, display_id, 'Logging in') self._download_webpage(request, display_id, 'Logging in')
start_page = self._download_webpage(webpage_url, display_id, 'Getting authenticated video page') start_page = self._download_webpage(webpage_url, display_id, 'Getting authenticated video page')

View File

@ -1124,7 +1124,23 @@ class GenericIE(InfoExtractor):
# m3u8 downloads # m3u8 downloads
'skip_download': True, 'skip_download': True,
} }
} },
# Brightcove embed, with no valid 'renditions' but valid 'IOSRenditions'
# This video can't be played in browsers if Flash disabled and UA set to iPhone, which is actually a false alarm
{
'url': 'https://dl.dropboxusercontent.com/u/29092637/interview.html',
'info_dict': {
'id': '4785848093001',
'ext': 'mp4',
'title': 'The Cardinal Pell Interview',
'description': 'Sky News Contributor Andrew Bolt interviews George Pell in Rome, following the Cardinal\'s evidence before the Royal Commission into Child Abuse. ',
'uploader': 'GlobeCast Australia - GlobeStream',
},
'params': {
# m3u8 downloads
'skip_download': True,
},
},
] ]
def report_following_redirect(self, new_url): def report_following_redirect(self, new_url):
@ -1294,6 +1310,7 @@ class GenericIE(InfoExtractor):
'vcodec': 'none' if m.group('type') == 'audio' else None 'vcodec': 'none' if m.group('type') == 'audio' else None
}] }]
info_dict['direct'] = True info_dict['direct'] = True
self._sort_formats(formats)
info_dict['formats'] = formats info_dict['formats'] = formats
return info_dict return info_dict
@ -1320,6 +1337,7 @@ class GenericIE(InfoExtractor):
# Is it an M3U playlist? # Is it an M3U playlist?
if first_bytes.startswith(b'#EXTM3U'): if first_bytes.startswith(b'#EXTM3U'):
info_dict['formats'] = self._extract_m3u8_formats(url, video_id, 'mp4') info_dict['formats'] = self._extract_m3u8_formats(url, video_id, 'mp4')
self._sort_formats(info_dict['formats'])
return info_dict return info_dict
# Maybe it's a direct link to a video? # Maybe it's a direct link to a video?
@ -1344,15 +1362,19 @@ class GenericIE(InfoExtractor):
if doc.tag == 'rss': if doc.tag == 'rss':
return self._extract_rss(url, video_id, doc) return self._extract_rss(url, video_id, doc)
elif re.match(r'^(?:{[^}]+})?smil$', doc.tag): elif re.match(r'^(?:{[^}]+})?smil$', doc.tag):
return self._parse_smil(doc, url, video_id) smil = self._parse_smil(doc, url, video_id)
self._sort_formats(smil['formats'])
return smil
elif doc.tag == '{http://xspf.org/ns/0/}playlist': elif doc.tag == '{http://xspf.org/ns/0/}playlist':
return self.playlist_result(self._parse_xspf(doc, video_id), video_id) return self.playlist_result(self._parse_xspf(doc, video_id), video_id)
elif re.match(r'(?i)^(?:{[^}]+})?MPD$', doc.tag): elif re.match(r'(?i)^(?:{[^}]+})?MPD$', doc.tag):
info_dict['formats'] = self._parse_mpd_formats( info_dict['formats'] = self._parse_mpd_formats(
doc, video_id, mpd_base_url=url.rpartition('/')[0]) doc, video_id, mpd_base_url=url.rpartition('/')[0])
self._sort_formats(info_dict['formats'])
return info_dict return info_dict
elif re.match(r'^{http://ns\.adobe\.com/f4m/[12]\.0}manifest$', doc.tag): elif re.match(r'^{http://ns\.adobe\.com/f4m/[12]\.0}manifest$', doc.tag):
info_dict['formats'] = self._parse_f4m_formats(doc, url, video_id) info_dict['formats'] = self._parse_f4m_formats(doc, url, video_id)
self._sort_formats(info_dict['formats'])
return info_dict return info_dict
except compat_xml_parse_error: except compat_xml_parse_error:
pass pass
@ -2037,6 +2059,9 @@ class GenericIE(InfoExtractor):
else: else:
entry_info_dict['url'] = video_url entry_info_dict['url'] = video_url
if entry_info_dict.get('formats'):
self._sort_formats(entry_info_dict['formats'])
entries.append(entry_info_dict) entries.append(entry_info_dict)
if len(entries) == 1: if len(entries) == 1:

View File

@ -3,11 +3,11 @@ from __future__ import unicode_literals
import base64 import base64
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
HEADRequest, HEADRequest,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -35,7 +35,7 @@ class HotNewHipHopIE(InfoExtractor):
r'"contentUrl" content="(.*?)"', webpage, 'content URL') r'"contentUrl" content="(.*?)"', webpage, 'content URL')
return self.url_result(video_url, ie='Youtube') return self.url_result(video_url, ie='Youtube')
reqdata = compat_urllib_parse.urlencode([ reqdata = urlencode_postdata([
('mediaType', 's'), ('mediaType', 's'),
('mediaId', video_id), ('mediaId', video_id),
]) ])

View File

@ -4,7 +4,7 @@ import json
import time import time
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse from ..compat import compat_urllib_parse_urlencode
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
sanitized_Request, sanitized_Request,
@ -28,7 +28,7 @@ class HypemIE(InfoExtractor):
track_id = self._match_id(url) track_id = self._match_id(url)
data = {'ax': 1, 'ts': time.time()} data = {'ax': 1, 'ts': time.time()}
request = sanitized_Request(url + '?' + compat_urllib_parse.urlencode(data)) request = sanitized_Request(url + '?' + compat_urllib_parse_urlencode(data))
response, urlh = self._download_webpage_handle( response, urlh = self._download_webpage_handle(
request, track_id, 'Downloading webpage with the url') request, track_id, 'Downloading webpage with the url')

View File

@ -5,7 +5,7 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urlparse, compat_urlparse,
compat_urllib_parse, compat_urllib_parse_urlencode,
) )
from ..utils import ( from ..utils import (
xpath_with_ns, xpath_with_ns,
@ -38,7 +38,7 @@ class InternetVideoArchiveIE(InfoExtractor):
# Other player ids return m3u8 urls # Other player ids return m3u8 urls
cleaned_dic['playerid'] = '247' cleaned_dic['playerid'] = '247'
cleaned_dic['videokbrate'] = '100000' cleaned_dic['videokbrate'] = '100000'
return compat_urllib_parse.urlencode(cleaned_dic) return compat_urllib_parse_urlencode(cleaned_dic)
def _real_extract(self, url): def _real_extract(self, url):
query = compat_urlparse.urlparse(url).query query = compat_urlparse.urlparse(url).query

View File

@ -14,7 +14,7 @@ from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_parse_qs, compat_parse_qs,
compat_str, compat_str,
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urllib_parse_urlparse, compat_urllib_parse_urlparse,
) )
from ..utils import ( from ..utils import (
@ -322,7 +322,7 @@ class IqiyiIE(InfoExtractor):
'bird_t': timestamp, 'bird_t': timestamp,
} }
validation_result = self._download_json( validation_result = self._download_json(
'http://kylin.iqiyi.com/validate?' + compat_urllib_parse.urlencode(validation_params), None, 'http://kylin.iqiyi.com/validate?' + compat_urllib_parse_urlencode(validation_params), None,
note='Validate credentials', errnote='Unable to validate credentials') note='Validate credentials', errnote='Unable to validate credentials')
MSG_MAP = { MSG_MAP = {
@ -456,7 +456,7 @@ class IqiyiIE(InfoExtractor):
'QY00001': auth_result['data']['u'], 'QY00001': auth_result['data']['u'],
}) })
api_video_url += '?' if '?' not in api_video_url else '&' api_video_url += '?' if '?' not in api_video_url else '&'
api_video_url += compat_urllib_parse.urlencode(param) api_video_url += compat_urllib_parse_urlencode(param)
js = self._download_json( js = self._download_json(
api_video_url, video_id, api_video_url, video_id,
note='Download video info of segment %d for format %s' % (segment_index + 1, format_id)) note='Download video info of segment %d for format %s' % (segment_index + 1, format_id))
@ -494,7 +494,7 @@ class IqiyiIE(InfoExtractor):
} }
api_url = 'http://cache.video.qiyi.com/vms' + '?' + \ api_url = 'http://cache.video.qiyi.com/vms' + '?' + \
compat_urllib_parse.urlencode(param) compat_urllib_parse_urlencode(param)
raw_data = self._download_json(api_url, video_id) raw_data = self._download_json(api_url, video_id)
return raw_data return raw_data

View File

@ -5,7 +5,7 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urlparse, compat_urlparse,
) )
from ..utils import qualities from ..utils import qualities
@ -62,7 +62,7 @@ class IvideonIE(InfoExtractor):
quality = qualities(self._QUALITIES) quality = qualities(self._QUALITIES)
formats = [{ formats = [{
'url': 'https://streaming.ivideon.com/flv/live?%s' % compat_urllib_parse.urlencode({ 'url': 'https://streaming.ivideon.com/flv/live?%s' % compat_urllib_parse_urlencode({
'server': server_id, 'server': server_id,
'camera': camera_id, 'camera': camera_id,
'sessionId': 'demo', 'sessionId': 'demo',

View File

@ -6,7 +6,7 @@ import base64
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urlparse, compat_urlparse,
compat_parse_qs, compat_parse_qs,
) )
@ -71,7 +71,7 @@ class KalturaIE(InfoExtractor):
for k, v in a.items(): for k, v in a.items():
params['%d:%s' % (i, k)] = v params['%d:%s' % (i, k)] = v
query = compat_urllib_parse.urlencode(params) query = compat_urllib_parse_urlencode(params)
url = self._API_BASE + query url = self._API_BASE + query
data = self._download_json(url, video_id, *args, **kwargs) data = self._download_json(url, video_id, *args, **kwargs)

View File

@ -26,10 +26,23 @@ class KuwoBaseIE(InfoExtractor):
def _get_formats(self, song_id, tolerate_ip_deny=False): def _get_formats(self, song_id, tolerate_ip_deny=False):
formats = [] formats = []
for file_format in self._FORMATS: for file_format in self._FORMATS:
headers = {}
cn_verification_proxy = self._downloader.params.get('cn_verification_proxy')
if cn_verification_proxy:
headers['Ytdl-request-proxy'] = cn_verification_proxy
query = {
'format': file_format['ext'],
'br': file_format.get('br', ''),
'rid': 'MUSIC_%s' % song_id,
'type': 'convert_url',
'response': 'url'
}
song_url = self._download_webpage( song_url = self._download_webpage(
'http://antiserver.kuwo.cn/anti.s?format=%s&br=%s&rid=MUSIC_%s&type=convert_url&response=url' % 'http://antiserver.kuwo.cn/anti.s',
(file_format['ext'], file_format.get('br', ''), song_id),
song_id, note='Download %s url info' % file_format['format'], song_id, note='Download %s url info' % file_format['format'],
query=query, headers=headers,
) )
if song_url == 'IPDeny' and not tolerate_ip_deny: if song_url == 'IPDeny' and not tolerate_ip_deny:
@ -44,18 +57,13 @@ class KuwoBaseIE(InfoExtractor):
'abr': file_format.get('abr'), 'abr': file_format.get('abr'),
}) })
# XXX _sort_formats fails if there are not formats, while it's not the
# desired behavior if 'IPDeny' is ignored
# This check can be removed if https://github.com/rg3/youtube-dl/pull/8051 is merged
if not tolerate_ip_deny:
self._sort_formats(formats)
return formats return formats
class KuwoIE(KuwoBaseIE): class KuwoIE(KuwoBaseIE):
IE_NAME = 'kuwo:song' IE_NAME = 'kuwo:song'
IE_DESC = '酷我音乐' IE_DESC = '酷我音乐'
_VALID_URL = r'https?://www\.kuwo\.cn/yinyue/(?P<id>\d+?)' _VALID_URL = r'https?://www\.kuwo\.cn/yinyue/(?P<id>\d+)'
_TESTS = [{ _TESTS = [{
'url': 'http://www.kuwo.cn/yinyue/635632/', 'url': 'http://www.kuwo.cn/yinyue/635632/',
'info_dict': { 'info_dict': {
@ -103,6 +111,7 @@ class KuwoIE(KuwoBaseIE):
lrc_content = None lrc_content = None
formats = self._get_formats(song_id) formats = self._get_formats(song_id)
self._sort_formats(formats)
album_id = self._html_search_regex( album_id = self._html_search_regex(
r'<p[^>]+class="album"[^<]+<a[^>]+href="http://www\.kuwo\.cn/album/(\d+)/"', r'<p[^>]+class="album"[^<]+<a[^>]+href="http://www\.kuwo\.cn/album/(\d+)/"',

View File

@ -5,7 +5,7 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urlparse, compat_urlparse,
) )
from ..utils import ( from ..utils import (
@ -90,7 +90,7 @@ class Laola1TvIE(InfoExtractor):
hd_doc = self._download_xml( hd_doc = self._download_xml(
'http://www.laola1.tv/server/hd_video.php?%s' 'http://www.laola1.tv/server/hd_video.php?%s'
% compat_urllib_parse.urlencode({ % compat_urllib_parse_urlencode({
'play': video_id, 'play': video_id,
'partner': partner_id, 'partner': partner_id,
'portal': portal, 'portal': portal,
@ -108,7 +108,7 @@ class Laola1TvIE(InfoExtractor):
req = sanitized_Request( req = sanitized_Request(
'https://club.laola1.tv/sp/laola1/api/v3/user/session/premium/player/stream-access?%s' % 'https://club.laola1.tv/sp/laola1/api/v3/user/session/premium/player/stream-access?%s' %
compat_urllib_parse.urlencode({ compat_urllib_parse_urlencode({
'videoId': video_id, 'videoId': video_id,
'target': VS_TARGETS.get(kind, '2'), 'target': VS_TARGETS.get(kind, '2'),
'label': _v('label'), 'label': _v('label'),
@ -130,6 +130,7 @@ class Laola1TvIE(InfoExtractor):
formats = self._extract_f4m_formats( formats = self._extract_f4m_formats(
'%s?hdnea=%s&hdcore=3.2.0' % (token_attrib['url'], token_auth), '%s?hdnea=%s&hdcore=3.2.0' % (token_attrib['url'], token_auth),
video_id, f4m_id='hds') video_id, f4m_id='hds')
self._sort_formats(formats)
categories_str = _v('meta_sports') categories_str = _v('meta_sports')
categories = categories_str.split(',') if categories_str else [] categories = categories_str.split(',') if categories_str else []

View File

@ -11,7 +11,7 @@ from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_ord, compat_ord,
compat_str, compat_str,
compat_urllib_parse, compat_urllib_parse_urlencode,
) )
from ..utils import ( from ..utils import (
determine_ext, determine_ext,
@ -122,7 +122,7 @@ class LeIE(InfoExtractor):
'domain': 'www.le.com' 'domain': 'www.le.com'
} }
play_json_req = sanitized_Request( play_json_req = sanitized_Request(
'http://api.le.com/mms/out/video/playJson?' + compat_urllib_parse.urlencode(params) 'http://api.le.com/mms/out/video/playJson?' + compat_urllib_parse_urlencode(params)
) )
cn_verification_proxy = self._downloader.params.get('cn_verification_proxy') cn_verification_proxy = self._downloader.params.get('cn_verification_proxy')
if cn_verification_proxy: if cn_verification_proxy:
@ -151,7 +151,7 @@ class LeIE(InfoExtractor):
for format_id in formats: for format_id in formats:
if format_id in dispatch: if format_id in dispatch:
media_url = playurl['domain'][0] + dispatch[format_id][0] media_url = playurl['domain'][0] + dispatch[format_id][0]
media_url += '&' + compat_urllib_parse.urlencode({ media_url += '&' + compat_urllib_parse_urlencode({
'm3v': 1, 'm3v': 1,
'format': 1, 'format': 1,
'expect': 3, 'expect': 3,
@ -305,7 +305,7 @@ class LetvCloudIE(InfoExtractor):
} }
self.sign_data(data) self.sign_data(data)
return self._download_json( return self._download_json(
'http://api.letvcloud.com/gpc.php?' + compat_urllib_parse.urlencode(data), 'http://api.letvcloud.com/gpc.php?' + compat_urllib_parse_urlencode(data),
media_id, 'Downloading playJson data for type %s' % cf) media_id, 'Downloading playJson data for type %s' % cf)
play_json = get_play_json(cf, time.time()) play_json = get_play_json(cf, time.time())

View File

@ -37,6 +37,7 @@ class LRTIE(InfoExtractor):
r'file\s*:\s*(["\'])(?P<url>.+?)\1\s*\+\s*location\.hash\.substring\(1\)', r'file\s*:\s*(["\'])(?P<url>.+?)\1\s*\+\s*location\.hash\.substring\(1\)',
webpage, 'm3u8 url', group='url') webpage, 'm3u8 url', group='url')
formats = self._extract_m3u8_formats(m3u8_url, video_id, 'mp4') formats = self._extract_m3u8_formats(m3u8_url, video_id, 'mp4')
self._sort_formats(formats)
thumbnail = self._og_search_thumbnail(webpage) thumbnail = self._og_search_thumbnail(webpage)
description = self._og_search_description(webpage) description = self._og_search_description(webpage)

View File

@ -4,15 +4,13 @@ import re
import json import json
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import compat_str
compat_str,
compat_urllib_parse,
)
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
clean_html, clean_html,
int_or_none, int_or_none,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -36,7 +34,7 @@ class LyndaBaseIE(InfoExtractor):
'stayPut': 'false' 'stayPut': 'false'
} }
request = sanitized_Request( request = sanitized_Request(
self._LOGIN_URL, compat_urllib_parse.urlencode(login_form).encode('utf-8')) self._LOGIN_URL, urlencode_postdata(login_form))
login_page = self._download_webpage( login_page = self._download_webpage(
request, None, 'Logging in as %s' % username) request, None, 'Logging in as %s' % username)
@ -65,7 +63,7 @@ class LyndaBaseIE(InfoExtractor):
'stayPut': 'false', 'stayPut': 'false',
} }
request = sanitized_Request( request = sanitized_Request(
self._LOGIN_URL, compat_urllib_parse.urlencode(confirm_form).encode('utf-8')) self._LOGIN_URL, urlencode_postdata(confirm_form))
login_page = self._download_webpage( login_page = self._download_webpage(
request, None, request, None,
'Confirming log in and log out from another device') 'Confirming log in and log out from another device')
@ -221,7 +219,7 @@ class LyndaCourseIE(LyndaBaseIE):
'Course %s does not exist' % course_id, expected=True) 'Course %s does not exist' % course_id, expected=True)
unaccessible_videos = 0 unaccessible_videos = 0
videos = [] entries = []
# Might want to extract videos right here from video['Formats'] as it seems 'Formats' is not provided # Might want to extract videos right here from video['Formats'] as it seems 'Formats' is not provided
# by single video API anymore # by single video API anymore
@ -231,20 +229,22 @@ class LyndaCourseIE(LyndaBaseIE):
if video.get('HasAccess') is False: if video.get('HasAccess') is False:
unaccessible_videos += 1 unaccessible_videos += 1
continue continue
if video.get('ID'): video_id = video.get('ID')
videos.append(video['ID']) if video_id:
entries.append({
'_type': 'url_transparent',
'url': 'http://www.lynda.com/%s/%s-4.html' % (course_path, video_id),
'ie_key': LyndaIE.ie_key(),
'chapter': chapter.get('Title'),
'chapter_number': int_or_none(chapter.get('ChapterIndex')),
'chapter_id': compat_str(chapter.get('ID')),
})
if unaccessible_videos > 0: if unaccessible_videos > 0:
self._downloader.report_warning( self._downloader.report_warning(
'%s videos are only available for members (or paid members) and will not be downloaded. ' '%s videos are only available for members (or paid members) and will not be downloaded. '
% unaccessible_videos + self._ACCOUNT_CREDENTIALS_HINT) % unaccessible_videos + self._ACCOUNT_CREDENTIALS_HINT)
entries = [
self.url_result(
'http://www.lynda.com/%s/%s-4.html' % (course_path, video_id),
'Lynda')
for video_id in videos]
course_title = course.get('Title') course_title = course.get('Title')
return self.playlist_result(entries, course_id, course_title) return self.playlist_result(entries, course_id, course_title)

View File

@ -13,7 +13,7 @@ from ..utils import (
class MailRuIE(InfoExtractor): class MailRuIE(InfoExtractor):
IE_NAME = 'mailru' IE_NAME = 'mailru'
IE_DESC = 'Видео@Mail.Ru' IE_DESC = 'Видео@Mail.Ru'
_VALID_URL = r'https?://(?:www\.)?my\.mail\.ru/(?:video/.*#video=/?(?P<idv1>(?:[^/]+/){3}\d+)|(?:(?P<idv2prefix>(?:[^/]+/){2})video/(?P<idv2suffix>[^/]+/\d+))\.html)' _VALID_URL = r'https?://(?:(?:www|m)\.)?my\.mail\.ru/(?:video/.*#video=/?(?P<idv1>(?:[^/]+/){3}\d+)|(?:(?P<idv2prefix>(?:[^/]+/){2})video/(?P<idv2suffix>[^/]+/\d+))\.html)'
_TESTS = [ _TESTS = [
{ {
@ -61,6 +61,10 @@ class MailRuIE(InfoExtractor):
'duration': 6001, 'duration': 6001,
}, },
'skip': 'Not accessible from Travis CI server', 'skip': 'Not accessible from Travis CI server',
},
{
'url': 'http://m.my.mail.ru/mail/3sktvtr/video/_myvideo/138.html',
'only_matching': True,
} }
] ]

View File

@ -4,7 +4,7 @@ from __future__ import unicode_literals
import random import random
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse from ..compat import compat_urllib_parse_urlencode
from ..utils import ( from ..utils import (
sanitized_Request, sanitized_Request,
xpath_text, xpath_text,
@ -29,7 +29,7 @@ class MatchTVIE(InfoExtractor):
def _real_extract(self, url): def _real_extract(self, url):
video_id = 'matchtv-live' video_id = 'matchtv-live'
request = sanitized_Request( request = sanitized_Request(
'http://player.matchtv.ntvplus.tv/player/smil?%s' % compat_urllib_parse.urlencode({ 'http://player.matchtv.ntvplus.tv/player/smil?%s' % compat_urllib_parse_urlencode({
'ts': '', 'ts': '',
'quality': 'SD', 'quality': 'SD',
'contentId': '561d2c0df7159b37178b4567', 'contentId': '561d2c0df7159b37178b4567',
@ -47,6 +47,7 @@ class MatchTVIE(InfoExtractor):
video_url = self._download_json(request, video_id)['data']['videoUrl'] video_url = self._download_json(request, video_id)['data']['videoUrl']
f4m_url = xpath_text(self._download_xml(video_url, video_id), './to') f4m_url = xpath_text(self._download_xml(video_url, video_id), './to')
formats = self._extract_f4m_formats(f4m_url, video_id) formats = self._extract_f4m_formats(f4m_url, video_id)
self._sort_formats(formats)
return { return {
'id': video_id, 'id': video_id,
'title': self._live_title('Матч ТВ - Прямой эфир'), 'title': self._live_title('Матч ТВ - Прямой эфир'),

View File

@ -5,7 +5,6 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_parse_qs, compat_parse_qs,
compat_urllib_parse,
compat_urllib_parse_unquote, compat_urllib_parse_unquote,
) )
from ..utils import ( from ..utils import (
@ -13,6 +12,7 @@ from ..utils import (
ExtractorError, ExtractorError,
int_or_none, int_or_none,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -117,7 +117,7 @@ class MetacafeIE(InfoExtractor):
'filters': '0', 'filters': '0',
'submit': "Continue - I'm over 18", 'submit': "Continue - I'm over 18",
} }
request = sanitized_Request(self._FILTER_POST, compat_urllib_parse.urlencode(disclaimer_form)) request = sanitized_Request(self._FILTER_POST, urlencode_postdata(disclaimer_form))
request.add_header('Content-Type', 'application/x-www-form-urlencoded') request.add_header('Content-Type', 'application/x-www-form-urlencoded')
self.report_age_confirmation() self.report_age_confirmation()
self._download_webpage(request, None, False, 'Unable to confirm age') self._download_webpage(request, None, False, 'Unable to confirm age')

View File

@ -2,12 +2,12 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse
from ..utils import ( from ..utils import (
int_or_none, int_or_none,
parse_duration, parse_duration,
parse_filesize, parse_filesize,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -39,7 +39,7 @@ class MinhatecaIE(InfoExtractor):
] ]
req = sanitized_Request( req = sanitized_Request(
'http://minhateca.com.br/action/License/Download', 'http://minhateca.com.br/action/License/Download',
data=compat_urllib_parse.urlencode(token_data)) data=urlencode_postdata(token_data))
req.add_header('Content-Type', 'application/x-www-form-urlencoded') req.add_header('Content-Type', 'application/x-www-form-urlencoded')
data = self._download_json( data = self._download_json(
req, video_id, note='Downloading metadata') req, video_id, note='Downloading metadata')

View File

@ -2,11 +2,10 @@ from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urlparse, compat_urlparse,
) )
from ..utils import ( from ..utils import (
encode_dict,
get_element_by_attribute, get_element_by_attribute,
int_or_none, int_or_none,
) )
@ -60,7 +59,7 @@ class MiTeleIE(InfoExtractor):
'sta': '0', 'sta': '0',
} }
media = self._download_json( media = self._download_json(
'%s/?%s' % (gat, compat_urllib_parse.urlencode(encode_dict(token_data))), '%s/?%s' % (gat, compat_urllib_parse_urlencode(token_data)),
display_id, 'Downloading %s JSON' % location['loc']) display_id, 'Downloading %s JSON' % location['loc'])
file_ = media.get('file') file_ = media.get('file')
if not file_: if not file_:
@ -68,6 +67,7 @@ class MiTeleIE(InfoExtractor):
formats.extend(self._extract_f4m_formats( formats.extend(self._extract_f4m_formats(
file_ + '&hdcore=3.2.0&plugin=aasp-3.2.0.77.18', file_ + '&hdcore=3.2.0&plugin=aasp-3.2.0.77.18',
display_id, f4m_id=loc)) display_id, f4m_id=loc))
self._sort_formats(formats)
title = self._search_regex( title = self._search_regex(
r'class="Destacado-text"[^>]*>\s*<strong>([^<]+)</strong>', webpage, 'title') r'class="Destacado-text"[^>]*>\s*<strong>([^<]+)</strong>', webpage, 'title')

View File

@ -5,11 +5,11 @@ import json
import re import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
int_or_none, int_or_none,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -77,7 +77,7 @@ class MoeVideoIE(InfoExtractor):
], ],
] ]
r_json = json.dumps(r) r_json = json.dumps(r)
post = compat_urllib_parse.urlencode({'r': r_json}) post = urlencode_postdata({'r': r_json})
req = sanitized_Request(self._API_URL, post) req = sanitized_Request(self._API_URL, post)
req.add_header('Content-type', 'application/x-www-form-urlencoded') req.add_header('Content-type', 'application/x-www-form-urlencoded')

View File

@ -5,11 +5,11 @@ import os.path
import re import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
remove_start, remove_start,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -88,7 +88,7 @@ class MonikerIE(InfoExtractor):
fields = re.findall(r'type="hidden" name="(.+?)"\s* value="?(.+?)">', orig_webpage) fields = re.findall(r'type="hidden" name="(.+?)"\s* value="?(.+?)">', orig_webpage)
data = dict(fields) data = dict(fields)
post = compat_urllib_parse.urlencode(data) post = urlencode_postdata(data)
headers = { headers = {
b'Content-Type': b'application/x-www-form-urlencoded', b'Content-Type': b'application/x-www-form-urlencoded',
} }

View File

@ -3,10 +3,10 @@ from __future__ import unicode_literals
import re import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -58,7 +58,7 @@ class MooshareIE(InfoExtractor):
} }
request = sanitized_Request( request = sanitized_Request(
'http://mooshare.biz/%s' % video_id, compat_urllib_parse.urlencode(download_form)) 'http://mooshare.biz/%s' % video_id, urlencode_postdata(download_form))
request.add_header('Content-Type', 'application/x-www-form-urlencoded') request.add_header('Content-Type', 'application/x-www-form-urlencoded')
self._sleep(5, video_id) self._sleep(5, video_id)

View File

@ -4,7 +4,7 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_str, compat_str,
) )
from ..utils import ( from ..utils import (
@ -171,7 +171,7 @@ class MTVServicesInfoExtractor(InfoExtractor):
data = {'uri': uri} data = {'uri': uri}
if self._LANG: if self._LANG:
data['lang'] = self._LANG data['lang'] = self._LANG
return compat_urllib_parse.urlencode(data) return compat_urllib_parse_urlencode(data)
def _get_videos_info(self, uri): def _get_videos_info(self, uri):
video_id = self._id_from_uri(uri) video_id = self._id_from_uri(uri)

View File

@ -1,9 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import compat_urllib_parse_urlencode
compat_urllib_parse,
)
class MuzuTVIE(InfoExtractor): class MuzuTVIE(InfoExtractor):
@ -25,7 +23,7 @@ class MuzuTVIE(InfoExtractor):
def _real_extract(self, url): def _real_extract(self, url):
video_id = self._match_id(url) video_id = self._match_id(url)
info_data = compat_urllib_parse.urlencode({ info_data = compat_urllib_parse_urlencode({
'format': 'json', 'format': 'json',
'url': url, 'url': url,
}) })
@ -41,7 +39,7 @@ class MuzuTVIE(InfoExtractor):
if video_info.get('v%s' % quality): if video_info.get('v%s' % quality):
break break
data = compat_urllib_parse.urlencode({ data = compat_urllib_parse_urlencode({
'ai': video_id, 'ai': video_id,
# Even if each time you watch a video the hash changes, # Even if each time you watch a video the hash changes,
# it seems to work for different videos, and it will work # it seems to work for different videos, and it will work

View File

@ -2,13 +2,13 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import re import re
import json
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..utils import (
compat_str, ExtractorError,
int_or_none,
parse_iso8601,
) )
from ..utils import ExtractorError
class MySpaceIE(InfoExtractor): class MySpaceIE(InfoExtractor):
@ -24,6 +24,8 @@ class MySpaceIE(InfoExtractor):
'description': 'This country quartet was all smiles while playing a sold out show at the Pacific Amphitheatre in Orange County, California.', 'description': 'This country quartet was all smiles while playing a sold out show at the Pacific Amphitheatre in Orange County, California.',
'uploader': 'Five Minutes to the Stage', 'uploader': 'Five Minutes to the Stage',
'uploader_id': 'fiveminutestothestage', 'uploader_id': 'fiveminutestothestage',
'timestamp': 1414108751,
'upload_date': '20141023',
}, },
'params': { 'params': {
# rtmp download # rtmp download
@ -64,7 +66,7 @@ class MySpaceIE(InfoExtractor):
'ext': 'mp4', 'ext': 'mp4',
'title': 'Starset - First Light', 'title': 'Starset - First Light',
'description': 'md5:2d5db6c9d11d527683bcda818d332414', 'description': 'md5:2d5db6c9d11d527683bcda818d332414',
'uploader': 'Jacob Soren', 'uploader': 'Yumi K',
'uploader_id': 'SorenPromotions', 'uploader_id': 'SorenPromotions',
'upload_date': '20140725', 'upload_date': '20140725',
} }
@ -78,6 +80,19 @@ class MySpaceIE(InfoExtractor):
player_url = self._search_regex( player_url = self._search_regex(
r'playerSwf":"([^"?]*)', webpage, 'player URL') r'playerSwf":"([^"?]*)', webpage, 'player URL')
def rtmp_format_from_stream_url(stream_url, width=None, height=None):
rtmp_url, play_path = stream_url.split(';', 1)
return {
'format_id': 'rtmp',
'url': rtmp_url,
'play_path': play_path,
'player_url': player_url,
'protocol': 'rtmp',
'ext': 'flv',
'width': width,
'height': height,
}
if mobj.group('mediatype').startswith('music/song'): if mobj.group('mediatype').startswith('music/song'):
# songs don't store any useful info in the 'context' variable # songs don't store any useful info in the 'context' variable
song_data = self._search_regex( song_data = self._search_regex(
@ -93,8 +108,8 @@ class MySpaceIE(InfoExtractor):
return self._search_regex( return self._search_regex(
r'''data-%s=([\'"])(?P<data>.*?)\1''' % name, r'''data-%s=([\'"])(?P<data>.*?)\1''' % name,
song_data, name, default='', group='data') song_data, name, default='', group='data')
streamUrl = search_data('stream-url') stream_url = search_data('stream-url')
if not streamUrl: if not stream_url:
vevo_id = search_data('vevo-id') vevo_id = search_data('vevo-id')
youtube_id = search_data('youtube-id') youtube_id = search_data('youtube-id')
if vevo_id: if vevo_id:
@ -106,36 +121,47 @@ class MySpaceIE(InfoExtractor):
else: else:
raise ExtractorError( raise ExtractorError(
'Found song but don\'t know how to download it') 'Found song but don\'t know how to download it')
info = { return {
'id': video_id, 'id': video_id,
'title': self._og_search_title(webpage), 'title': self._og_search_title(webpage),
'uploader': search_data('artist-name'), 'uploader': search_data('artist-name'),
'uploader_id': search_data('artist-username'), 'uploader_id': search_data('artist-username'),
'thumbnail': self._og_search_thumbnail(webpage), 'thumbnail': self._og_search_thumbnail(webpage),
'duration': int_or_none(search_data('duration')),
'formats': [rtmp_format_from_stream_url(stream_url)]
} }
else: else:
context = json.loads(self._search_regex( video = self._parse_json(self._search_regex(
r'context = ({.*?});', webpage, 'context')) r'context = ({.*?});', webpage, 'context'),
video = context['video'] video_id)['video']
streamUrl = video['streamUrl'] formats = []
info = { hls_stream_url = video.get('hlsStreamUrl')
'id': compat_str(video['mediaId']), if hls_stream_url:
formats.append({
'format_id': 'hls',
'url': hls_stream_url,
'protocol': 'm3u8_native',
'ext': 'mp4',
})
stream_url = video.get('streamUrl')
if stream_url:
formats.append(rtmp_format_from_stream_url(
stream_url,
int_or_none(video.get('width')),
int_or_none(video.get('height'))))
self._sort_formats(formats)
return {
'id': video_id,
'title': video['title'], 'title': video['title'],
'description': video['description'], 'description': video.get('description'),
'thumbnail': video['imageUrl'], 'thumbnail': video.get('imageUrl'),
'uploader': video['artistName'], 'uploader': video.get('artistName'),
'uploader_id': video['artistUsername'], 'uploader_id': video.get('artistUsername'),
'duration': int_or_none(video.get('duration')),
'timestamp': parse_iso8601(video.get('dateAdded')),
'formats': formats,
} }
rtmp_url, play_path = streamUrl.split(';', 1)
info.update({
'url': rtmp_url,
'play_path': play_path,
'player_url': player_url,
'ext': 'flv',
})
return info
class MySpaceAlbumIE(InfoExtractor): class MySpaceAlbumIE(InfoExtractor):
IE_NAME = 'MySpace:album' IE_NAME = 'MySpace:album'

View File

@ -9,8 +9,8 @@ import json
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_ord, compat_ord,
compat_urllib_parse,
compat_urllib_parse_unquote, compat_urllib_parse_unquote,
compat_urllib_parse_urlencode,
) )
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
@ -112,7 +112,7 @@ class MyVideoIE(InfoExtractor):
encxml = compat_urllib_parse_unquote(b) encxml = compat_urllib_parse_unquote(b)
if not params.get('domain'): if not params.get('domain'):
params['domain'] = 'www.myvideo.de' params['domain'] = 'www.myvideo.de'
xmldata_url = '%s?%s' % (encxml, compat_urllib_parse.urlencode(params)) xmldata_url = '%s?%s' % (encxml, compat_urllib_parse_urlencode(params))
if 'flash_playertype=MTV' in xmldata_url: if 'flash_playertype=MTV' in xmldata_url:
self._downloader.report_warning('avoiding MTV player') self._downloader.report_warning('avoiding MTV player')
xmldata_url = ( xmldata_url = (

View File

@ -5,7 +5,7 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urlparse, compat_urlparse,
) )
from ..utils import ( from ..utils import (
@ -53,8 +53,8 @@ class NaverIE(InfoExtractor):
raise ExtractorError('couldn\'t extract vid and key') raise ExtractorError('couldn\'t extract vid and key')
vid = m_id.group(1) vid = m_id.group(1)
key = m_id.group(2) key = m_id.group(2)
query = compat_urllib_parse.urlencode({'vid': vid, 'inKey': key, }) query = compat_urllib_parse_urlencode({'vid': vid, 'inKey': key, })
query_urls = compat_urllib_parse.urlencode({ query_urls = compat_urllib_parse_urlencode({
'masterVid': vid, 'masterVid': vid,
'protocol': 'p2p', 'protocol': 'p2p',
'inKey': key, 'inKey': key,

View File

@ -6,7 +6,7 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urlparse, compat_urlparse,
) )
from ..utils import ( from ..utils import (
@ -97,7 +97,7 @@ class NBAIE(InfoExtractor):
_PAGE_SIZE = 30 _PAGE_SIZE = 30
def _fetch_page(self, team, video_id, page): def _fetch_page(self, team, video_id, page):
search_url = 'http://searchapp2.nba.com/nba-search/query.jsp?' + compat_urllib_parse.urlencode({ search_url = 'http://searchapp2.nba.com/nba-search/query.jsp?' + compat_urllib_parse_urlencode({
'type': 'teamvideo', 'type': 'teamvideo',
'start': page * self._PAGE_SIZE + 1, 'start': page * self._PAGE_SIZE + 1,
'npp': (page + 1) * self._PAGE_SIZE + 1, 'npp': (page + 1) * self._PAGE_SIZE + 1,

View File

@ -134,6 +134,30 @@ class NBCSportsIE(InfoExtractor):
NBCSportsVPlayerIE._extract_url(webpage), 'NBCSportsVPlayer') NBCSportsVPlayerIE._extract_url(webpage), 'NBCSportsVPlayer')
class CSNNEIE(InfoExtractor):
_VALID_URL = r'https?://www\.csnne\.com/video/(?P<id>[0-9a-z-]+)'
_TEST = {
'url': 'http://www.csnne.com/video/snc-evening-update-wright-named-red-sox-no-5-starter',
'info_dict': {
'id': 'yvBLLUgQ8WU0',
'ext': 'mp4',
'title': 'SNC evening update: Wright named Red Sox\' No. 5 starter.',
'description': 'md5:1753cfee40d9352b19b4c9b3e589b9e3',
}
}
def _real_extract(self, url):
display_id = self._match_id(url)
webpage = self._download_webpage(url, display_id)
return {
'_type': 'url_transparent',
'ie_key': 'ThePlatform',
'url': self._html_search_meta('twitter:player:stream', webpage),
'display_id': display_id,
}
class NBCNewsIE(ThePlatformIE): class NBCNewsIE(ThePlatformIE):
_VALID_URL = r'''(?x)https?://(?:www\.)?nbcnews\.com/ _VALID_URL = r'''(?x)https?://(?:www\.)?nbcnews\.com/
(?:video/.+?/(?P<id>\d+)| (?:video/.+?/(?P<id>\d+)|

View File

@ -8,7 +8,7 @@ import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_str, compat_str,
compat_itertools_count, compat_itertools_count,
) )
@ -153,7 +153,7 @@ class NetEaseMusicIE(NetEaseMusicBaseIE):
'ids': '[%s]' % song_id 'ids': '[%s]' % song_id
} }
info = self.query_api( info = self.query_api(
'song/detail?' + compat_urllib_parse.urlencode(params), 'song/detail?' + compat_urllib_parse_urlencode(params),
song_id, 'Downloading song info')['songs'][0] song_id, 'Downloading song info')['songs'][0]
formats = self.extract_formats(info) formats = self.extract_formats(info)

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .mtv import MTVServicesInfoExtractor from .mtv import MTVServicesInfoExtractor
from ..compat import compat_urllib_parse from ..compat import compat_urllib_parse_urlencode
class NextMovieIE(MTVServicesInfoExtractor): class NextMovieIE(MTVServicesInfoExtractor):
@ -20,7 +20,7 @@ class NextMovieIE(MTVServicesInfoExtractor):
}] }]
def _get_feed_query(self, uri): def _get_feed_query(self, uri):
return compat_urllib_parse.urlencode({ return compat_urllib_parse_urlencode({
'feed': '1505', 'feed': '1505',
'mgid': uri, 'mgid': uri,
}) })

View File

@ -1,8 +1,10 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse from ..utils import (
from ..utils import sanitized_Request sanitized_Request,
urlencode_postdata,
)
class NFBIE(InfoExtractor): class NFBIE(InfoExtractor):
@ -40,7 +42,7 @@ class NFBIE(InfoExtractor):
request = sanitized_Request( request = sanitized_Request(
'https://www.nfb.ca/film/%s/player_config' % video_id, 'https://www.nfb.ca/film/%s/player_config' % video_id,
compat_urllib_parse.urlencode({'getConfig': 'true'}).encode('ascii')) urlencode_postdata({'getConfig': 'true'}))
request.add_header('Content-Type', 'application/x-www-form-urlencoded') request.add_header('Content-Type', 'application/x-www-form-urlencoded')
request.add_header('X-NFB-Referer', 'http://www.nfb.ca/medias/flash/NFBVideoPlayer.swf') request.add_header('X-NFB-Referer', 'http://www.nfb.ca/medias/flash/NFBVideoPlayer.swf')

View File

@ -7,7 +7,7 @@ import os
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urlparse, compat_urlparse,
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urllib_parse_urlparse compat_urllib_parse_urlparse
) )
from ..utils import ( from ..utils import (
@ -38,7 +38,7 @@ class NHLBaseInfoExtractor(InfoExtractor):
parsed_url = compat_urllib_parse_urlparse(initial_video_url) parsed_url = compat_urllib_parse_urlparse(initial_video_url)
filename, ext = os.path.splitext(parsed_url.path) filename, ext = os.path.splitext(parsed_url.path)
path = '%s_sd%s' % (filename, ext) path = '%s_sd%s' % (filename, ext)
data = compat_urllib_parse.urlencode({ data = compat_urllib_parse_urlencode({
'type': 'fvod', 'type': 'fvod',
'path': compat_urlparse.urlunparse(parsed_url[:2] + (path,) + parsed_url[3:]) 'path': compat_urlparse.urlunparse(parsed_url[:2] + (path,) + parsed_url[3:])
}) })
@ -211,7 +211,7 @@ class NHLVideocenterIE(NHLBaseInfoExtractor):
r'tab0"[^>]*?>(.*?)</td>', r'tab0"[^>]*?>(.*?)</td>',
webpage, 'playlist title', flags=re.DOTALL).lower().capitalize() webpage, 'playlist title', flags=re.DOTALL).lower().capitalize()
data = compat_urllib_parse.urlencode({ data = compat_urllib_parse_urlencode({
'cid': cat_id, 'cid': cat_id,
# This is the default value # This is the default value
'count': 12, 'count': 12,

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .mtv import MTVServicesInfoExtractor from .mtv import MTVServicesInfoExtractor
from ..compat import compat_urllib_parse from ..compat import compat_urllib_parse_urlencode
class NickIE(MTVServicesInfoExtractor): class NickIE(MTVServicesInfoExtractor):
@ -54,7 +54,7 @@ class NickIE(MTVServicesInfoExtractor):
}] }]
def _get_feed_query(self, uri): def _get_feed_query(self, uri):
return compat_urllib_parse.urlencode({ return compat_urllib_parse_urlencode({
'feed': 'nick_arc_player_prime', 'feed': 'nick_arc_player_prime',
'mgid': uri, 'mgid': uri,
}) })

View File

@ -7,11 +7,10 @@ import datetime
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urllib_parse, compat_urllib_parse_urlencode,
compat_urlparse, compat_urlparse,
) )
from ..utils import ( from ..utils import (
encode_dict,
ExtractorError, ExtractorError,
int_or_none, int_or_none,
parse_duration, parse_duration,
@ -19,6 +18,7 @@ from ..utils import (
sanitized_Request, sanitized_Request,
xpath_text, xpath_text,
determine_ext, determine_ext,
urlencode_postdata,
) )
@ -101,7 +101,7 @@ class NiconicoIE(InfoExtractor):
'mail': username, 'mail': username,
'password': password, 'password': password,
} }
login_data = compat_urllib_parse.urlencode(encode_dict(login_form_strs)).encode('utf-8') login_data = urlencode_postdata(login_form_strs)
request = sanitized_Request( request = sanitized_Request(
'https://secure.nicovideo.jp/secure/login', login_data) 'https://secure.nicovideo.jp/secure/login', login_data)
login_results = self._download_webpage( login_results = self._download_webpage(
@ -141,7 +141,7 @@ class NiconicoIE(InfoExtractor):
r'\'thumbPlayKey\'\s*:\s*\'(.*?)\'', ext_player_info, 'thumbPlayKey') r'\'thumbPlayKey\'\s*:\s*\'(.*?)\'', ext_player_info, 'thumbPlayKey')
# Get flv info # Get flv info
flv_info_data = compat_urllib_parse.urlencode({ flv_info_data = compat_urllib_parse_urlencode({
'k': thumb_play_key, 'k': thumb_play_key,
'v': video_id 'v': video_id
}) })

View File

@ -8,7 +8,6 @@ import hashlib
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_str, compat_str,
compat_urllib_parse,
compat_urlparse, compat_urlparse,
) )
from ..utils import ( from ..utils import (
@ -18,6 +17,7 @@ from ..utils import (
float_or_none, float_or_none,
parse_iso8601, parse_iso8601,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -75,7 +75,7 @@ class NocoIE(InfoExtractor):
'username': username, 'username': username,
'password': password, 'password': password,
} }
request = sanitized_Request(self._LOGIN_URL, compat_urllib_parse.urlencode(login_form)) request = sanitized_Request(self._LOGIN_URL, urlencode_postdata(login_form))
request.add_header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8') request.add_header('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
login = self._download_json(request, None, 'Logging in as %s' % username) login = self._download_json(request, None, 'Logging in as %s' % username)

View File

@ -7,7 +7,6 @@ from ..compat import compat_urlparse
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
NO_DEFAULT, NO_DEFAULT,
encode_dict,
sanitized_Request, sanitized_Request,
urlencode_postdata, urlencode_postdata,
) )
@ -73,7 +72,7 @@ class NovaMovIE(InfoExtractor):
if not post_url.startswith('http'): if not post_url.startswith('http'):
post_url = compat_urlparse.urljoin(url, post_url) post_url = compat_urlparse.urljoin(url, post_url)
request = sanitized_Request( request = sanitized_Request(
post_url, urlencode_postdata(encode_dict(fields))) post_url, urlencode_postdata(fields))
request.add_header('Content-Type', 'application/x-www-form-urlencoded') request.add_header('Content-Type', 'application/x-www-form-urlencoded')
request.add_header('Referer', post_url) request.add_header('Referer', post_url)
webpage = self._download_webpage( webpage = self._download_webpage(

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse from ..compat import compat_urllib_parse_urlencode
from ..utils import ( from ..utils import (
int_or_none, int_or_none,
qualities, qualities,
@ -38,7 +38,7 @@ class NprIE(InfoExtractor):
playlist_id = self._match_id(url) playlist_id = self._match_id(url)
config = self._download_json( config = self._download_json(
'http://api.npr.org/query?%s' % compat_urllib_parse.urlencode({ 'http://api.npr.org/query?%s' % compat_urllib_parse_urlencode({
'id': playlist_id, 'id': playlist_id,
'fields': 'titles,audio,show', 'fields': 'titles,audio,show',
'format': 'json', 'format': 'json',

View File

@ -63,6 +63,7 @@ class NRKIE(InfoExtractor):
if determine_ext(media_url) == 'f4m': if determine_ext(media_url) == 'f4m':
formats = self._extract_f4m_formats( formats = self._extract_f4m_formats(
media_url + '?hdcore=3.5.0&plugin=aasp-3.5.0.151.81', video_id, f4m_id='hds') media_url + '?hdcore=3.5.0&plugin=aasp-3.5.0.151.81', video_id, f4m_id='hds')
self._sort_formats(formats)
else: else:
formats = [{ formats = [{
'url': media_url, 'url': media_url,

View File

@ -7,7 +7,7 @@ from .common import InfoExtractor
class OnceIE(InfoExtractor): class OnceIE(InfoExtractor):
_VALID_URL = r'https?://once\.unicornmedia\.com/now/[^/]+/[^/]+/(?P<domain_id>[^/]+)/(?P<application_id>[^/]+)/(?:[^/]+/)?(?P<media_item_id>[^/]+)/content\.(?:once|m3u8|mp4)' _VALID_URL = r'https?://.+?\.unicornmedia\.com/now/[^/]+/[^/]+/(?P<domain_id>[^/]+)/(?P<application_id>[^/]+)/(?:[^/]+/)?(?P<media_item_id>[^/]+)/content\.(?:once|m3u8|mp4)'
ADAPTIVE_URL_TEMPLATE = 'http://once.unicornmedia.com/now/master/playlist/%s/%s/%s/content.m3u8' ADAPTIVE_URL_TEMPLATE = 'http://once.unicornmedia.com/now/master/playlist/%s/%s/%s/content.m3u8'
PROGRESSIVE_URL_TEMPLATE = 'http://once.unicornmedia.com/now/media/progressive/%s/%s/%s/%s/content.mp4' PROGRESSIVE_URL_TEMPLATE = 'http://once.unicornmedia.com/now/media/progressive/%s/%s/%s/%s/content.mp4'

View File

@ -9,7 +9,7 @@ from ..utils import (
ExtractorError, ExtractorError,
unsmuggle_url, unsmuggle_url,
) )
from ..compat import compat_urllib_parse from ..compat import compat_urllib_parse_urlencode
class OoyalaBaseIE(InfoExtractor): class OoyalaBaseIE(InfoExtractor):
@ -35,7 +35,7 @@ class OoyalaBaseIE(InfoExtractor):
for supported_format in ('mp4', 'm3u8', 'hds', 'rtmp'): for supported_format in ('mp4', 'm3u8', 'hds', 'rtmp'):
auth_data = self._download_json( auth_data = self._download_json(
self._AUTHORIZATION_URL_TEMPLATE % (pcode, embed_code) + self._AUTHORIZATION_URL_TEMPLATE % (pcode, embed_code) +
compat_urllib_parse.urlencode({ compat_urllib_parse_urlencode({
'domain': domain, 'domain': domain,
'supportedFormats': supported_format 'supportedFormats': supported_format
}), }),

View File

@ -65,7 +65,7 @@ class PatreonIE(InfoExtractor):
request = sanitized_Request( request = sanitized_Request(
'https://www.patreon.com/processLogin', 'https://www.patreon.com/processLogin',
compat_urllib_parse.urlencode(login_form).encode('utf-8') compat_urllib_parse_urlencode(login_form).encode('utf-8')
) )
login_page = self._download_webpage(request, None, note='Logging in as %s' % username) login_page = self._download_webpage(request, None, note='Logging in as %s' % username)

View File

@ -5,10 +5,10 @@ import re
import os.path import os.path
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -40,7 +40,7 @@ class PlayedIE(InfoExtractor):
self._sleep(2, video_id) self._sleep(2, video_id)
post = compat_urllib_parse.urlencode(data) post = urlencode_postdata(data)
headers = { headers = {
b'Content-Type': b'application/x-www-form-urlencoded', b'Content-Type': b'application/x-www-form-urlencoded',
} }

View File

@ -4,7 +4,7 @@ from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_urlparse, compat_urlparse,
compat_urllib_parse, compat_urllib_parse_urlencode,
) )
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
@ -106,7 +106,7 @@ class PlaytvakIE(InfoExtractor):
}) })
info_url = compat_urlparse.urlunparse( info_url = compat_urlparse.urlunparse(
parsed_url._replace(query=compat_urllib_parse.urlencode(qs, True))) parsed_url._replace(query=compat_urllib_parse_urlencode(qs, True)))
json_info = self._download_json( json_info = self._download_json(
info_url, video_id, info_url, video_id,

View File

@ -8,7 +8,6 @@ import collections
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_str, compat_str,
compat_urllib_parse,
compat_urlparse, compat_urlparse,
) )
from ..utils import ( from ..utils import (
@ -17,6 +16,7 @@ from ..utils import (
parse_duration, parse_duration,
qualities, qualities,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -76,7 +76,7 @@ class PluralsightIE(PluralsightBaseIE):
post_url = compat_urlparse.urljoin(self._LOGIN_URL, post_url) post_url = compat_urlparse.urljoin(self._LOGIN_URL, post_url)
request = sanitized_Request( request = sanitized_Request(
post_url, compat_urllib_parse.urlencode(login_form).encode('utf-8')) post_url, urlencode_postdata(login_form))
request.add_header('Content-Type', 'application/x-www-form-urlencoded') request.add_header('Content-Type', 'application/x-www-form-urlencoded')
response = self._download_webpage( response = self._download_webpage(
@ -279,13 +279,18 @@ class PluralsightCourseIE(PluralsightBaseIE):
course_id, 'Downloading course data JSON') course_id, 'Downloading course data JSON')
entries = [] entries = []
for module in course_data: for num, module in enumerate(course_data, 1):
for clip in module.get('clips', []): for clip in module.get('clips', []):
player_parameters = clip.get('playerParameters') player_parameters = clip.get('playerParameters')
if not player_parameters: if not player_parameters:
continue continue
entries.append(self.url_result( entries.append({
'%s/training/player?%s' % (self._API_BASE, player_parameters), '_type': 'url_transparent',
'Pluralsight')) 'url': '%s/training/player?%s' % (self._API_BASE, player_parameters),
'ie_key': PluralsightIE.ie_key(),
'chapter': module.get('title'),
'chapter_number': num,
'chapter_id': module.get('moduleRef'),
})
return self.playlist_result(entries, course_id, title, description) return self.playlist_result(entries, course_id, title, description)

View File

@ -2,8 +2,8 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from ..compat import ( from ..compat import (
compat_urllib_parse,
compat_urllib_parse_unquote, compat_urllib_parse_unquote,
compat_urllib_parse_urlencode,
) )
from .common import InfoExtractor from .common import InfoExtractor
from ..utils import ( from ..utils import (
@ -50,7 +50,7 @@ class Porn91IE(InfoExtractor):
r'so.addVariable\(\'seccode\',\'([^\']+)\'', webpage, 'sec code') r'so.addVariable\(\'seccode\',\'([^\']+)\'', webpage, 'sec code')
max_vid = self._search_regex( max_vid = self._search_regex(
r'so.addVariable\(\'max_vid\',\'(\d+)\'', webpage, 'max vid') r'so.addVariable\(\'max_vid\',\'(\d+)\'', webpage, 'max vid')
url_params = compat_urllib_parse.urlencode({ url_params = compat_urllib_parse_urlencode({
'VID': file_id, 'VID': file_id,
'mp4': '1', 'mp4': '1',
'seccode': sec_code, 'seccode': sec_code,

View File

@ -1,10 +1,12 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import itertools
import os import os
import re import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import (
compat_HTTPError,
compat_urllib_parse_unquote, compat_urllib_parse_unquote,
compat_urllib_parse_unquote_plus, compat_urllib_parse_unquote_plus,
compat_urllib_parse_urlparse, compat_urllib_parse_urlparse,
@ -12,6 +14,7 @@ from ..compat import (
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
int_or_none, int_or_none,
orderedSet,
sanitized_Request, sanitized_Request,
str_to_int, str_to_int,
) )
@ -75,7 +78,7 @@ class PornHubIE(InfoExtractor):
flashvars = self._parse_json( flashvars = self._parse_json(
self._search_regex( self._search_regex(
r'var\s+flashv1ars_\d+\s*=\s*({.+?});', webpage, 'flashvars', default='{}'), r'var\s+flashvars_\d+\s*=\s*({.+?});', webpage, 'flashvars', default='{}'),
video_id) video_id)
if flashvars: if flashvars:
video_title = flashvars.get('video_title') video_title = flashvars.get('video_title')
@ -149,9 +152,12 @@ class PornHubIE(InfoExtractor):
class PornHubPlaylistBaseIE(InfoExtractor): class PornHubPlaylistBaseIE(InfoExtractor):
def _extract_entries(self, webpage): def _extract_entries(self, webpage):
return [ return [
self.url_result('http://www.pornhub.com/%s' % video_url, PornHubIE.ie_key()) self.url_result(
for video_url in set(re.findall( 'http://www.pornhub.com/%s' % video_url,
r'href="/?(view_video\.php\?.*\bviewkey=[\da-z]+[^"]*)"', webpage)) PornHubIE.ie_key(), video_title=title)
for video_url, title in orderedSet(re.findall(
r'href="/?(view_video\.php\?.*\bviewkey=[\da-z]+[^"]*)"[^>]*\s+title="([^"]+)"',
webpage))
] ]
def _real_extract(self, url): def _real_extract(self, url):
@ -185,16 +191,31 @@ class PornHubPlaylistIE(PornHubPlaylistBaseIE):
class PornHubUserVideosIE(PornHubPlaylistBaseIE): class PornHubUserVideosIE(PornHubPlaylistBaseIE):
_VALID_URL = r'https?://(?:www\.)?pornhub\.com/users/(?P<id>[^/]+)/videos' _VALID_URL = r'https?://(?:www\.)?pornhub\.com/users/(?P<id>[^/]+)/videos'
_TESTS = [{ _TESTS = [{
'url': 'http://www.pornhub.com/users/rushandlia/videos', 'url': 'http://www.pornhub.com/users/zoe_ph/videos/public',
'info_dict': { 'info_dict': {
'id': 'rushandlia', 'id': 'zoe_ph',
}, },
'playlist_mincount': 13, 'playlist_mincount': 171,
}, {
'url': 'http://www.pornhub.com/users/rushandlia/videos',
'only_matching': True,
}] }]
def _real_extract(self, url): def _real_extract(self, url):
user_id = self._match_id(url) user_id = self._match_id(url)
webpage = self._download_webpage(url, user_id) entries = []
for page_num in itertools.count(1):
try:
webpage = self._download_webpage(
url, user_id, 'Downloading page %d' % page_num,
query={'page': page_num})
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 404:
break
page_entries = self._extract_entries(webpage)
if not page_entries:
break
entries.extend(page_entries)
return self.playlist_result(self._extract_entries(webpage), user_id) return self.playlist_result(entries, user_id)

View File

@ -1,10 +1,10 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -42,7 +42,7 @@ class PrimeShareTVIE(InfoExtractor):
self._sleep(wait_time, video_id) self._sleep(wait_time, video_id)
req = sanitized_Request( req = sanitized_Request(
url, compat_urllib_parse.urlencode(fields), headers) url, urlencode_postdata(fields), headers)
video_page = self._download_webpage( video_page = self._download_webpage(
req, video_id, 'Downloading video page') req, video_id, 'Downloading video page')

View File

@ -4,11 +4,11 @@ from __future__ import unicode_literals
import re import re
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import compat_urllib_parse
from ..utils import ( from ..utils import (
determine_ext, determine_ext,
ExtractorError, ExtractorError,
sanitized_Request, sanitized_Request,
urlencode_postdata,
) )
@ -34,7 +34,7 @@ class PromptFileIE(InfoExtractor):
expected=True) expected=True)
fields = self._hidden_inputs(webpage) fields = self._hidden_inputs(webpage)
post = compat_urllib_parse.urlencode(fields) post = urlencode_postdata(fields)
req = sanitized_Request(url, post) req = sanitized_Request(url, post)
req.add_header('Content-type', 'application/x-www-form-urlencoded') req.add_header('Content-type', 'application/x-www-form-urlencoded')
webpage = self._download_webpage( webpage = self._download_webpage(

View File

@ -5,9 +5,7 @@ import re
from hashlib import sha1 from hashlib import sha1
from .common import InfoExtractor from .common import InfoExtractor
from ..compat import ( from ..compat import compat_urllib_parse_urlencode
compat_urllib_parse,
)
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
determine_ext, determine_ext,
@ -235,7 +233,7 @@ class ProSiebenSat1IE(InfoExtractor):
client_name = 'kolibri-2.0.19-splec4' client_name = 'kolibri-2.0.19-splec4'
client_location = url client_location = url
videos_api_url = 'http://vas.sim-technik.de/vas/live/v2/videos?%s' % compat_urllib_parse.urlencode({ videos_api_url = 'http://vas.sim-technik.de/vas/live/v2/videos?%s' % compat_urllib_parse_urlencode({
'access_token': access_token, 'access_token': access_token,
'client_location': client_location, 'client_location': client_location,
'client_name': client_name, 'client_name': client_name,
@ -256,7 +254,7 @@ class ProSiebenSat1IE(InfoExtractor):
client_id = g[:2] + sha1(''.join([clip_id, g, access_token, client_location, g, client_name]) client_id = g[:2] + sha1(''.join([clip_id, g, access_token, client_location, g, client_name])
.encode('utf-8')).hexdigest() .encode('utf-8')).hexdigest()
sources_api_url = 'http://vas.sim-technik.de/vas/live/v2/videos/%s/sources?%s' % (clip_id, compat_urllib_parse.urlencode({ sources_api_url = 'http://vas.sim-technik.de/vas/live/v2/videos/%s/sources?%s' % (clip_id, compat_urllib_parse_urlencode({
'access_token': access_token, 'access_token': access_token,
'client_id': client_id, 'client_id': client_id,
'client_location': client_location, 'client_location': client_location,
@ -270,7 +268,7 @@ class ProSiebenSat1IE(InfoExtractor):
client_location, source_ids_str, g, client_name]) client_location, source_ids_str, g, client_name])
.encode('utf-8')).hexdigest() .encode('utf-8')).hexdigest()
url_api_url = 'http://vas.sim-technik.de/vas/live/v2/videos/%s/sources/url?%s' % (clip_id, compat_urllib_parse.urlencode({ url_api_url = 'http://vas.sim-technik.de/vas/live/v2/videos/%s/sources/url?%s' % (clip_id, compat_urllib_parse_urlencode({
'access_token': access_token, 'access_token': access_token,
'client_id': client_id, 'client_id': client_id,
'client_location': client_location, 'client_location': client_location,

View File

@ -31,6 +31,7 @@ class RestudyIE(InfoExtractor):
formats = self._extract_smil_formats( formats = self._extract_smil_formats(
'https://www.restudy.dk/awsmedia/SmilDirectory/video_%s.xml' % video_id, 'https://www.restudy.dk/awsmedia/SmilDirectory/video_%s.xml' % video_id,
video_id) video_id)
self._sort_formats(formats)
return { return {
'id': video_id, 'id': video_id,

View File

@ -49,6 +49,7 @@ class RteIE(InfoExtractor):
# f4m_url = server + relative_url # f4m_url = server + relative_url
f4m_url = json_string['shows'][0]['media:group'][0]['rte:server'] + json_string['shows'][0]['media:group'][0]['url'] f4m_url = json_string['shows'][0]['media:group'][0]['rte:server'] + json_string['shows'][0]['media:group'][0]['url']
f4m_formats = self._extract_f4m_formats(f4m_url, video_id) f4m_formats = self._extract_f4m_formats(f4m_url, video_id)
self._sort_formats(f4m_formats)
return { return {
'id': video_id, 'id': video_id,

View File

@ -209,6 +209,7 @@ class RTVELiveIE(InfoExtractor):
png = self._download_webpage(png_url, video_id, 'Downloading url information') png = self._download_webpage(png_url, video_id, 'Downloading url information')
m3u8_url = _decrypt_url(png) m3u8_url = _decrypt_url(png)
formats = self._extract_m3u8_formats(m3u8_url, video_id, ext='mp4') formats = self._extract_m3u8_formats(m3u8_url, video_id, ext='mp4')
self._sort_formats(formats)
return { return {
'id': video_id, 'id': video_id,

View File

@ -38,6 +38,7 @@ class RTVNHIE(InfoExtractor):
item['file'], video_id, ext='mp4', entry_protocol='m3u8_native')) item['file'], video_id, ext='mp4', entry_protocol='m3u8_native'))
elif item.get('type') == '': elif item.get('type') == '':
formats.append({'url': item['file']}) formats.append({'url': item['file']})
self._sort_formats(formats)
return { return {
'id': video_id, 'id': video_id,

Some files were not shown because too many files have changed in this diff Show More