Compare commits

...

746 Commits

Author SHA1 Message Date
Philipp Hagemeister
4dd09c9add release 2015.07.07 2015-07-07 10:36:07 +02:00
Yen Chi Hsuan
267dc07e6b [gfycat] Catch errors 2015-07-07 14:22:13 +08:00
Yen Chi Hsuan
d7b4d5dd50 [gfycat] Extract id correctly (fixes #6165) 2015-07-07 14:16:56 +08:00
Sergey M․
7f220b2fac [vk] Catch ownership confirmation request 2015-07-07 00:04:19 +06:00
Sergey M․
275c0423aa [vk] Fix extraction (Closes #6153) 2015-07-07 00:02:34 +06:00
Yen Chi Hsuan
d3ee4bbc5a Merge branch 'ping-qqmusic-format-fix' 2015-07-06 17:55:45 +08:00
Yen Chi Hsuan
85a064861f [qqmusic] Use regex for thumbnails in test cases 2015-07-06 17:54:41 +08:00
Yen Chi Hsuan
d0b436bff2 Merge branch 'qqmusic-format-fix' of https://github.com/ping/youtube-dl into ping-qqmusic-format-fix 2015-07-06 17:24:44 +08:00
Yen Chi Hsuan
92b2f18072 Merge branch 'ping-qqmusic-album-fix' 2015-07-06 17:09:56 +08:00
Yen Chi Hsuan
dfc4eca21f [qqmusic:album] Playlist names are optional 2015-07-06 17:09:17 +08:00
Yen Chi Hsuan
fc7ae675e2 [qqmusic:album] Strip description 2015-07-06 17:08:32 +08:00
Yen Chi Hsuan
804ad79985 Merge branch 'qqmusic-album-fix' of https://github.com/ping/youtube-dl into ping-qqmusic-album-fix 2015-07-06 17:01:59 +08:00
Yen Chi Hsuan
da839880e9 Merge branch 'ping-qqmusic-playlist' 2015-07-06 16:20:46 +08:00
Yen Chi Hsuan
e9d33454b5 [qqmusic:playlist] Playlist names are optional 2015-07-06 16:19:49 +08:00
Yen Chi Hsuan
d80891efc4 Merge branch 'qqmusic-playlist' of https://github.com/ping/youtube-dl into ping-qqmusic-playlist 2015-07-06 16:08:30 +08:00
Yen Chi Hsuan
59a83d3e5b [spiegeltv] Skip invalid m3u8 manifests (closes #6157) 2015-07-06 08:41:14 +08:00
Yen Chi Hsuan
13af92fdc4 [common] Add 'fatal' to _extract_m3u8_formats 2015-07-06 08:39:38 +08:00
Sergey M․
0c20ee7d4b [rtlnl] Clarify current adaptive -> flash workaround rationale 2015-07-06 04:16:56 +06:00
Sergey M․
89d42c2c75 [rtlnl] Clarify test 2015-07-06 02:58:02 +06:00
Sergey M․
04611765a4 Merge branch 'corone17-patch-1' 2015-07-05 19:07:51 +06:00
Sergey M․
9dfc4fa1a1 [rtlnl] Add test with encrypted m3u8 streams for reference 2015-07-05 19:07:07 +06:00
Sergey M․
43232d5c14 [rtlnl] Improve 2015-07-05 19:01:07 +06:00
Sergey M․
f7c272d4fa Merge branch 'patch-1' of https://github.com/corone17/youtube-dl into corone17-patch-1 2015-07-05 18:07:39 +06:00
Sergey M․
ede21449c8 [crunchyroll] Fix extraction (Closes #5855, closes #5881) 2015-07-05 06:29:36 +06:00
Sergey M․
d7c9a3e976 Credit @remitamine for snagfilms (#6096) 2015-07-04 17:22:11 +06:00
Philipp Hagemeister
35eb649e9d release 2015.07.04 2015-07-04 09:24:00 +02:00
Sergey M․
e56a4c9e9b [thisamericanlife] Improve and simplify 2015-07-04 05:42:53 +06:00
Eric Wong
95506e37af [thisamericanlife] Remove unnecessary comment 2015-07-04 05:12:28 +06:00
Eric Wong
e41840c522 [thisamericanlife] get info from <meta> tags 2015-07-04 05:12:20 +06:00
Eric Wong
2a46a27e6c [thisamericanlife] Add a new extractor 2015-07-04 05:12:10 +06:00
Sergey M․
0bcdc27653 [dailymotion:cloud] Extend _VALID_URL (Closes #6145) 2015-07-03 22:47:52 +06:00
Sergey M․
ddf0f74de7 [howcast] Fix extraction and modernize 2015-07-03 22:32:56 +06:00
Yen Chi Hsuan
91b21b2334 [infoq] Fix extraction (closes #6141) 2015-07-03 11:54:36 +08:00
Sergey M․
66e568de3b [extractor/generic] Improve kaltura embeds support (Closes #6137) 2015-07-02 21:39:46 +06:00
Sergey M․
f5ca97e393 [npo] Clarify token decryption algorithm source 2015-07-02 20:20:09 +06:00
Yen Chi Hsuan
8d06a62485 [npo] Decrypting token (closes #6136) 2015-07-02 16:47:55 +08:00
Yen Chi Hsuan
93f9420993 [pbs] Add coding declaration
Python 2.x does not work without it.
2015-07-02 13:13:27 +08:00
Yen Chi Hsuan
5b61070c70 [pbs] skip_download for m3u8 test cases 2015-07-02 13:08:48 +08:00
Yen Chi Hsuan
dbe1a93526 [pbs] Fix player URL (closes #6139) 2015-07-02 13:05:43 +08:00
Sergey M․
86511ea417 [drtuber] Fix extraction 2015-07-01 21:47:56 +06:00
Sergey M.
33f1f81b8b Merge pull request #6132 from alarig/master
Add support of HTTPS for ina.fr
2015-06-30 20:53:49 +06:00
Sergey M․
9d0b581fea [youtube] Prefer meta for upload date and modernize 2015-06-30 20:52:26 +06:00
alarig
c05724cb18 Add support of HTTPS for ina.fr 2015-06-30 16:47:14 +02:00
Sergey M․
f0714c9f86 [youtube] Speed up upload date regex (#6125) 2015-06-30 01:02:48 +06:00
Sergey M․
cf386750c9 [hentaistigma] Modernize 2015-06-29 22:21:09 +06:00
Sergey M.
54f428f645 Merge pull request #6120 from nawl/master
[hentaistigma] Fix video extractor
2015-06-29 21:14:49 +05:00
Sergey M.
dc2bd20e55 Merge pull request #6098 from dstftw/use-codecs-from-dash-manifest
[youtube] Pick up codecs info from DASH manifest when not set explicitly
2015-06-29 20:58:52 +05:00
Sergey M.
c608ee491f Merge pull request #6097 from dstftw/union-itags-from-multiple-dashmpd
[youtube] Extract formats from multiple DASH manifests (Closes #6093)
2015-06-29 20:58:34 +05:00
nawl
738b926322 [hentaistigma] Fix video extractor 2015-06-28 17:24:00 -06:00
corone17
bea41c7f3f Update rtlnl.py
Better to extract 'http://manifest.us.rtl.nl' from the json, I'd say. And I think it's better to use the default json-url to make it more futureproof.
Succesfully tested with tarball.
2015-06-29 00:59:18 +02:00
Sergey M.
1bbe660dfa Merge pull request #6117 from Kagee/patch-1
NRK now supports / requires HTTPS
2015-06-29 03:15:53 +05:00
Anders Einar Hilden
c4bd188da4 NRK now supports / requires HTTPS
Add s? to regexp to support new urls. Update testcases to use HTTPS.
2015-06-29 00:11:31 +02:00
Sergey M․
5414623791 [extractor/common] Remove superfluous line 2015-06-29 00:49:19 +06:00
Sergey M․
c93d53f5e3 [youtube] Fix likes/dislike extraction 2015-06-29 00:48:06 +06:00
Sergey M․
507683780e Credit @gebn for moviefap 2015-06-28 23:08:05 +06:00
Sergey M․
e8b9ee5e08 Merge branch 'gebn-moviefap' 2015-06-28 23:05:49 +06:00
Sergey M․
d16154d163 [tnaflix] Generalize tnaflix extractors 2015-06-28 23:05:09 +06:00
Sergey M․
c342041fba [extractor/common] Use NO_DEFAULT from utils 2015-06-28 22:56:45 +06:00
Sergey M․
bf42a9906d [utils] Add default value for xpath_text 2015-06-28 22:56:07 +06:00
Sergey M․
9603e8a7d9 [YoutubeDL] Handle None width and height similarly to formats 2015-06-28 22:55:28 +06:00
Sergey M․
c7c040b825 Merge branch 'moviefap' of https://github.com/gebn/youtube-dl into gebn-moviefap 2015-06-28 18:00:49 +06:00
Yen Chi Hsuan
ac0474f89d [twitch:vod] Update _TEST
The original test case is gone
2015-06-28 13:33:09 +08:00
Yen Chi Hsuan
bb512e57dc [twitch:vod] Fix 'Source' format in m3u8 (closes #6115) 2015-06-28 13:33:09 +08:00
George Brighton
db652ea186 [moviefap] Fix flake8 warnings introduced in 1a5fd4e 2015-06-27 23:04:55 +01:00
George Brighton
5a9cc19972 [moviefap] Move flv videos to formats in the metadata 2015-06-27 23:03:06 +01:00
George Brighton
1a5fd4eebc [moviefap] Wrap long lines 2015-06-27 22:32:56 +01:00
George Brighton
8a1b49ff19 [moviefap] Explicitly sort formats to handle possible site changes 2015-06-27 22:28:17 +01:00
George Brighton
b971abe897 [moviefap] Replace call to str() with compat.compat_str() 2015-06-27 21:04:53 +01:00
George Brighton
43b925ce74 [moviefap] Replace calls to find() with util.xpath_text(). 2015-06-27 20:52:12 +01:00
George Brighton
62b742ece3 [moviefap] Remove redundant comments 2015-06-27 20:51:11 +01:00
George Brighton
d16ef949ca [moviefap] Allow non-critical fields to change without breaking extraction 2015-06-27 20:36:46 +01:00
Sergey M․
23e7cba87f [twitter:card] Add extractor (#5239) 2015-06-28 01:22:25 +06:00
George Brighton
a8e6f30d8e [moviefap] Swap and justify tests 2015-06-27 20:16:53 +01:00
George Brighton
9c49410898 [moviefap] Add categories to tests 2015-06-27 20:16:53 +01:00
George Brighton
802d74aa6b [moviefap] Swap test for an alternative non-copyrighted video 2015-06-27 20:16:53 +01:00
George Brighton
71f9e49e67 [moviefap] Fix dictionary comprehension syntax incompatible with Python 2.6 2015-06-27 20:16:53 +01:00
George Brighton
82ea1051b5 [moviefap] Add new extractor 2015-06-27 20:16:53 +01:00
Sergey M․
6c4d20cd6f [downloader/external] Fix externals downloaders specified with extension on Windows 2015-06-28 00:08:52 +06:00
Sergey M․
04c27802c0 [smotri] Add tests for password protected videos 2015-06-27 23:31:27 +06:00
Sergey M․
c3b7202f4f [smotri] Remove non relevant test 2015-06-27 23:03:26 +06:00
Sergey M․
81103ef35d [smotri] Fix password protected video extraction 2015-06-27 23:00:27 +06:00
Sergey M.
0eb5c1c62a Merge pull request #6081 from yan12125/skip_problematic_sites
[planetaplay/quickvid/vube] Skip inaccessible sites
2015-06-27 18:49:29 +05:00
Sergey M․
a9de951744 [snagfilms] More tests 2015-06-27 18:57:01 +06:00
Sergey M․
a42a1bb09d [snagfilms] Capture not available error 2015-06-27 18:54:08 +06:00
Sergey M․
9fbfc9bd4d [snagfilms:embed] Capture geolocation restriction error 2015-06-27 18:50:26 +06:00
Sergey M․
242a998bdc [snagfilms] Add support for shows 2015-06-27 18:40:01 +06:00
Sergey M․
9d1bf70234 Merge branch 'remitamine-snagfilms' 2015-06-27 18:29:16 +06:00
Sergey M․
b8c1cc1a51 [extractor/generic] Add test for snagfilms embeds 2015-06-27 18:28:10 +06:00
Sergey M․
eedd20ef96 [extractor/generic] Add support for snagfilms embeds 2015-06-27 18:26:14 +06:00
Sergey M․
7c197ad96d [snagfilms] Add routine for generic embeds extractions 2015-06-27 18:25:50 +06:00
Sergey M․
654fd03c73 [snagfilms] Improve and simplify 2015-06-27 18:20:42 +06:00
Jaime Marquínez Ferrándiz
cee16e0fa3 [newstube] style: fix alignment 2015-06-27 14:20:33 +02:00
Jaime Marquínez Ferrándiz
73c471e9ef [newstube] Fix GUID extraction (fixes #6109) 2015-06-27 14:18:01 +02:00
Sergey M․
533b99fbf9 Merge branch 'snagfilms' of https://github.com/remitamine/youtube-dl into remitamine-snagfilms 2015-06-27 16:52:51 +06:00
remitamine
f39eb98bab download all pages before start extracting info 2015-06-27 10:55:25 +01:00
Sergey M․
da77d856a1 [youtube] Add test for #6093 2015-06-27 14:55:46 +06:00
Sergey M․
b2575b38e7 [options] Clarify --youtube-skip-dash-manifest 2015-06-27 14:38:41 +06:00
Sergey M․
0a3cf9ad3d [youtube] Skip get_video_info requests when --youtube-skip-dash-manifest is specified 2015-06-27 14:31:18 +06:00
Sergey M․
00334d0de0 [options] Add missing whitespace and split lines 2015-06-27 14:26:51 +06:00
Sergey M․
226b886ca8 [vk] Fix authentication (Closes #6105) 2015-06-27 14:04:55 +06:00
Sergey M․
bc93bdb5bb [youtube] Fix reference before assignment for video_info 2015-06-27 13:19:46 +06:00
Yen Chi Hsuan
af214c3a79 [youtube] More useful messages for georestricted videos (#5716) 2015-06-27 13:15:57 +08:00
Yen Chi Hsuan
4eb10f6621 [utils] Add ISO3166Utils 2015-06-27 13:13:57 +08:00
remitamine
7d7d469025 add support for embed links 2015-06-27 00:13:14 +01:00
remitamine
fd40bdc0be remove unnecessary symbolic name for group 2015-06-26 21:56:15 +01:00
remitamine
7e0480ae0e convert tabs to 4 spaces identation 2015-06-26 21:50:27 +01:00
Sergey M․
d80265ccd6 [youtube] Simplify non-DASH formats exclusion 2015-06-27 02:48:50 +06:00
Sergey M․
1b5a1ae257 [youtube] Pick up codecs info from DASH manifest when not set explicitly 2015-06-27 00:41:26 +06:00
Sergey M․
d8d24a922a [youtube] Extract formats from multiple DASH manifests (Closes #6093)
DASH manifest pointed by dashmpd from the video webpage and one pointed by get_video_info may
be different (namely different itag set) - some itags are missing from DASH manifest pointed by
webpage's dashmpd, some - from DASH manifest pointed by get_video_info's dashmpd).
The general idea is to take a union of itags of both DASH manifests (for example video with such
'manifest behavior' see https://github.com/rg3/youtube-dl/issues/6093).
2015-06-27 00:36:23 +06:00
remitamine
03339b7b5b [snagfilms] Add new extractor 2015-06-26 18:25:43 +01:00
Sergey M․
2988835af5 [lynda] Fix non-ASCII logins/passwords on python 2 2015-06-26 19:48:23 +06:00
Sergey M․
62cca96b72 [lynda] Fix confirm login request (#6088) 2015-06-26 19:46:42 +06:00
Sergey M․
b4dea075a3 [lynda] Fix login request (Closes #6088) 2015-06-26 19:36:04 +06:00
Sergey M․
533f67d3fa [infoq] Relax _VALID_URL (Closes #6071) 2015-06-25 19:54:44 +06:00
Jaime Marquínez Ferrándiz
906e2f0eac [downloader/external] Add downloader for httpie (closes #6079) 2015-06-25 15:48:04 +02:00
Yen Chi Hsuan
b8091db6b9 [planetaplay/quickvid/vube] Skip inaccessible sites 2015-06-25 16:40:29 +08:00
Yen Chi Hsuan
381c067755 [thesixtyone] Modernize 2015-06-25 16:19:04 +08:00
Yen Chi Hsuan
2182ab5187 [thesixtyone] Fix audio_server
Some of the songs are moved to Amazon AWS
2015-06-25 16:15:13 +08:00
Philipp Hagemeister
a1593a4a0e release 2015.06.25 2015-06-25 07:43:49 +02:00
Sergey M.
12e9e8445d [README.md] Fix typo 2015-06-25 01:10:42 +06:00
Sergey M․
8084be78c5 [extractor/generic] Add test for OnionStudios embeds 2015-06-24 23:23:16 +06:00
Sergey M․
1ac1c4c26e [extractor/generic] Add support for OnionStudios embeds (Closes #5841) 2015-06-24 23:19:50 +06:00
Sergey M․
d4f58034f7 [onionstudios] Add generic embed extraction routine 2015-06-24 23:16:33 +06:00
Sergey M․
f843300fe5 [onionstudios] Add extractor 2015-06-24 23:12:13 +06:00
Sergey M․
03b9c94437 [soundcloud:user] Add test 2015-06-24 20:49:22 +06:00
Sergey M․
a219d175c6 [soundcloud] Improve _VALID_URL
Do not takeover soundcloud:user URLs
2015-06-24 20:48:57 +06:00
Sergey M.
3c3b4176bd Merge pull request #5961 from dstftw/force-generic-extractor
Add --force-generic-extractor
2015-06-24 19:10:45 +05:00
Sergey M.
022383139b Merge pull request #6067 from mitsukarenai/master
[noco.tv] Fix issue #6066: title interpreted as integer
2015-06-24 19:10:01 +05:00
Mitsukarenai
1a1251e877 [noco.tv] Fix issue #6066: title interpreted as integer 2015-06-24 10:40:01 +02:00
Yen Chi Hsuan
18b5e1e534 [drbonanza] Fix extraction of videos 2015-06-24 16:02:10 +08:00
Sergey M․
2fece970b8 [extractor/generic] Clarify generic extraction warning 2015-06-24 03:08:24 +06:00
Sergey M․
e20d0c1e69 [brightcove] Use compat_xml_parse_error (Closes #6060) 2015-06-23 21:34:29 +06:00
Sergey M․
255f5694aa [faz] Extend _VALID_URL (Closes #6050) 2015-06-22 20:11:15 +06:00
Jaime Marquínez Ferrándiz
25701d5a2c [xhamster] pep8: remove trailing ';' 2015-06-22 11:18:52 +02:00
Yen Chi Hsuan
a5158f38a3 [generic/adobetv] Support AdobeTVVideo embeds (#6039) 2015-06-22 15:07:32 +08:00
Sergey M․
c76799c555 [extractor/generic] Add test for xhamster embed 2015-06-21 23:18:28 +06:00
Sergey M․
2bb5b6d0a1 [generic] Add support for xhamster embeds 2015-06-21 23:11:25 +06:00
Sergey M․
0bbba43ed0 [xhamster:embed] Add extractor (Closes #6032) 2015-06-21 23:10:38 +06:00
Yen Chi Hsuan
98ca102441 [sohu] Fix extraction again 2015-06-22 00:59:55 +08:00
Yen Chi Hsuan
3f3308cd75 Revert "[sohu] Update extractor"
This reverts commit 32060c6d6b.
2015-06-21 23:29:40 +08:00
Yen Chi Hsuan
6f96e308d0 [francetvinfo.fr] Support dmcloud embeds (fixes #6034) 2015-06-21 21:31:33 +08:00
Yen Chi Hsuan
756f574e4e [dailymotion/generic] Add DailymotionCloudIE 2015-06-21 21:30:34 +08:00
Yen Chi Hsuan
78294e6a9c [bbccouk] Remove TTML to srt conversion codes
It's broken. See #6038
2015-06-21 19:24:45 +08:00
Yen Chi Hsuan
4e33577173 [utils] Support ttaf1 namespace in TTML
It's found in bbc.co.uk. See #6038
2015-06-21 19:24:39 +08:00
Yen Chi Hsuan
607841af64 [adobetv] Support embeddable videos (closes #6039) 2015-06-21 18:55:26 +08:00
Yen Chi Hsuan
396726244a [utils/ffmpeg] Move ISO 639 related codes to utils 2015-06-21 18:53:17 +08:00
Yen Chi Hsuan
c5895d5dbd [tumblr] Support Vimeo embeds (fixes #5969) 2015-06-21 18:30:38 +08:00
Yen Chi Hsuan
b407e173e4 [vimeo/generic] Move detection logic from GenericIE to VimeoIE 2015-06-21 18:23:58 +08:00
Yen Chi Hsuan
6a745c2c0f [pinkbike] PEP8 2015-06-21 18:23:08 +08:00
Sergey M․
c9ac7fa909 [imdb] Fix extraction 2015-06-21 04:17:54 +06:00
Yen Chi Hsuan
964afd0689 [xvideos] Support lower-quality formats found on Android
Closes #5968
2015-06-21 03:12:17 +08:00
Sergey M․
16d6973f8a [viki] Pass session token around (#6005) 2015-06-20 00:49:28 +06:00
Sergey M․
edcd2d665b Merge branch 'misterhat-pinkbike' 2015-06-20 00:10:27 +06:00
Sergey M․
385c3e5e91 [pinkbike] Improve and simplify 2015-06-20 00:10:08 +06:00
Sergey M․
c8e337450b Merge branch 'pinkbike' of https://github.com/misterhat/youtube-dl into misterhat-pinkbike 2015-06-19 23:00:00 +06:00
Sergey M․
10464af5d1 [dramafever:series] Fix extraction while authenticated 2015-06-19 22:02:07 +06:00
Sergey M․
cbcd1a5474 [dramafever] Add support for authentication (Closes #6017) 2015-06-19 21:57:31 +06:00
Sergey M․
c9bebed294 [youtube] Add itag 59 and 78 (Closes #5979) 2015-06-19 20:52:44 +06:00
Sergey M․
360075e28a [pornhub] Extend _VALID_URL (Closes #6019) 2015-06-18 22:26:17 +06:00
Sergey M․
accf79b107 [viki] Add support for authentication (Closes #6005) 2015-06-18 21:17:26 +06:00
ping
4d58b24c15 [qqmusic] Use _check_formats instead 2015-06-18 23:09:04 +08:00
Yen Chi Hsuan
c33a8639a7 [postprocessor/embedthumbnail] Skipping if thumbnail file missing
Fixes #5996
2015-06-18 22:05:02 +08:00
Yen Chi Hsuan
25fa8d66e6 [bbccouk] Fix description (closes #6006) 2015-06-18 22:00:13 +08:00
Yen Chi Hsuan
974a6146fe [bbccouk] Fix error handling 2015-06-18 21:40:45 +08:00
ping
0392ac98d2 [qqmusic] Fix code formatting 2015-06-18 21:13:03 +08:00
ping
5e3915cbe3 [qqmusic] Fix song extraction when certain formats are unavailable 2015-06-18 21:06:25 +08:00
ping
29b809de68 [qqmusic] Fix album extraction 2015-06-18 15:52:04 +08:00
ping
0d0d5d3717 [qqmusic] Add support for playlists 2015-06-18 13:59:37 +08:00
Sergey M․
a69e8bfdd9 [lifenews] Fix tests 2015-06-17 20:29:15 +06:00
Sergey M․
062a3fdf36 [lifenews] Modernize 2015-06-17 20:28:47 +06:00
Sergey M․
028a33d7f2 [lifenews] Fix extraction 2015-06-17 20:27:38 +06:00
Sergey M․
447053668f [spankwire] Fix extraction 2015-06-16 21:19:18 +06:00
Jaime Marquínez Ferrándiz
f3aecb27a4 [youku] Simplify a bit the 'entries' construction
Mainly avoid having to use an index.
2015-06-16 14:41:52 +02:00
Sergey M․
7f0172b3e5 Credit @jackyzy823 for iqiyi 2015-06-15 22:29:41 +06:00
Yen Chi Hsuan
79fe954d79 Merge branch 'PeterDing-youku' 2015-06-16 00:20:52 +08:00
Yen Chi Hsuan
0501bfa159 [YoutubeDL] Youku extractor now uses the standard format selection 2015-06-16 00:15:30 +08:00
Yen Chi Hsuan
a155b7e76c [youku] Coding style 2015-06-16 00:15:09 +08:00
Yen Chi Hsuan
5228b756af [youku] Add cn_verification_proxy support and add a georestricted test case 2015-06-16 00:06:23 +08:00
Yen Chi Hsuan
04e7596680 [youku] Better error handling 2015-06-15 23:54:55 +08:00
Yen Chi Hsuan
f1e66cb2eb [youku] Change video_id and add a multipart test case 2015-06-15 23:46:07 +08:00
Sergey M․
4fd35ee072 [safari] Add test for #5985 2015-06-15 21:36:30 +06:00
Yen Chi Hsuan
ee69799262 [youku] Add a v.swf test case 2015-06-15 23:36:28 +08:00
Sergey M.
636a9637f4 Merge pull request #5985 from zx8/master
[safari] make url regex more lenient
2015-06-15 20:31:47 +05:00
Yen Chi Hsuan
9383e66f94 [youku] Use _match_id 2015-06-15 23:31:30 +08:00
Sergey M․
99e6833c85 [francetv] Update f4m manifest token URL (Closes #5981, Closes #5989) 2015-06-15 21:30:27 +06:00
Yen Chi Hsuan
c203be3fb4 [youku] Better handling for Python 2/3 compatibility 2015-06-15 23:28:59 +08:00
Sergey M․
02175a7986 [youtube:search] Fix search query (Closes #5988) 2015-06-15 21:01:26 +06:00
Sergey M․
8117df4cd9 [vk] Extract view count 2015-06-15 20:55:25 +06:00
Sergey M․
7c7dd9dc7f [vk] Fix upload date extraction 2015-06-15 20:47:01 +06:00
Sergey M․
054932f403 [vk] Fix extraction (Closes #5987) 2015-06-15 20:46:10 +06:00
Yen Chi Hsuan
aed473ccf9 [youku] PEP8 2015-06-15 22:41:24 +08:00
Yen Chi Hsuan
8268e94cd4 Merge branch 'youku' of https://github.com/PeterDing/youtube-dl into PeterDing-youku 2015-06-15 22:36:44 +08:00
Yen Chi Hsuan
4af98ecdfb [vbox7] Fix extraction (fixes #5967) 2015-06-15 18:49:27 +08:00
Philipp Hagemeister
4b9f9010b0 release 2015.06.15 2015-06-15 01:35:50 +02:00
zx8
2a0fcf6113 [safari] make url regex more lenient 2015-06-15 00:27:43 +01:00
Sergey M․
67d95f177c [niconico] Simplify format info 2015-06-15 03:43:33 +06:00
Sergey M.
44773ad125 Merge pull request #5975 from chaoskagami/niconico_qualitynote
Quality note for niconico
2015-06-15 02:38:33 +05:00
Sergey M․
5774ef35c4 [options] Add missing whitespace for --fixup description 2015-06-15 02:57:07 +06:00
Sergey M․
b95cfa9170 [liveleak] Clarify test 2015-06-15 02:54:49 +06:00
Sergey M․
afa1ded425 [liveleak] Clarify rationale for restoring raw video 2015-06-15 02:54:05 +06:00
Sergey M․
00ac23e6e0 [liveleak] Improve regex for restoring original video URL 2015-06-15 02:51:21 +06:00
Sergey M.
7d0c934a3e Merge pull request #5983 from jomo/master
LiveLeak: support more original videos
2015-06-15 01:49:41 +05:00
jomo
8f75761f24 LiveLak: add test for URLs with 'h264_270p' 2015-06-14 22:41:44 +02:00
jomo
9fd24e3a22 LiveLeak: support more original videos
some (old?) videos use ...mp4.h264_270p.mp4... instead of ...mp4.h264_base.mp4...
This is an addition to #4768
2015-06-14 21:50:03 +02:00
Naglis Jonaitis
755a9d3d1a [tvplay] Add support for NovaTv 2015-06-14 20:59:22 +03:00
Sergey M.
ac499cb61c Merge pull request #5976 from SpEcHiDe/patch-1
spelling mistake corrected
2015-06-14 18:26:53 +05:00
Shrimadhav U K
180940e02d spelling mistake corrected
acces changed to accessing
2015-06-14 11:19:42 +05:30
chaoskagami
976b03c56b Quality note for niconico - at least notify whether you'll get low or src 2015-06-14 00:18:40 -04:00
Sergey M․
450d89ddc1 [dramafever] Improve _VALID_URL 2015-06-14 09:58:26 +06:00
Sergey M․
463b2e5542 [dramafever:series] Rollback _PAGE_SIZE to max possible 2015-06-14 09:51:07 +06:00
Sergey M․
70a2002399 [dramafever:series] Fix _VALID_URL (Closes #5973) 2015-06-14 09:50:23 +06:00
Sergey M․
a617b10075 Merge branch 'ping-dramafever' 2015-06-14 07:43:50 +06:00
Sergey M․
0029071adb [dramefever] Improve and simplify 2015-06-14 07:43:14 +06:00
Sergey M․
ad49fe7c8f Merge branch 'dramafever' of https://github.com/ping/youtube-dl into ping-dramafever 2015-06-14 04:56:54 +06:00
Sergey M․
49bc802f81 Merge branch 'atomicdryad-brightcove_custombc_extractor' 2015-06-13 19:54:02 +06:00
Sergey M․
af9cdee9cb [brightcove] Improve and generalize brightcove URL extraction from JS 2015-06-13 19:53:32 +06:00
fnord
b4e1576aee Brightcove extractor: support customBC.createVideo(...); method
found in http://www.americanbar.org/groups/family_law.html and
http://america.aljazeera.com/watch/shows/america-tonight/2015/6/exclusive-hunting-isil-with-the-pkk.html
2015-06-13 06:20:30 -05:00
Sergey M․
78e2b74bb9 [tumblr] Add support for pornhub embeds (Closes #5963) 2015-06-13 03:39:14 +06:00
Sergey M․
65d161c480 [extractor/generic] Add support for pornhub embeds 2015-06-13 03:36:16 +06:00
Sergey M․
9fcbd5db2a [pornhub] Add support for embeds 2015-06-13 03:24:36 +06:00
Sergey M․
4f3bf679f5 [vk] Fix authentication for non-ASCII login/password 2015-06-13 03:09:35 +06:00
Sergey M․
0072afca8e [YoutubeDL] Remove force_generic_extractor arg from process_ie_result 2015-06-13 02:21:29 +06:00
Sergey M․
61aa5ba36e [YoutubeDL] Remove global state for force_generic_extractor flag in favor of passing argument 2015-06-13 02:05:21 +06:00
Sergey M․
9f4323252a [YoutubeDL] Fix for multiple URLs 2015-06-12 21:56:50 +06:00
Sergey M․
8b6c896c4b [prosiebensat1] Add title regex 2015-06-12 21:18:13 +06:00
Sergey M․
185dbc4974 [prosiebensat1] Fix rtmp extraction (Closes #5962) 2015-06-12 21:13:14 +06:00
Sergey M․
3d535e0471 [tvc] Fix embed regex 2015-06-12 19:31:52 +06:00
Sergey M․
d22dec74ff Add --force-generic-extractor
For some extractors that are hard to workout a good _VALID_URL we use very vague and unrestrictive ones,
e.g. just allowing anything after hostname and capturing part of URL as id.
If some of these extractors happen to have an video embed of some different hoster or platform
and this scenario was not handled in extractor itself we end up with inability to download this embed
until extractor is fixed to support embed of this kind.
Forcing downloader to use the generic extractor can be a neat temporary solution for this problem.
Example: FiveTV extractor with Tvigle embed - http://www.5-tv.ru/rabota/broadcasts/48/
2015-06-12 19:20:12 +06:00
Sergey M․
9872d3110c [extractor/generic] Add support for tvigle embeds 2015-06-12 18:37:09 +06:00
Sergey M․
b859971873 [extractor/generic] Rename tvc embed url variable 2015-06-12 18:15:30 +06:00
Sergey M․
e5095f1198 Merge branch 'hlintala-5tv' 2015-06-12 17:49:07 +06:00
Sergey M․
499a077761 [5tv] Improve 2015-06-12 17:48:42 +06:00
Sergey M․
5da7177729 Merge branch '5tv' of https://github.com/hlintala/youtube-dl into hlintala-5tv 2015-06-12 16:34:28 +06:00
Sergey M․
3507766bd0 Merge branch 'hlintala-tvc' 2015-06-12 16:29:10 +06:00
Sergey M․
f37bdbe537 [extractor/generic] Add test for tvc embed 2015-06-12 16:28:45 +06:00
Sergey M․
2da09ff8b0 [extractor/generic] Fix tvc ie_key 2015-06-12 16:26:31 +06:00
Sergey M․
5ccddb7ecf [tvc] Fix ie_key 2015-06-12 16:25:26 +06:00
Sergey M․
954c1d0529 [tvc] Refactor extractor names 2015-06-12 16:24:13 +06:00
Sergey M․
494f20cbdc [extractor/generic] Add support for tvc embeds 2015-06-12 16:22:46 +06:00
Sergey M․
29902c8ec0 [tvc:embed] Add embed extraction routine 2015-06-12 16:22:23 +06:00
Sergey M․
9f15bdabc8 [tvc] Separate embed extractor 2015-06-12 16:13:36 +06:00
Sergey M․
fff3455f58 Merge branch 'tvc' of https://github.com/hlintala/youtube-dl into hlintala-tvc 2015-06-12 15:12:54 +06:00
Hannu Lintala
87446dc618 [tvc] Add extractor (Closes #5795) 2015-06-12 01:34:10 +03:00
Hannu Lintala
99ac0390f5 [fivetv] Add extractor (Closes #5794) 2015-06-12 01:03:14 +03:00
Sergey M․
ff0f0b9172 [tube8] Fix extraction (Closes #5952) 2015-06-11 22:18:08 +06:00
Sergey M․
97b570a94c [generic] Improve rtl.nl embeds detection (Closes #5950) 2015-06-11 19:04:12 +06:00
Sergey M․
a9d56c6843 [rtlnl] Improve _VALID_URL (#5950) 2015-06-11 19:03:22 +06:00
Sergey M․
f98470df69 [bilibili] Fix FutureWarning 2015-06-10 23:01:12 +06:00
Jaime Marquínez Ferrándiz
eb8be1fe76 [rtbf] Extract all formats (closes #5947) 2015-06-10 14:12:43 +02:00
Yen Chi Hsuan
7ebd5376fe [nfl] Relax _VALID_URL (fixes #5940) 2015-06-10 14:17:03 +08:00
Jaime Marquínez Ferrándiz
70219b0f43 [youtube:playlist] Use an iterator for the entries (closes #5935)
So that '--playlist-end' downloads only the required pages.
2015-06-09 23:49:11 +02:00
Sergey M․
bd5bc0cd5a [theplatform] Check for /select/media URLs first (#5746) 2015-06-09 23:12:13 +06:00
Sergey M․
6e054aacca [theplatform] Take care of /select/media URLs (Closes #5746) 2015-06-09 23:07:22 +06:00
Sergey M․
9d581f3d52 [cbs] Extract display_id 2015-06-09 21:39:45 +06:00
Sergey M․
9bf99891d0 [cbs] Add support for colbertlateshow (Closes #5888) 2015-06-09 21:23:53 +06:00
Sergey M․
d9cf48e81e [spiegeltv] Extract all formats and prefer hls (Closes #5843) 2015-06-09 20:36:08 +06:00
Yen Chi Hsuan
e1b9322b09 [youtube] Restricter DASH signature pattern
A problematic DASH url is:
https://manifest.googlevideo.com/api/manifest/dash/mm/35/key/yt5/ip/140.112.247.145/ms/pm/mv/s/mt/1433794435/id/o-AD2Od_dsOlAUYPu03ZsVWKSbGEbCJJrMp9vnXGhnyRhd/mn/sn-aigllm7r/sparams/as%2Chfr%2Cid%2Cip%2Cipbits%2Citag%2Cmm%2Cmn%2Cms%2Cmv%2Cnh%2Cpl%2Cplayback_host%2Crequiressl%2Csource%2Cexpire/fexp/9406009%2C9406821%2C9407575%2C9408142%2C9408420%2C9408710%2C9409121%2C9409208%2C9412514%2C9412780%2C9413208%2C9413426%2C9413476%2C9413503%2C9415304%2C9415753/upn/viDQrs8SnmE/as/fmp4_audio_clear%2Cwebm_audio_clear%2Cfmp4_sd_hd_clear%2Cwebm_sd_hd_clear%2Cwebm2_sd_hd_clear/playback_host/r4---sn-aigllm7r.googlevideo.com/ipbits/0/requiressl/yes/pl/20/itag/0/source/youtube/expire/1433824806/nh/EAQ/signature/81ABE6391E351BA495F5B041B00FF1257A353318.1A6E48ABB74E8F4AE73CA2CB1F963FC34E33DEE7/sver/3/hfr/1
2015-06-09 14:48:18 +08:00
Yen Chi Hsuan
627b964825 [kickstarted] Extract thumbnails in embedded videos (#5929) 2015-06-09 11:54:13 +08:00
Sergey M․
a55e36f48d [YoutubeDL] Handle out-of-range timestamps (#5826) 2015-06-08 21:05:17 +06:00
Yen Chi Hsuan
01e21b89ee [noco] Skip invalid timestamps (closes #5826) 2015-06-08 17:39:55 +08:00
Yen Chi Hsuan
788be3313d [cnet] Fix theplatform vid extraction (fixes #5924) 2015-06-08 13:34:23 +08:00
Yen Chi Hsuan
e1ec93304d [instagram:user] Truncate title to 80 characters (#5919)
This is a workaround. Currently YoutubeDL.process_info() truncates
info_dict['title'] to 200 characters, but the implementation can't
handle wide characters.
2015-06-08 01:46:33 +08:00
Yen Chi Hsuan
edb99d4c18 [instagram] Handling null values (fixes #5919)
I didn't add the test case here because it takes too much time. (7
minutes on my machine)
2015-06-08 01:17:21 +08:00
Yen Chi Hsuan
68477c3dab [tlc] Fix test failure due to DiscoveryIE changes 2015-06-07 16:38:39 +08:00
Yen Chi Hsuan
65ba8b23f4 [discovery] Rewrite DiscoveryIE (fixes #5898)
Discovery.com now uses a completely different approach for serving
videos. At least in both test cases brightcove are involved. However,
AMF support is necessary for these brightcove videos. As a result, I
try to extract videos from the info page ('?flat=1'). The downloaded
file can be different from the one in browsers.
2015-06-07 16:34:19 +08:00
Yen Chi Hsuan
621ed9f5f4 [common] Add note and errnote field for _extract_m3u8_formats 2015-06-07 16:33:22 +08:00
Yen Chi Hsuan
b26733ba7f [brightcove] Allow single quotes in Brightcove URLs (fixes #5901) 2015-06-07 15:29:42 +08:00
Sergey M․
9836cfb8d6 [options] Clarify --list-extractors (Closes #5916) 2015-06-07 08:12:21 +06:00
Sergey M․
665b6c1236 Merge branch 'hlintala-ruutu' 2015-06-07 05:38:29 +06:00
Sergey M․
9414338a48 [ruutu] Improve, make more robust and fix python 2.6 support 2015-06-07 05:37:29 +06:00
Jaime Marquínez Ferrándiz
de390ea077 update: Use https for getting the version info (fixes #5909) 2015-06-07 00:21:30 +02:00
Sergey M․
717b0239fd Merge branch 'ruutu' of https://github.com/hlintala/youtube-dl into hlintala-ruutu 2015-06-07 04:01:28 +06:00
Hannu Lintala
d00735a0c5 [ruutu] Don't use fallback for DASH and other non-HTTP urls 2015-06-06 23:01:23 +03:00
Yen Chi Hsuan
c23d5ce926 Merge branch 'PeterDing-iqiyi' 2015-06-07 02:59:27 +08:00
Yen Chi Hsuan
b5a3c7f109 [iqiyi] Cache encryption keys 2015-06-07 02:47:36 +08:00
Yen Chi Hsuan
9c5f685ef1 [iqiyi] Improve regex pattern again 2015-06-07 02:39:03 +08:00
Yen Chi Hsuan
08bb8ef201 [iqiyi] Unify get_format() and get_bid() 2015-06-07 02:25:00 +08:00
Yen Chi Hsuan
865ab62f43 [iqiyi] Make _VALID_URL more accurate
v_* urls are individual videos, while a_* urls are playlists, which are
not supported yet.
2015-06-07 02:13:22 +08:00
Yen Chi Hsuan
9948113590 [iqiyi] Add a multipart test case 2015-06-07 02:09:33 +08:00
Yen Chi Hsuan
c4ee87022b [iqiyi] Change id for multipart videos 2015-06-07 01:57:05 +08:00
Yen Chi Hsuan
ffba4edb06 [iqiyi] Improve some variable names and add download notes 2015-06-07 01:52:51 +08:00
Yen Chi Hsuan
958d0b659b [iqiyi] Reorder imports 2015-06-07 01:35:09 +08:00
Yen Chi Hsuan
aacda28b28 [iqiyi] Give error message for assertion failures 2015-06-07 01:32:03 +08:00
Yen Chi Hsuan
29e7e0781b [iqiyi] Simplify and improve regex patterns
See the comments in #5849
2015-06-07 00:56:08 +08:00
Yen Chi Hsuan
7012620e2b [iqiyi] Remove format selection codes 2015-06-07 00:44:54 +08:00
Yen Chi Hsuan
f1da861018 [iqiyi] PEP8 2015-06-07 00:37:29 +08:00
Naglis Jonaitis
05aa9c82d9 [sunporno] Fix view_count extraction 2015-06-06 13:58:52 +03:00
Naglis Jonaitis
a9e58ecd3f [turbo] Improve description extraction
`og:description` is empty for some videos.
2015-06-06 13:58:51 +03:00
Hannu Lintala
223544552f [Ruutu] Add new extractor 2015-06-06 04:29:03 +03:00
Sergey M․
3d8e9573a4 [youtube:channel] Improve channel id extraction (#5904) 2015-06-06 06:25:37 +06:00
Naglis Jonaitis
54eb81a087 [pornovoisines] Improve average_rating extraction and update test case 2015-06-06 03:11:43 +03:00
Naglis Jonaitis
c33c547d66 [izlesene] Avoid timestamp differences in tests due to DST 2015-06-06 02:57:21 +03:00
Naglis Jonaitis
dfe7dd9bdb [izlesene] Unquote video URLs and simplify 2015-06-06 02:57:21 +03:00
Yen Chi Hsuan
63ccf6474d Merge branch 'ping-qqmusic-more-formats' 2015-06-05 23:19:54 +08:00
Yen Chi Hsuan
e8ac61e840 [qqmusic] Use meaningful variable names 2015-06-05 23:19:25 +08:00
Yen Chi Hsuan
f00a650705 [qqmusic] Rearrange codes 2015-06-05 23:16:34 +08:00
Yen Chi Hsuan
4bde5ce992 Merge branch 'qqmusic-more-formats' of https://github.com/ping/youtube-dl into ping-qqmusic-more-formats 2015-06-05 23:14:44 +08:00
Yen Chi Hsuan
d31573fa37 [teamcoco] Handle incomplete m3u8 URLs (fixes #5798)
There are 2 TODOs. I don't know how to handle these cases correctly.
2015-06-05 22:59:04 +08:00
ping
8b8cde2140 [qqmusic] Set abr for mp3 formats 2015-06-05 06:04:26 +08:00
Philipp Hagemeister
0e805e782b release 2015.06.04.1 2015-06-04 21:54:33 +02:00
Philipp Hagemeister
f5c78d118b release 2015.06.04 2015-06-04 21:49:02 +02:00
Yen Chi Hsuan
9d4f213f90 [qqmusic:toplist] List name and description are optional 2015-06-05 00:52:18 +08:00
Yen Chi Hsuan
168db222c6 Merge pull request #5891 from ping/qqmusic-toplist-fix
[qqmusic] Fix toplist extraction
2015-06-05 00:50:59 +08:00
Sergey M․
3d6388e34e [tnaflix] Fix relative URLs (empflix) 2015-06-04 20:42:37 +06:00
Sergey M․
3ce9bc712a [empflix] Fix typo 2015-06-04 20:39:03 +06:00
Sergey M․
e52c0bd0eb [tnaflix] Modernize 2015-06-04 20:37:05 +06:00
Sergey M․
56c837ccb7 [tnaflix] Fix typo 2015-06-04 20:34:48 +06:00
ping
55e5841f14 [qqmusic] Extract additional formats (mp3-128, mp3-320) 2015-06-04 17:41:29 +08:00
ping
ed15e9ba02 [qqmusic] Remove unused import 2015-06-04 17:32:06 +08:00
ping
eedda32e6b [qqmusic] Fix toplist 2015-06-04 11:27:18 +08:00
Jaime Marquínez Ferrándiz
4c8fea92f3 [test/aes] Fix on python 3.3 and higher
Since 878563c847 the aes functions only accepts the base64 data as a unicode string.
2015-06-03 23:50:38 +02:00
Sergey M.
d073055dcd Merge pull request #5876 from slava-sh/nova
[nova] Update
2015-06-03 23:18:01 +05:00
Slava Shklyaev
e4ac7bb1e5 [nova] Revert "Fix extension extraction bug"
This reverts commit 9464a194db.
2015-06-03 19:25:30 +03:00
Yen Chi Hsuan
9bac8c57e3 Merge branch 'iqiyi' of https://github.com/PeterDing/youtube-dl into PeterDing-iqiyi 2015-06-03 23:59:52 +08:00
Sergey M․
3153a2c98d [tvigle] Skip tests 2015-06-03 20:53:54 +06:00
Sergey M․
15b74b94be [tvigle] Capture error message 2015-06-03 20:52:47 +06:00
Sergey M․
687cb3ad35 [24video] Fix uploader extraction 2015-06-03 20:47:11 +06:00
Yen Chi Hsuan
8f94784124 [tumblr] Detect vid.me embeds (fixes #5883) 2015-06-03 10:26:39 +08:00
Yen Chi Hsuan
23dd1fc74c [vidme] Always use the non-embedded page
For example, https://vid.me/Wmur contains more information than
https://vid.me/e/Wmur
2015-06-03 10:24:02 +08:00
Slava Shklyaev
fa971259e6 [nova] Add a comment about html in description 2015-06-02 19:09:47 +03:00
Slava Shklyaev
b0cda32f72 [nova] Fix Python 2.6 compatability issue 2015-06-02 18:30:25 +03:00
Slava Shklyaev
08b7968e28 [nova] Fix display_id extraction bug 2015-06-02 18:24:19 +03:00
Slava Shklyaev
4b5fe1349f [nova] Comply with review 2015-06-02 18:23:42 +03:00
Sergey M․
d23da75b32 [iprima] Fix description extraction
`og:description` does not contain actual description anymore.
2015-06-02 21:10:18 +06:00
Sergey M.
06e027992d Merge pull request #5877 from slava-sh/iprima
[iprima] Update
2015-06-02 20:04:04 +05:00
Slava Shklyaev
b5597738d4 [iprima] Comply with review 2015-06-02 17:42:53 +03:00
Slava Shklyaev
bc03e58565 [iprima] Update 2015-06-02 13:19:02 +03:00
Slava Shklyaev
a00234f1c5 [nova] Minor style improvement 2015-06-02 12:57:03 +03:00
Slava Shklyaev
34c0f95db2 [nova] Remove html tags from description 2015-06-02 12:56:36 +03:00
Slava Shklyaev
fcb04bcaca [nova] Extract upload_date in some cases 2015-06-02 12:55:41 +03:00
Slava Shklyaev
9464a194db [nova] Fix extension extraction bug
Replace the hardcoded flv with determine_ext. Let rtmpdump parse the url.
2015-06-02 12:54:20 +03:00
Slava Shklyaev
9f4b9118cc [nova] Fix display_id extraction bug
Make id group non-greedy so that .html is not included in it.
2015-06-02 12:49:01 +03:00
Sergey M․
60158217ef [nova] Add tv test 2015-06-02 00:57:08 +06:00
Sergey M․
923e79e2e4 [nova] Add extractor 2015-06-02 00:53:04 +06:00
Naglis Jonaitis
866b296d0f [aftonbladet] Fix extraction and update _VALID_URL (Fixes #5863) 2015-06-01 16:12:11 +03:00
Yen Chi Hsuan
4053ee9104 Credit @PeterDing for 91porn extractor (#5830) 2015-06-01 14:44:10 +08:00
Sergey M․
47fd8c2f76 [patreon] Fix embeds extraction (Closes #5862) 2015-06-01 00:04:36 +06:00
Sergey M․
96b9690985 [imgur] Improve extraction 2015-05-31 04:05:26 +06:00
Sergey M․
df15ef8dab [YoutubeDL] Tweak select_format for video only media 2015-05-31 04:05:09 +06:00
Sergey M.
002c0fb511 Merge pull request #5852 from ivan/make-playlist-url
[youtube] Construct a playlist URL in case the page is missing one
2015-05-31 02:19:00 +05:00
Sergey M․
7584e38ce4 [tvigle] Modernize 2015-05-31 03:01:41 +06:00
Sergey M․
eb47569f8a [tvigle] Add support for m3u8 2015-05-31 03:00:13 +06:00
Ivan Kozik
d2a9de78df [youtube] Construct a playlist URL in case the page is missing one
This fixes jumping from user/channel -> playlist for some users like
https://www.youtube.com/user/BitcoinFoundation

This also removes the superfluous log message
"add --no-playlist to just download video VIDEOID"
when downloading a user/channel.
2015-05-30 20:54:03 +00:00
Sergey M․
c5138a7ce4 [extractor/generic] Clarify test comment 2015-05-31 02:36:20 +06:00
Sergey M․
c5fa81fe81 [extractor/generic] Put all direct link tests near to each other for better navigation 2015-05-31 02:22:29 +06:00
Sergey M․
a074e92296 [extractor/generic] Add test for large compressed media 2015-05-31 02:13:24 +06:00
Sergey M․
1ddb9456c4 [extractor/generic] Use compat_urllib_parse_unquote for unquoting video_id and title from URL 2015-05-31 01:23:58 +06:00
Sergey M․
58bde34a23 [extractor/generic] Force Accept-Encoding to any for extraction pass 2015-05-31 00:44:54 +06:00
Sergey M․
339516072b [extractor/generic] Unescape video_id and title extracted from URL 2015-05-30 23:16:14 +06:00
Sergey M․
931bc3c3a7 [YoutubeDL] Do not loose request method information 2015-05-30 22:52:02 +06:00
Yen Chi Hsuan
db1e9ee771 Merge branch 'PeterDing-porn91' 2015-05-31 00:33:30 +08:00
Yen Chi Hsuan
a2d971309b [porn91] Use single quotes 2015-05-31 00:31:18 +08:00
Yen Chi Hsuan
d05a1dbe70 [porn91] Catch daily limit error 2015-05-31 00:26:12 +08:00
Yen Chi Hsuan
a80601f8d9 [porn91] Extract more info 2015-05-31 00:20:37 +08:00
Yen Chi Hsuan
1c22238756 [porn91] Simplify 2015-05-31 00:03:19 +08:00
Yen Chi Hsuan
9ff811c5cd [porn91] PEP8 2015-05-30 23:35:55 +08:00
Yen Chi Hsuan
1ebc05df91 Merge branch 'porn91' of https://github.com/PeterDing/youtube-dl into PeterDing-porn91 2015-05-30 23:33:10 +08:00
Sergey M․
386bdfa698 [youtube:user] Workaround 35 pages limitation (Closes #5778) 2015-05-30 18:29:16 +06:00
Naglis Jonaitis
1ae7ff771b [tubitv] Add error message for videos that require login (#5524) 2015-05-30 14:33:27 +03:00
Naglis Jonaitis
5196b98897 [tubitv] Add new extractor (Closes #5524) 2015-05-30 14:16:18 +03:00
Sergey M․
e6e63e91a7 [tf1] Extend _VALID_URL (Closes #5848) 2015-05-30 16:18:11 +06:00
Sergey M․
b4dd98358f [vgtv] Properly handle lives 2015-05-30 16:12:07 +06:00
Sergey M․
181c7053e3 [YoutubeDL] Make sure all formats have unique format_id 2015-05-30 16:04:44 +06:00
Sergey M․
4d454c5e4b [vgtv] Check for inactive videos 2015-05-30 15:15:42 +06:00
Sergey M․
5c2191a605 [vgtv] Skip wasLive hds (Closes #5835) 2015-05-30 15:14:10 +06:00
Sergey M․
bba5bfc890 Merge branch 'ping-soompi' 2015-05-30 14:37:18 +06:00
Sergey M․
1a5b77dc21 [crunchyroll] Fix python 3.2 2015-05-30 14:36:45 +06:00
Sergey M․
b2cf6543b2 [soompi] Improve and simplify 2015-05-30 14:30:04 +06:00
Sergey M․
0385d64223 [crunchyroll] Extract subtitles extraction routine 2015-05-30 14:12:58 +06:00
pulpe
6ebdfe43e4 [tube8] fix extractor (fixes #5846) 2015-05-30 09:30:14 +02:00
Yen Chi Hsuan
fafec39d41 [spiegeltv] Changed RTMP server (fixes #5788 and fixes #5843)
Thanks to @brickleroux for finding out the problem
2015-05-30 13:23:09 +08:00
PeterDing
670861bd20 [iqiyi] Do not request for unneeded formats 2015-05-30 10:37:54 +08:00
PeterDing
08f7db20c1 [youku] change format_id 2015-05-30 10:03:32 +08:00
PeterDing
605ec701b7 [iqiyi] Add new extractor for iqiyi.com 2015-05-29 23:32:04 +08:00
pulpe
d6aa68ce75 [postprocessor/embedthumbnail] embed mp4 too (fixes #5840) 2015-05-29 12:47:20 +02:00
Philipp Hagemeister
eb6cb9fbe9 release 2015.05.29 2015-05-29 07:52:17 +02:00
Yen Chi Hsuan
84e1e036c2 [senate] Extend _VALID_URL (fixes #5836) 2015-05-29 12:44:31 +08:00
PeterDing
1498940b10 [youku] compare bytes and str for compatible; use compat_urllib_parse for making video_url 2015-05-29 10:13:09 +08:00
PeterDing
806598b94d [porn91] the one that _search_regex returns not needs to be checked 2015-05-29 08:21:24 +08:00
Sergey M․
e26be70bca Merge branch 'soompi' of https://github.com/ping/youtube-dl into ping-soompi 2015-05-28 22:22:29 +06:00
PeterDing
ca45246627 [youku] compatible for python > 3.3 or > 2.7 2015-05-28 21:04:58 +08:00
PeterDing
f9355dc989 [youku] update youku 2015-05-28 17:00:09 +08:00
Sergey M․
9e0b579128 [nowtv] Add test for rtlnitro 2015-05-28 01:26:14 +06:00
Sergey M․
ff4a1279f2 [nowtv] Do not request unnecessary metadata 2015-05-28 01:15:04 +06:00
Sergey M․
9b254aa177 [nowtv] Add non-free video check 2015-05-27 23:41:43 +06:00
PeterDing
703d78bbf5 [porn91] change re to _search_regex 2015-05-28 01:37:24 +08:00
Sergey M․
d9446c7319 Merge branch 'akirk-nowtv' 2015-05-27 23:22:19 +06:00
Sergey M․
b25b645d51 [nowtv] Improve and simplify 2015-05-27 23:20:32 +06:00
PeterDing
d90b3854ca [porn91] Add new extractor for 91porn.com 2015-05-28 00:37:00 +08:00
Sergey M․
bf24c3d017 [facebook] Improve title regex (Closes #5816) 2015-05-27 21:25:07 +06:00
Yen Chi Hsuan
f0bfaa2d7d [nrk] Update subtitles test
Subtitle conversion routine is removed, so the subtitles are TTML now. See
1c7e2e64f6
2015-05-27 15:23:34 +08:00
Yen Chi Hsuan
f9f3e3df9a [teamcoco] Use determine_ext to determine the video type
Some videos does not contain a 'type' field (#5798)
2015-05-27 14:51:18 +08:00
Yen Chi Hsuan
f8d5e1cfb5 [naver] Fix video url (fixes #5809)
RTMP urls in test:naver does not work. Need more investigation.
2015-05-27 14:44:08 +08:00
Yen Chi Hsuan
c23848b3c5 [naver] Enhanced error detection 2015-05-27 14:20:29 +08:00
Yen Chi Hsuan
6d00a2dcd1 [bilibili] Catch API call failures
JSON are returned in a failed API call
2015-05-27 04:23:21 +08:00
Yen Chi Hsuan
b535170b21 [bilibili] Skip assertion if HQ videos not available 2015-05-27 04:14:24 +08:00
Sergey M․
1434184c57 [spankwire] Do not modify aes key string 2015-05-27 01:42:53 +06:00
Sergey M․
7a372b64df [pornhub] Do not modify aes key string (Closes #5824) 2015-05-27 01:41:00 +06:00
Sergey M․
5406af92bc [dailymotion:user] Fix _VALID_URL 2015-05-26 22:16:47 +06:00
Sergey M․
7d65242dc3 [dailymotion:user] Process user home as user (Closes #5823) 2015-05-26 22:12:26 +06:00
Naglis Jonaitis
544a8693b7 Remove Firedrive and Sockshare imports
Oops
2015-05-26 13:53:14 +03:00
Naglis Jonaitis
35a4f24a37 [firedrive] Remove extractor (Closes #3870)
Haywire since last October.
2015-05-26 13:44:46 +03:00
Naglis Jonaitis
ff305edd64 [sockshare] Remove extractor
Haywire since last October.
2015-05-26 13:43:00 +03:00
Yen Chi Hsuan
efec4358b9 [cinemassacre] Support an alternative form of screenwavemedia URL
fixes #5821
2015-05-26 13:54:41 +08:00
Yen Chi Hsuan
db3ca36403 [facebook] Move the title extraction warning below (fixes #5820) 2015-05-26 13:41:38 +08:00
Yen Chi Hsuan
42833b44b5 [tf1] Extend _VALID_URL (fixes #5819) 2015-05-26 13:32:43 +08:00
Alexander Kirk
5d0a33eebc rtlnow is now hosted at nowtv.de 2015-05-25 20:36:25 +02:00
Sergey M․
ba2df04b41 [odnoklassniki] Make URL explicit 2015-05-25 21:27:43 +06:00
Sergey M․
c6bbdadd79 [odnoklassniki] Support extraction from metadata URL (Closes #5813) 2015-05-25 21:22:13 +06:00
Sergey M․
b885bae634 Credit @misterhat for karrierevideos (#5729) 2015-05-25 04:53:53 +06:00
Mister Hat
680f9744c4 [pinkbike] used proper conversion methods 2015-05-24 16:45:10 -05:00
Mister Hat
2c935c0c72 [pinkbike] converted duration to int 2015-05-24 16:30:03 -05:00
Mister Hat
7198063d96 [pinkbike] new extractor 2015-05-24 15:26:59 -05:00
Sergey M?
d41ebe146b [tenplay] Fix formats and modernize (Closes #5806) 2015-05-24 23:58:09 +06:00
Jaime Marquínez Ferrándiz
4b4e1af059 [arte] Remove unused import 2015-05-24 18:46:29 +02:00
Sergey M.
80240b347e Merge pull request #5780 from jaimeMF/remove-nondash
[youtube] Remove the nondash formats (fixes #5774)
2015-05-24 21:42:15 +05:00
Jaime Marquínez Ferrándiz
04b3b3df05 [youtube] Remove the nondash formats (fixes #5774)
Since we use fixed values for some fields like width and height they can be wrong, and would get picked by some formats filters.
For example for https://www.youtube.com/watch?v=EQCrhbBxsjA the biggest height is 720 and for nondash formats it's set to 1440, so -f 'bestvideo[height>=1200]+bestaudio' would incorrectly pick the nondash format, instead it should report that the requested format is not available.
2015-05-24 18:26:20 +02:00
Sergey M․
2ad5708c43 [arte:future] Switch to search_regex for now (Closes #5801) 2015-05-24 21:25:00 +06:00
Sergey M․
63f3cab4ae [rtbf] Fix extraction (Closes #5803) 2015-05-24 21:09:08 +06:00
Sergey M․
8cdf03a7a2 Merge branch 'misterhat-karrierevideos' 2015-05-24 20:14:54 +06:00
Sergey M․
d78c834ead [karrierevideos] Improve and simplify 2015-05-24 20:04:13 +06:00
Sergey M․
05a976cd99 Merge branch 'karrierevideos' of https://github.com/misterhat/youtube-dl into misterhat-karrierevideos 2015-05-24 19:19:48 +06:00
Sergey M․
34fb7e46ad [empflix] Relax _VALID_URL 2015-05-24 19:11:40 +06:00
Sergey M․
abac15f3c6 [tnaflix] Do not capture cat_id 2015-05-24 19:11:31 +06:00
Sergey M.
b700055ba4 Merge pull request #5772 from frenchy1983/fix_tnaflix_regex
[TNAFlix] Allow dot (and more) in cat_id and display_id
2015-05-24 17:54:25 +05:00
Sergey M.
23905927e1 [README.md] Keep more idiomatic rwx order 2015-05-24 18:32:04 +06:00
Sergey M.
56be5f1567 Merge pull request #5800 from WassimAttar/patch-1
[README.md] chmod error
2015-05-24 17:29:26 +05:00
WassimAttar
1807ae22dd chmod error
After installing youtube-dl with this method
    sudo wget https://yt-dl.org/downloads/latest/youtube-dl -O /usr/local/bin/youtube-dl
    sudo chmod a+xr /usr/local/bin/youtube-dl
When i try to use it, i get this error
    python: can't open file '/usr/local/bin/youtube-dl': [Errno 13] Permission denied

The correct chmod is a+xr
2015-05-24 10:37:05 +02:00
Sergey M․
71646e4653 [YoutubeDL] Initialize files_to_delete (Closes #5797) 2015-05-24 04:14:01 +06:00
Sergey M?
1335c3aca8 [drtv] Improve extraction (Closes #5792) 2015-05-24 01:22:11 +06:00
Yen Chi Hsuan
30455ce255 [nextmedia] Extend and reorder _VALID_URL 2015-05-24 02:42:01 +08:00
Yen Chi Hsuan
9bf87ae3aa [nextmedia] Merge AppleDailyRealtimeNewsIE and AppleDailyAnimationNewsIE 2015-05-24 02:36:47 +08:00
Yen Chi Hsuan
abca34cbc0 [cnn] Relax _VALID_URL again (fixes #5737)
The problem is the same as test:CNN_1, so I didn't add the test case
2015-05-24 02:04:02 +08:00
Sergey M․
d386878af9 [prosiebensat1] Add support for .at domain names (Closes #5786) 2015-05-23 21:25:53 +06:00
Sergey M․
685c74d315 [rutv] Extend embed URL (Closes #5782) 2015-05-23 01:01:47 +06:00
Sergey M․
69e0f1b445 Credit @ping for viki:channel, qqmusic:toplist 2015-05-23 00:08:10 +06:00
Jaime Marquínez Ferrándiz
79979c6897 Clarify that --dump-pages encodes the pages using base64 (#5781) 2015-05-22 16:15:50 +02:00
Jaime Marquínez Ferrándiz
ba64547616 [sportbox] Remove unused import 2015-05-22 11:35:09 +02:00
frenchy1983
ed5a637d62 [TNAFlix] Restore test
See dstftw's comment in #5772
2015-05-22 09:29:35 +02:00
Yen Chi Hsuan
8a278a1d7e [nba] Fix duration extraction (fixes #5777) 2015-05-22 13:30:39 +08:00
Sergey M․
77d9cb2f04 [sportbox] Fix extraction 2015-05-22 00:45:33 +06:00
Sergey M․
0459432d96 [shared] Fix for python 3.2 2015-05-22 00:10:53 +06:00
Sergey M․
43150d7ac3 [shared] Fix for python 3.2 2015-05-22 00:10:05 +06:00
Sergey M․
afe8b594be [rtve.es:alacarta] Fix for python 3.2 2015-05-22 00:09:15 +06:00
Sergey M․
878563c847 [aes] Fix for python 3.2 2015-05-22 00:06:10 +06:00
Sergey M․
06947add03 [chilloutzone] Fix for python 3.2 2015-05-22 00:03:47 +06:00
Sergey M․
5cd47a5e4f [videott] Fix for python 3.2 2015-05-21 23:58:46 +06:00
Sergey M․
53de95da5e [viki] Extend _VALID_URLs 2015-05-21 22:27:22 +06:00
Sergey M․
663004ac2b [options] Clarify --metadata-from-title additional templates 2015-05-21 22:06:25 +06:00
Jaime Marquínez Ferrándiz
6ad9cb224a [mitele] It now uses m3u8 (#5764)
It should also be possible to use Adobe HDS, but it would require more work.
2015-05-21 12:02:53 +02:00
frenchy1983
e7752cd578 [TNAFlix] Allow dot (and more) in cat_id and display_id
URLs with dots were raising a "UnsupportedError: Unsupported URL" error.
2015-05-21 11:47:16 +02:00
Jaime Marquínez Ferrándiz
4d2f42361e [viki] remove unused import 2015-05-21 11:42:20 +02:00
Sergey M․
4d8ee01389 [viki] Fix typo 2015-05-21 02:38:43 +06:00
Sergey M․
d01924f488 [viki:channel] Extend matching URLs and extract movies 2015-05-21 02:30:04 +06:00
Sergey M․
bc56355ec6 [viki:channel] Switch to API 2015-05-21 02:08:13 +06:00
Sergey M․
ac20d95f97 [viki] Add support for youtube externals 2015-05-21 01:56:02 +06:00
Sergey M․
1a83c731bd [viki] Switch extraction to API 2015-05-21 01:44:05 +06:00
Sergey M․
ca57a59883 Merge branch 'ping-viki-shows' 2015-05-20 22:10:06 +06:00
Sergey M․
b0d619fde2 [viki:channel] Extract title from JSON 2015-05-20 21:28:04 +06:00
Sergey M․
cc7051efd7 Merge branch 'viki-shows' of https://github.com/ping/youtube-dl into ping-viki-shows 2015-05-20 20:17:47 +06:00
ping
5137adb94d [soompi] Switch to non-geoblocked test video 2015-05-20 16:16:10 +08:00
Philipp Hagemeister
0b9f7cd074 release 2015.05.20 2015-05-20 10:01:48 +02:00
ping
2632941f32 [soompi] Add new extractor for tv.soompi.com 2015-05-20 15:53:45 +08:00
ping
137597b0ea [dramafever] Streamline code 2015-05-20 15:15:28 +08:00
Yen Chi Hsuan
051df9ad99 [letv/sohu] Skip tests relying on external proxies
The proxy is currently broken. See #5655 and zhuzhuor/Unblock-Youku#427
2015-05-20 14:08:23 +08:00
ping
f670ef1c8e [dramafever] Add new extractor for dramafever.com 2015-05-20 13:51:43 +08:00
Sergey M․
d9d747a06a [ultimedia] Fix extraction 2015-05-19 21:28:41 +06:00
Yen Chi Hsuan
b813d8caf1 [qqmusic] Unescape '\\n' in description (#5705) 2015-05-19 01:01:42 +08:00
Yen Chi Hsuan
ecee572411 [yahoo] Add support for closed captions (closes #5714) 2015-05-19 00:50:24 +08:00
Yen Chi Hsuan
1b0427e6c4 [utils] Support TTML without default namespace
In a strict sense such TTML is invalid, but Yahoo uses it.
2015-05-19 00:45:01 +08:00
Jaime Marquínez Ferrándiz
2aa64b89b3 tox: Pass HOME environment variable
Since version 2.0 it only passes a limited set of variables and we need HOME for the tests
2015-05-18 17:58:53 +02:00
Sergey M․
484c9d2d5b [vier] Fix extraction 2015-05-18 21:43:54 +06:00
Sergey M․
5d8dcb5342 [vuclip] Fix extraction 2015-05-18 21:39:15 +06:00
Sergey M․
2328f2fe68 [vulture] Fix extraction 2015-05-18 21:34:20 +06:00
Sergey M․
4f514c7e88 [wimp] Fix youtube extraction (Closes #5690) 2015-05-18 21:29:41 +06:00
Sergey M․
5bdc520cf1 [xminus] Fix extraction 2015-05-18 21:23:05 +06:00
Jaime Marquínez Ferrándiz
fc6e75dd57 [instagram] Only recognize https urls (fixes #5739)
http urls redirect to them.
2015-05-18 11:21:09 +02:00
Sergey M․
4a5a898a8f [YoutubeDL] Clarify incompatible formats merge message
When `-f` is not specified it's misleading to see `You have requested ...` as user did not actually request any formats.
2015-05-17 20:56:03 +06:00
Mister Hat
ba9d16291b manually specify namespace 2015-05-17 03:35:08 -05:00
Mister Hat
725652e924 [karrierevideos] add support for www.karrierevideos.at (closes #5354) 2015-05-16 19:50:58 -05:00
ping
8da0e0e946 [viki] Change IE name to channel, better message output 2015-05-17 06:19:38 +08:00
Sergey M․
588b82bbf8 [tv2:article] Add extractor (Closes #5724) 2015-05-17 03:32:53 +06:00
Sergey M․
bc0f937b55 [tv2] Add extractor (#5724) 2015-05-17 03:01:52 +06:00
Sergey M․
baa43cbaf0 [extractor/common] Relax valid url check verbosity 2015-05-17 02:59:35 +06:00
Sergey M․
adb6b1b316 Merge branch 'viki-shows' of https://github.com/ping/youtube-dl into ping-viki-shows 2015-05-17 00:38:58 +06:00
ping
1c18de0019 [viki] Add proper paging and include clips 2015-05-17 01:38:50 +08:00
Jaime Marquínez Ferrándiz
4d52f2eb7f [sbs] Remove unused import 2015-05-16 18:38:28 +02:00
Sergey M․
363cf58645 Merge branch 'viki-shows' of https://github.com/ping/youtube-dl into ping-viki-shows 2015-05-16 21:28:36 +06:00
Sergey M․
7e760fc188 [espn] Add extractor (#4396)
Unfinished
2015-05-16 21:14:19 +06:00
Sergey M․
ef2dcbe4ad [sbs] Fix extraction (Closes #5725) 2015-05-16 21:07:29 +06:00
Sergey M․
9354a5fad4 [ooyala] Fix unresolved reference 2015-05-16 20:15:31 +06:00
Sergey M․
1c97b0a777 [ooyala:external] Add extractor 2015-05-16 20:00:40 +06:00
ping
2f3bdab2b9 [viki] Fix code format 2015-05-16 15:56:37 +08:00
ping
0d7f036429 [viki] Add support for shows 2015-05-16 15:43:13 +08:00
Sergey M.
2cda13213d Merge pull request #5717 from blissland/master
[CBSNewsIE] Relax thumbnail regex so test passes
2015-05-15 22:36:07 +05:00
Sergey M․
70d0d43b5e [rts] Check formats (Closes #5711) 2015-05-15 23:32:25 +06:00
Sergey M․
25c3a7348f [generic] Fix typo 2015-05-15 23:23:51 +06:00
Sergey M․
9123d64592 Merge branch 'maddoger-sportbox-fix' 2015-05-15 23:19:21 +06:00
Sergey M․
b827a6015c [generic] Add test for sportbox embeds 2015-05-15 23:18:21 +06:00
Sergey M․
d40a3b5b55 [generic] Add support for sportbox embeds 2015-05-15 23:09:34 +06:00
Sergey M․
ef28a6cb26 [sportbox:embed] Relax thumbnail 2015-05-15 23:09:10 +06:00
Sergey M․
1436a6835e [sportbox:embed] Add _extract_urls 2015-05-15 23:08:44 +06:00
blissland
e8cfacae37 [CBSNewsIE] Relax thumbnail regex so test passes 2015-05-15 17:57:32 +01:00
Sergey M․
3a7382950b [sportbox:embed] Add extractor 2015-05-15 22:50:44 +06:00
Jaime Marquínez Ferrándiz
eeb23eb7ea [gamespot] The protocol is not optional 2015-05-15 18:44:08 +02:00
Jaime Marquínez Ferrándiz
34fe5a94ba [gamespot] Add support for videos that don't use 'f4m_stream' (fixes #5707) 2015-05-15 18:42:59 +02:00
Sergey M․
6181864290 Merge branch 'sportbox-fix' of https://github.com/maddoger/youtube-dl into maddoger-sportbox-fix 2015-05-15 22:09:18 +06:00
Vitaliy Syrchikov
e9ca615a98 New test 2015-05-15 19:57:54 +04:00
Sergey M․
62c95fd5fc [youtube:feed] Check each 'load more' portion for unique video ids 2015-05-15 21:42:34 +06:00
Sergey M․
25f14e9f93 [youtube] Separate feed extractor 2015-05-15 21:06:59 +06:00
Vitaliy Syrchikov
ae670a6ed8 Sportbox source fix. HD videos support. 2015-05-15 17:53:05 +04:00
Vitaliy Syrchikov
a7b8467ac0 Sportbox extractor fix. 2015-05-15 16:52:11 +04:00
blissland
15da7ce7fb Fix file format extraction regex and update test file checksum 2015-05-15 14:12:52 +02:00
Jaime Marquínez Ferrándiz
e9eaf3fbcf [test/YoutubeDL] Add tests for 'playliststart', 'playlistend' and 'playlist_items' 2015-05-15 14:08:26 +02:00
Jaime Marquínez Ferrándiz
3884dcf313 YoutubeDL: ignore indexes from 'playlist_items' that are not in the list (fixes #5706)
We ignore them instead of failing to match the behaviour of the 'playliststart' parameter.
2015-05-15 14:08:26 +02:00
Philipp Hagemeister
c4fc559f45 release 2015.05.15 2015-05-15 10:13:43 +02:00
Jaime Marquínez Ferrándiz
2bc4330303 [youtube:history] Fix extraction (fixes #5702)
It uses the same method as YoutubeSubscriptionsIE, if other feed starts using it we should consider using base class.
2015-05-14 23:41:27 +02:00
Yen Chi Hsuan
12675275a1 [teamcoco] Detect expired videos (#5626) 2015-05-15 02:28:41 +08:00
Yen Chi Hsuan
3a105f7b20 [teamcoco] Rewrite preload data extraction
Idea: "puncture" some consecutive fragments and check whether the
b64decode result of a punctured string is a valid JSON or not.

It's a O(N^3) algorithm, but should be fast for a small N (less than 30
fragments in all test cases)
2015-05-15 02:28:40 +08:00
Sergey M․
1ae72fb23d [soundcloud:user] Defer download link resolve (Closes #5248)
Looks like final download links can expire before downloading process reach them. So, resolving download links right before actual downloading.
2015-05-14 22:28:42 +06:00
Yen Chi Hsuan
7ec676bb3d [qqmusic] Add IE_NAME for all extractors 2015-05-14 23:32:36 +08:00
Yen Chi Hsuan
29ea57283e [qqmusic] Refactoring QQMusicToplistIE 2015-05-14 23:28:42 +08:00
Yen Chi Hsuan
5488973961 [qqmusic] flake8 2015-05-14 23:25:43 +08:00
Yen Chi Hsuan
96d45a5489 Merge pull request #5680 from ping/qqmusic-toplist-ie
[qqmusic] Add support for charts / top lists
2015-05-14 23:23:32 +08:00
Sergey M․
7a012d5a16 [screenwavemedia] Add support for player2 URLs (Closes #5696) 2015-05-14 16:39:35 +06:00
Yen Chi Hsuan
fa6a16996e [worldstarhiphop] Support Android URLs (fixes #5629) 2015-05-14 18:00:57 +08:00
Sergey M․
82245a6de7 [YoutubeDL] Restore filename for thumbnails 2015-05-14 15:21:27 +06:00
Sergey M․
ff28ede2d1 Merge branch 'dstftw-best-fallback-on-outdated-avconv' 2015-05-14 15:19:14 +06:00
Sergey M․
98b8ec8616 Merge branch 'best-fallback-on-outdated-avconv' of https://github.com/dstftw/youtube-dl into dstftw-best-fallback-on-outdated-avconv
Conflicts:
	youtube_dl/YoutubeDL.py
2015-05-14 15:18:58 +06:00
Yen Chi Hsuan
88f9d8748c Merge remote-tracking branch 'upstream/master' 2015-05-14 17:07:02 +08:00
Sergey M․
7d57d2e18b [canalplus] Restore checksums in tests 2015-05-14 14:59:27 +06:00
Sergey M.
38caa00d18 Merge pull request #5695 from blissland/master
[CanalplusIE] Update tests that were no longer working
2015-05-14 13:57:56 +05:00
Yen Chi Hsuan
c827d4cfdb [xattr] Enhanced error messages on Windows 2015-05-14 16:53:10 +08:00
blissland
509c630db8 [CanalplusIE] Update tests that were no longer working 2015-05-14 08:09:56 +01:00
Yen Chi Hsuan
fbff30d2db [xattr] Catch 'Argument list too long' 2015-05-14 14:51:00 +08:00
Yen Chi Hsuan
86c7fdb17c [xattr] Enhance error handling to catch ENOSPC
Fixes #5589
2015-05-14 14:28:41 +08:00
Yen Chi Hsuan
62bd6589c7 Merge pull request #5692 from yan12125/fix-embedthumbnailpp
Use thumbnails downloaded by YoutubeDL in EmbedThumbnailPP
2015-05-14 12:35:58 +08:00
Yen Chi Hsuan
2cc6d13547 [postprocessor/embedthumbnail] Encode arguments in calling AtomicParsley 2015-05-14 04:41:30 +08:00
Yen Chi Hsuan
bb8ca1d112 [postprocessor/embedthumbnail] Use run_ffmpeg_multiple_files 2015-05-14 02:35:28 +08:00
Yen Chi Hsuan
8e59539752 [postprocessor/embedthumbnail] Use thumbnails downloaded by YoutubeDL 2015-05-14 02:32:00 +08:00
Sergey M․
372744c544 [odnoklassniki] Fix extraction (Closes #5671) 2015-05-13 22:26:30 +06:00
Sergey M.
83880949a1 Merge pull request #5682 from blissland/master
[BYUtvIE] Relax thumbnail regex so test does not fail
2015-05-13 19:36:22 +05:00
Yen Chi Hsuan
3749e36e9f [YoutubeDL] Fix PEP8 W503 2015-05-13 21:16:45 +08:00
blissland
0b4253fa37 [BYUtvIE] Change thumbnail regex so test does not fail 2015-05-12 18:57:06 +01:00
ping
86ec1e487c [qqmusic] Code fixes 2015-05-13 01:37:56 +08:00
ping
fd4eefed39 [qqmusic] Fix extraction for global list 2015-05-13 01:14:02 +08:00
ping
b480e7874b [qqmusic] Fix code formatting 2015-05-12 22:41:37 +08:00
ping
41333b97b9 [qqmusic] Add support for charts / top lists 2015-05-12 22:35:16 +08:00
Yen Chi Hsuan
c1c924abfe [utils,common] Merge format_srt_time and _subtitles_timecode
format_srt_time uses a comma as the delimiter between seconds and
milliseconds while _subtitles_timecode uses a dot. All .srt examples I
found on the Internet uses a comma, so I use a comma in the merged
version. See http://matroska.org/technical/specs/subtitles/srt.html and
http://devel.aegisub.org/wiki/SubtitleFormats/SRT
2015-05-12 13:04:54 +08:00
Yen Chi Hsuan
1c7e2e64f6 [nrk] Remove TTML to srt conversion codes
A common routine is implemented in utils.py and can be used via
--convert-subtitles.
2015-05-12 12:55:14 +08:00
Yen Chi Hsuan
7dff03636a [utils] Support 'dur' field in TTML 2015-05-12 12:47:37 +08:00
Yen Chi Hsuan
5332fd91bf [nytimes] Correct _VALID_URL of NYTimesArticleIE 2015-05-12 12:42:13 +08:00
Sergey M․
d4b963d0a6 [vine] Relax alt_title (Closes #5677) 2015-05-12 01:54:56 +06:00
Sergey M․
6d3f5935e5 [southpark] Fix IE_NAME 2015-05-11 23:47:50 +06:00
rrooij
968ee17677 [southparkdk] Add extractor 2015-05-11 23:45:38 +06:00
rrooij
81ed3bb9c0 [southpark] Sort alphabetically 2015-05-11 23:45:29 +06:00
Sergey M․
5115652828 [zingmp3] Capture error message 2015-05-11 21:31:36 +06:00
Sergey M․
1f92865494 [dumpert] Add cpc cookie (Closes #5672) 2015-05-11 21:05:39 +06:00
Yen Chi Hsuan
e41f450f28 [tmz] Add support for articles (fixes #5477) 2015-05-11 20:06:10 +08:00
Sergey M․
97fcf1bbd0 [YoutubeDL] Check if merger can actually merge 2015-05-11 02:01:16 +06:00
Sergey M․
13763ce599 [postprocessor/ffmpeg] Add can_merge method 2015-05-11 02:00:31 +06:00
Sergey M․
7fcb605b82 [YoutubeDL] Fallback to -f best when merger is outdated 2015-05-11 00:27:29 +06:00
Sergey M․
70484b9f8a [postprocessor/ffmpeg] Extract check_outdated method 2015-05-11 00:26:39 +06:00
Jaime Marquínez Ferrándiz
69b46b3d95 ExecAfterDownloadPP: fix __init__ method 2015-05-10 17:47:49 +02:00
Jaime Marquínez Ferrándiz
95c5534f8e ExecAfterDownloadPP, YoutubeDL: remove unused parameters 2015-05-10 17:41:11 +02:00
Sergey M․
370b39e8ec [voicerepublic] Fix fallback branch formats extraction 2015-05-10 18:37:52 +06:00
Sergey M․
3da8038918 Merge branch 'duncankl-voicerepublic' 2015-05-10 18:29:36 +06:00
Sergey M․
a6762c4a22 [voicerepublic] Make more robust and extract more metadata 2015-05-10 18:29:15 +06:00
Sergey M․
98c2c0febc Merge branch 'voicerepublic' of https://github.com/duncankl/youtube-dl into duncankl-voicerepublic 2015-05-10 17:31:55 +06:00
Yen Chi Hsuan
63cbd19f50 [ndr] Replace the 404 test case 2015-05-10 18:30:26 +08:00
Yen Chi Hsuan
1934f3a0ea [ndr] Extended to support n-joy.de as well (closes #4527)
According to http://en.wikipedia.org/wiki/N-Joy, n-joy.de is a service
hosted by NDR, so I put them together.
2015-05-10 18:22:07 +08:00
ping
a909e6ad43 [dailymotion] Patch upload_date detection.
(closes #5665)
2015-05-10 11:13:14 +02:00
Duncan
1dcb52188d [voicerepublic] Remove hardcoded paths to media files 2015-05-10 17:06:34 +12:00
Duncan
28ebef0b1b [voicerepublic] Detect list of available formats from the web page 2015-05-10 16:03:09 +12:00
Duncan
f03a8a3c4e [voicerepublic] Raise ExtractorError if audio is still being processed 2015-05-10 15:50:06 +12:00
Duncan
03f760b1c0 [voicerepublic] Remove creator field 2015-05-10 15:41:27 +12:00
Duncan
f900dc3fb9 [voicerepublic] Extract author using _html_search_meta 2015-05-10 15:01:58 +12:00
Sergey M․
95eb1adda8 [life:embed] Sort formats 2015-05-10 08:54:50 +06:00
Duncan
c6ddbdb66c [voicerepublic] Add new extractor 2015-05-10 12:39:24 +12:00
Sergey M․
3800b908b1 [mlb] Fix #5663 2015-05-10 06:14:34 +06:00
Philipp Hagemeister
69fe3a5f09 release 2015.05.10 2015-05-10 01:05:24 +02:00
Sergey M․
754270313a [life:embed] Move to separated extractor and extract m3u8 formats 2015-05-10 01:03:26 +06:00
Sergey M․
057ebeaca3 [lifenews] Add test for #5660 2015-05-10 00:27:49 +06:00
Sergey M․
480065172d [lifenews] Add support for video URLs (Closes #5660) 2015-05-10 00:26:42 +06:00
Sergey M․
f2e0056579 [vgtv] Avoid duplicate format_id 2015-05-09 21:23:09 +06:00
Sergey M․
32fffff2cc [eroprofile] Fix video URL extraction (Closes #5657) 2015-05-09 21:19:09 +06:00
Sergey M.
3c47824d6b Merge pull request #5658 from blissland/master
[BRIE] Updated two test cases
2015-05-09 20:07:21 +05:00
blissland
0892090a56 Added audio test for BRIE 2015-05-09 16:02:07 +01:00
blissland
d592b42f5c Updated two tests for BRIE 2015-05-09 15:26:00 +01:00
Jaime Marquínez Ferrándiz
3b5f65a64c [mlb] Fix extraction of articles
And move test from generic, since it's directly handled by MLBIE
2015-05-09 12:41:56 +02:00
Jaime Marquínez Ferrándiz
5c0b2c16a8 [vgtv] Escape '#' in _VALID_URL and remove empty newlines at the end
In verbose mode, '#' is interpreted as the start of a comment.
2015-05-09 12:34:45 +02:00
Yen Chi Hsuan
d39e0f05db [utils] Remove sanitize_url_path_consecutive_slashes()
This function is used only in SohuIE, which is updated to use a new
extraction logic.
2015-05-09 17:37:39 +08:00
Yen Chi Hsuan
6d14d08e06 [yam] Fix title and uploader id 2015-05-09 17:36:07 +08:00
Yen Chi Hsuan
32060c6d6b [sohu] Update extractor
The original extraction logic always fails for all test videos
2015-05-09 14:02:11 +08:00
Yen Chi Hsuan
3dbec410a0 [sohu] Enhance error handling 2015-05-09 14:02:11 +08:00
Sergey M․
de765f6c31 [foxsports] Support some more URLs (#5611) 2015-05-09 02:15:51 +06:00
Sergey M․
dc455a5f88 [extractor/generic] Add test for svt embed 2015-05-09 00:27:37 +06:00
Sergey M․
bab19a8e91 [extractor/generic] Add support for svt embeds (Closes #5622) 2015-05-09 00:23:35 +06:00
Sergey M․
322915014f [svtplay] Rename to svt 2015-05-09 00:13:40 +06:00
Sergey M․
79998cd5af [svtplay] Generalize svt extractors and add svt.se extractor 2015-05-09 00:12:42 +06:00
Sergey M.
50b9013064 [README.md] Fix typo 2015-05-08 23:21:23 +06:00
Sergey M.
bb03fdae0d [README.md] Clarify format selection when streaming to stdout 2015-05-08 23:19:57 +06:00
Sergey M․
4384cf9e7d [extractor/__init__] Fix alphabetic order 2015-05-08 23:04:27 +06:00
Sergey M.
d47e980d0d Merge pull request #5641 from dstftw/preserve-best-for-stdout-outtmpl
[YoutubeDL] Do not force bestvideo+bestaudio when outtmpl is stdout
2015-05-08 22:01:50 +05:00
Sergey M․
fe373287eb [vgtv] Add support for bt vestlendingen (Closes #5620) 2015-05-08 22:59:50 +06:00
Sergey M․
cbe443362f [aftenposten] Implement in terms of xtream extractor 2015-05-08 22:52:20 +06:00
Sergey M․
2c0c9dc46c [xstream] Move xstream to separate extractor 2015-05-08 22:50:01 +06:00
Sergey M․
0ceab84749 [vgtv] Add support for bt.no articles (#5620) 2015-05-08 22:18:43 +06:00
Sergey M․
34e7dc81a9 [vgtv] Add support for generic bt.no URLs (#5620) 2015-05-08 22:03:03 +06:00
Sergey M․
4e6e9d21bd [mlb] Improve _VALID_URL 2015-05-08 21:48:47 +06:00
Sergey M․
d1feb30811 [mlb] Fallback to extracting video id from webpage for all URLs that does not contain it explicitly (Closes #5630) 2015-05-08 20:07:53 +06:00
blissland
43837189c1 Fix URL template extraction for netzkino. Fixes #5614 2015-05-08 12:20:34 +02:00
blissland
249962ffa2 [bet] Use unique part of xml url as the video id and fix tests (closes #5642)
The guid changes often.
2015-05-08 11:31:05 +02:00
Jaime Marquínez Ferrándiz
541168039d [utils] get_exe_version: encode executable name (fixes #5647)
It failed in python 2.x when $PATH contains a directory with non-ascii characters.
2015-05-08 11:01:24 +02:00
Yen Chi Hsuan
7ef00afe9d [nhl] Support RTMP videos (fixes #4481) 2015-05-08 03:11:25 +08:00
Yen Chi Hsuan
156fc83a55 [downloader/rtmp] Fix a typo 2015-05-08 03:11:24 +08:00
Naglis Jonaitis
46be82b811 [vessel] Use main_video_asset when searching for video_asset (Fixes #5623) 2015-05-07 22:00:07 +03:00
Yen Chi Hsuan
09b412dafa [nhl] Partial support for hlg id (fixes #4285) 2015-05-08 02:14:28 +08:00
Jaime Marquínez Ferrándiz
5268a05e47 [ooyala] Style fix 2015-05-07 17:04:15 +02:00
Sergey M․
406224be52 [extractor/generic] Fix following incomplete redirects (#5640) 2015-05-07 21:02:59 +06:00
Sergey M․
3799834dcf [YoutubeDL] Do not force bestvideo+bestaudio when outtmpl is stdout (#5627) 2015-05-07 20:46:11 +06:00
Yen Chi Hsuan
553e412bda Merge branch 'master' of github.com:rg3/youtube-dl 2015-05-07 22:24:49 +08:00
Sergey M․
f22834a372 [bild] Relax thumbnail test check 2015-05-07 20:20:43 +06:00
Sergey M.
bd349a8704 Merge pull request #5638 from blissland/master
[BildIE] Fix ampersands in xml attributes & update test thumbnails
2015-05-07 19:18:35 +05:00
blissland
bc08873cff Fix indents 2015-05-07 15:09:27 +01:00
Yen Chi Hsuan
aafe273990 [ooyala] Use SAS API to extract info (fixes #4336) 2015-05-07 22:07:32 +08:00
blissland
c09593c04e [BildIE] Escape ampersands in xml and update test thumbnail 2015-05-07 15:07:11 +01:00
Yen Chi Hsuan
84bf31aaf8 [ooyala] Extract m3u8 information (#2292) 2015-05-07 18:12:01 +08:00
Yen Chi Hsuan
05d5392cda [common] Ignore subtitles in m3u8 2015-05-07 18:06:22 +08:00
Yen Chi Hsuan
d9a743d917 [vice] Remove a redundant print 2015-05-07 18:05:37 +08:00
Yen Chi Hsuan
ac6c358c2a [teamcoco] Fix extracting preload data again 2015-05-07 12:58:00 +08:00
Sergey M․
ad0c0ad3b4 [historicfilms] Fix tape id extraction 2015-05-06 21:52:26 +06:00
Sergey M․
1ed34f3dd6 [gorillavid] Switch 404 test to only matching 2015-05-06 21:43:36 +06:00
Sergey M․
6a8f9cd22e [giga] Fix view count extraction 2015-05-06 21:39:53 +06:00
Sergey M․
e8b9ab8957 [pbs] Add format_id for direct links 2015-05-06 21:31:25 +06:00
Sergey M․
74f728249f [extractor/common] Fallback to empty string for (yet) missing format_id in _sort_formats (Closes #5624) 2015-05-06 21:24:24 +06:00
blissland
d6a1738892 [archive.org] Fix incorrect url condition (closes #5628)
The condition for assigning to json_url is the wrong way round:

currently for url: aaa.com/xxx

we get:

aaa.com/xxx&output=json

instead of the correct value:

aaa.com/xxx?output=json
2015-05-06 15:06:10 +02:00
Sergey M․
b326b07adc [lifenews] Use _proto_relative_url 2015-05-05 21:49:36 +06:00
Yen Chi Hsuan
07d2921c6d [lifenews] Correctly determine iframe links (fixes #5618) 2015-05-05 23:39:54 +08:00
Sergey M.
22e462c97a Merge pull request #5612 from rrooij/southparknl
Southparknl
2015-05-05 19:32:27 +05:00
rrooij
dcf8077906 [southparknl] Fix test to match playlist tests 2015-05-05 09:17:21 +02:00
rrooij
3408f6e64a [southparkde] Fix naming inconsistency
The class was first called 'SouthparkDe'. It is now changed to
'SouthParkDe' to match the name of the other extractors.
2015-05-05 09:01:07 +02:00
rrooij
e10dc0e1f0 [southparknl] Add extractor for southpark.nl 2015-05-05 08:59:09 +02:00
Sergey M․
ce5c1ae517 [noco] Remove unused import 2015-05-05 02:52:21 +06:00
Sergey M․
bbe718c97f Merge branch 'Tassatux-noco' 2015-05-05 02:50:58 +06:00
Sergey M․
01e4b1ee14 [noco] Update tests 2015-05-05 02:50:39 +06:00
Sergey M․
815ac0293e [noco] Modernize 2015-05-05 02:38:13 +06:00
Sergey M․
6568382d6f [noco] Extract all variations of audio/subtitles media 2015-05-05 02:27:24 +06:00
Sergey M․
f943b7ddce Merge branch 'noco' of https://github.com/Tassatux/youtube-dl into Tassatux-noco 2015-05-05 00:39:24 +06:00
Aurélien Dunand
ff9d68e7be [noco] Add test for multi languages video 2015-05-04 19:55:29 +02:00
Aurélien Dunand
7212560f4d [noco] Retrieve video language according to user options 2015-05-04 18:06:12 +02:00
Sergey M․
1aa43d77c0 [rutv] Remove superfluous check 2015-05-04 21:29:56 +06:00
Sergey M․
e038d5c4e3 [rutv] Fix preference 2015-05-04 21:29:32 +06:00
Sergey M․
dfad3aac98 [rutv] Fix live stream test URL 2015-05-04 21:23:26 +06:00
Yen Chi Hsuan
df8418ffcf [nytimes] Extend _VALID_URL (#2754) 2015-05-04 23:03:47 +08:00
Yen Chi Hsuan
50aa43b3ae [nytimes] Implement extracting videos from articles (closes #5436) 2015-05-04 23:03:47 +08:00
Jaime Marquínez Ferrándiz
a90552663e [livestream:original] Update url format (fixes #5598) 2015-05-04 16:54:01 +02:00
Jaime Marquínez Ferrándiz
883340c107 [livestream:original] Fix extraction (fixes #4702) 2015-05-04 16:52:17 +02:00
Yen Chi Hsuan
0fe2ff78e6 [NBC] Enhance embedURL extraction (closes #2549) 2015-05-04 21:55:04 +08:00
Philipp Hagemeister
dc1eed93be release 2015.05.04 2015-05-04 15:12:48 +02:00
Sergey M․
b2f82360d7 [escapist] Add uploader to tests 2015-05-04 19:06:07 +06:00
Sergey M․
782e0568ef [escapist] Modernize 2015-05-04 19:04:49 +06:00
Sergey M․
90b4b0eabe [escapist] Improve _VALID_URL 2015-05-04 19:01:08 +06:00
Sergey M․
cec04ef3a6 [escapist] Update tests' checksums 2015-05-04 19:00:34 +06:00
Sergey M․
71fa56b887 [escapist] Fix formats extraction 2015-05-04 18:59:22 +06:00
Yen Chi Hsuan
b9b3ab45ea [NBC] Enhance extraction of ThePlatform URL (fixes #5470) 2015-05-04 19:09:18 +08:00
Philipp Hagemeister
957b794c26 release 2015.05.03 2015-05-03 22:31:39 +02:00
Yen Chi Hsuan
8001607e90 [generic] Detect more MLB videos (fixes #5443) 2015-05-04 02:20:07 +08:00
Yen Chi Hsuan
3e7202c1bc [MLB] Extend _VALID_URL (#5443) 2015-05-04 01:59:26 +08:00
Yen Chi Hsuan
848edeab89 [lifenews] Detect <iframe> (fixes #5346) 2015-05-04 01:24:19 +08:00
Yen Chi Hsuan
1748d67aea [lifenews] Fix view count and comment count 2015-05-04 01:11:23 +08:00
Jaime Marquínez Ferrándiz
5477ca8239 [dailymotion] Use https urls
The video url still redirects to an http url, but it doesn't explicitly contain the video id.
2015-05-03 16:59:14 +02:00
Sergey M․
d0fd305023 [rutv] Add test for #5584 2015-05-03 10:00:34 +06:00
Sergey M․
8dab1e9072 [rutv] Recognize live streams (#5584) 2015-05-03 09:56:03 +06:00
Sergey M․
963aea5279 [baiduvideo] Improve _VALID_URL 2015-05-03 07:45:15 +06:00
Sergey M․
0a64aa7355 [vgtv] Fix _VALID_URL (Closes #5578) 2015-05-03 00:58:42 +06:00
Sergey M․
0669c89c55 [options] Clarify --write-annotations help 2015-05-02 23:38:30 +06:00
Sergey M․
2699da8041 [YoutubeDL] Improve description file naming 2015-05-02 23:36:55 +06:00
Sergey M․
98727e123f [YoutubeDL] Improve annotations file naming 2015-05-02 23:35:18 +06:00
Sergey M․
b29e0000e6 [YoutubeDL] Improve JSON info file naming 2015-05-02 23:23:44 +06:00
Sergey M․
b3ed15b760 [utils] Add replace_extension 2015-05-02 23:23:06 +06:00
Sergey M․
666a9a2b95 [YoutubeDL] Improve audio/video-only file naming 2015-05-02 23:11:34 +06:00
Sergey M․
a4bcaad773 [test_utils] Add tests for prepend_extension 2015-05-02 23:10:48 +06:00
Sergey M․
e65e4c8874 [utils] Improve prepend_extension
Now `ext` is appended to filename if real extension != expected extension.
2015-05-02 23:06:01 +06:00
Yen Chi Hsuan
21f6330274 [baiduvideo] Add new extractor (closes #4563) 2015-05-03 00:53:24 +08:00
Sergey M․
38c6902b90 [YoutubeDL] Ensure correct extension is always present for a merged file (Closes #5535) 2015-05-02 22:52:21 +06:00
Jaime Marquínez Ferrándiz
2ddcd88129 Remove code that was only used by the Grooveshark extractor 2015-05-02 17:29:56 +02:00
Yen Chi Hsuan
dd8920653c [Grooveshark] Remove the extractor
grooveshark.com was shut down on 2015/04/30
2015-05-02 21:46:33 +08:00
Sergey M․
c938c35f95 [iconosquare] Fix extraction 2015-05-02 07:18:22 +06:00
Yen Chi Hsuan
2eb0192155 [viki] Remove clean_html call 2015-05-02 01:35:46 +08:00
Yen Chi Hsuan
d948e09b61 [viki] Extract m3u8 videos (#4855) 2015-05-02 01:20:16 +08:00
Yen Chi Hsuan
89966a5aea [viki] Enhance error message handling (#3774) 2015-05-02 01:20:15 +08:00
Yen Chi Hsuan
8e3df9dfee [viki] Fix extractor and add a global availble test case 2015-05-02 01:20:15 +08:00
Sergey M․
5890eef6b0 [pbs] Add support for HD (Closes #3564, closes #5390) 2015-05-01 17:43:06 +06:00
Nikoli
083c1bb960 Add ability to embed subtitles in mkv files (closes #5434) 2015-05-01 11:54:40 +02:00
Yen Chi Hsuan
861e65eb05 [yahoo] Extend _VALID_URL 2015-05-01 12:32:24 +08:00
Sergey M․
650cfd0cb0 [bbccouk] Mute thumbnail 2015-05-01 04:07:30 +06:00
Sergey M․
e68ae99a41 [bbccouk] Add test for #5530 2015-05-01 04:02:56 +06:00
Sergey M․
8683b4d8d9 [bbccouk] Improve extraction (Closes #5530) 2015-05-01 03:59:13 +06:00
Sergey M․
1dbd717eb4 [theplaform] Fix FutureWarning 2015-05-01 02:51:55 +06:00
Sergey M․
6a8422b942 [foxsports] Add extractor (Closes #5517) 2015-05-01 02:49:06 +06:00
Sergey M․
cb202fd286 [YoutubeDL] Filter requested info fields on --load-info as well
In order to properly handle JSON info files generated by youtube-dl versions prior to 4070b458ec
2015-05-01 00:44:34 +06:00
Naglis Jonaitis
67fc8ecd53 [dreisat] Extend _VALID_URL (Closes #5548) 2015-04-30 21:28:08 +03:00
Jaime Marquínez Ferrándiz
df8301fef5 [YoutubeDL] pep8: use 'k not in' instead of 'not k in' 2015-04-30 20:18:42 +02:00
Sergey M․
4070b458ec [YoutubeDL] Do not write requested info in info JSON file (Closes #5562, closes #5564) 2015-04-30 23:55:05 +06:00
Yen Chi Hsuan
ffbc3901d2 Merge remote-tracking branch 'upstream/master' 2015-04-30 23:33:49 +08:00
Sergey M․
7a03280df4 [vporn] More metadata extraction fixes and tests update (#5560) 2015-04-30 21:31:38 +06:00
Yen Chi Hsuan
482a1258de [VeeHD] Replace the third test case due to copyright issues 2015-04-30 23:27:07 +08:00
Sergey M․
cd298882cd [vporn] Fix metadata extraction (#5560) 2015-04-30 21:25:17 +06:00
Sergey M․
e01c56f9e1 [YoutubeDL] Generalize best/worst format match behavior 2015-04-30 21:06:51 +06:00
Sergey M.
4d72df4031 Merge pull request #5556 from jaimeMF/best-format-nodash
Make 'best' format only match non-DASH formats (closes #5554)
2015-04-30 19:57:02 +05:00
Yen Chi Hsuan
f7f1df1d82 [VeeHD] Enhance extraction and fix tests (fixes #4965) 2015-04-30 22:37:41 +08:00
Yen Chi Hsuan
c4a21bc9db [bilibili] Extract multipart videos (closes #3250) 2015-04-30 18:26:08 +08:00
Yen Chi Hsuan
621ffe7bf4 [niconico] Fix so* video extraction (fixes #4874) (#2087) 2015-04-30 17:05:02 +08:00
Jaime Marquínez Ferrándiz
8dd5418803 Make 'best' format only match non-DASH formats (closes #5554)
Otherwise it's impossible to only download non-DASH formats, for example `best[height=?480]/best` would download a DASH video if it's the only one with height=480, instead for falling back to the second format specifier.
For audio only urls (soundcloud, bandcamp ...), the best audio will be downloaded as before.
2015-04-29 22:53:18 +02:00
Jaime Marquínez Ferrándiz
965cb8d530 [escapist] pep8 fixes 2015-04-29 22:46:19 +02:00
Yen Chi Hsuan
b2e8e7dab5 [niconico] Try to extract all optional fields from various sources 2015-04-30 02:24:05 +08:00
Yen Chi Hsuan
59d814f793 [niconico] Remove credentials from tests and enhance title extraction
All test videos can be downloaded without username and password now.
2015-04-30 00:50:48 +08:00
Yen Chi Hsuan
bb865f3a5e [niconico] Fix extraction and update tests (closes #5511) 2015-04-30 00:50:48 +08:00
Yen Chi Hsuan
9ee53a49f0 [YouPorn] Fix extractor 2015-04-30 00:50:48 +08:00
Sergey M.
79adb09baa Merge pull request #5553 from zouhair/master
Typo: twice "the the" to "the"
2015-04-29 20:05:48 +05:00
zouhair
cf0649f8b7 Typo: twice "the the" to "the" 2015-04-29 11:03:10 -04:00
Sergey M.
f8690631e2 Merge pull request #5552 from zouhair/master
Typo "incompatible" instead of "uncompatible"
2015-04-29 19:09:47 +05:00
zouhair
5456d78f0c Typo "incompatible" instead of "uncompatible" 2015-04-29 10:07:49 -04:00
Yen Chi Hsuan
cbbece96a2 [yourupload] Simplify 2015-04-29 04:05:14 +08:00
Yen Chi Hsuan
9d8ba307ef [yourupload] Fix extraction 2015-04-29 04:03:07 +08:00
Yen Chi Hsuan
ec7c1e85e0 [testtube] Fix test case 1
Seems the site now provides webm with higher bitrates
2015-04-29 00:24:58 +08:00
Yen Chi Hsuan
e70c7568c0 [testtube] Detect Youtube iframes (fixes #4867) 2015-04-29 00:22:17 +08:00
Yen Chi Hsuan
39b62db116 [youtube] Catch more alert messages (closes #5074) 2015-04-28 23:07:56 +08:00
Jaime Marquínez Ferrándiz
2edce52584 [vimeo] Fix password protected videos again (#5082)
Since they have changed again to the previous format, I've modified the regex to match both formats.
2015-04-28 15:06:08 +02:00
pulpe
10831b5ec9 [vimeo] Fix redirection 2015-04-28 14:56:48 +02:00
Philipp Hagemeister
3a0f0c263a release 2015.04.28 2015-04-28 09:11:18 +02:00
Sergey M․
2419a376b9 [moniker] Check not found error (#5541) 2015-04-27 23:46:16 +06:00
Sergey M․
e206740fd7 [moniker] Capture and output error message (#5541) 2015-04-27 23:44:05 +06:00
Sergey M․
290a5a8d85 [escapist] Fix imsVideo regex (#5090) 2015-04-27 22:17:51 +06:00
pulpe
e2dc351d25 [escapist] Fix extractor (fixes #5090) 2015-04-27 17:44:13 +02:00
Sergey M․
c86b61428b [utils] Fix another old python 2.6 kwargs issue (Closes #5539) 2015-04-27 20:00:18 +06:00
Sergey M.
40b96352c9 Merge pull request #5523 from jaimeMF/remove-format-limit
Remove the --max-quality option
2015-04-27 16:44:58 +05:00
Sergey M.
189ba90996 [README] Use youtube-dl test video URL 2015-04-27 16:05:01 +06:00
Sergey M.
c8183e661d [README] Document special characters escaping (#5538) 2015-04-27 16:01:30 +06:00
Sergey M․
053c94f1b3 [README] Clarify youtube-dl version when format selection changed to bestvideo+bestaudio/best 2015-04-27 15:21:51 +06:00
Sergey M․
b9d76a9571 Merge branch 'fstirlitz-philharmoniedeparis' 2015-04-27 03:36:46 +06:00
Sergey M․
a01cfc2951 [philharmoniedeparis] Fix extraction and tests, improve, simplify 2015-04-27 03:36:32 +06:00
felix
06d07c4000 New extractor: live.philharmoniedeparis.fr 2015-04-26 14:15:29 +02:00
Jaime Marquínez Ferrándiz
0d1bd5d62f README: remove --max-quality 2015-04-25 15:14:16 +02:00
Jaime Marquínez Ferrándiz
9f3fa89f7c Remove the --max-quality option
It doesn't work well with 'bestvideo' and 'bestaudio' because they are usually before the max quality.
Format filters should be used instead, they are more flexible and don't require the requested quality to exist for each video.
2015-04-25 11:59:54 +02:00
203 changed files with 7914 additions and 2670 deletions

View File

@@ -124,3 +124,9 @@ Mohammad Teimori Pabandi
Roman Le Négrate
Matthias Küch
Julian Richen
Ping O.
Mister Hat
Peter Ding
jackyzy823
George Brighton
Remita Amine

View File

@@ -17,12 +17,12 @@ youtube-dl - download videos from youtube.com or other video platforms
To install it right away for all UNIX users (Linux, OS X, etc.), type:
sudo curl https://yt-dl.org/latest/youtube-dl -o /usr/local/bin/youtube-dl
sudo chmod a+x /usr/local/bin/youtube-dl
sudo chmod a+rx /usr/local/bin/youtube-dl
If you do not have curl, you can alternatively use a recent wget:
sudo wget https://yt-dl.org/downloads/latest/youtube-dl -O /usr/local/bin/youtube-dl
sudo chmod a+x /usr/local/bin/youtube-dl
sudo chmod a+rx /usr/local/bin/youtube-dl
Windows users can [download a .exe file](https://yt-dl.org/latest/youtube-dl.exe) and place it in their home directory or any other location on their [PATH](http://en.wikipedia.org/wiki/PATH_%28variable%29).
@@ -52,8 +52,9 @@ which means you can modify it, redistribute it or use it however you like.
-i, --ignore-errors Continue on download errors, for example to skip unavailable videos in a playlist
--abort-on-error Abort downloading of further videos (in the playlist or the command line) if an error occurs
--dump-user-agent Display the current browser identification
--list-extractors List all supported extractors and the URLs they would handle
--list-extractors List all supported extractors
--extractor-descriptions Output descriptions of all supported extractors
--force-generic-extractor Force extraction to use the generic extractor
--default-search PREFIX Use this prefix for unqualified URLs. For example "gvsearch2:" downloads two videos from google videos for youtube-dl "large apple".
Use the value "auto" to let youtube-dl guess ("auto_warning" to emit a warning when guessing). "error" just throws an error. The
default value "fixup_error" repairs broken URLs, but emits an error if this is not possible instead of searching.
@@ -107,7 +108,7 @@ which means you can modify it, redistribute it or use it however you like.
--playlist-reverse Download playlist videos in reverse order
--xattr-set-filesize Set file xattribute ytdl.filesize with expected filesize (experimental)
--hls-prefer-native Use the native HLS downloader instead of ffmpeg (experimental)
--external-downloader COMMAND Use the specified external downloader. Currently supports aria2c,curl,wget
--external-downloader COMMAND Use the specified external downloader. Currently supports aria2c,curl,httpie,wget
--external-downloader-args ARGS Give these arguments to the external downloader
## Filesystem Options:
@@ -133,7 +134,7 @@ which means you can modify it, redistribute it or use it however you like.
--no-mtime Do not use the Last-modified header to set the file modification time
--write-description Write video description to a .description file
--write-info-json Write video metadata to a .info.json file
--write-annotations Write video annotations to a .annotation file
--write-annotations Write video annotations to a .annotations.xml file
--load-info FILE JSON file containing the video information (created with the "--write-info-json" option)
--cookies FILE File to read cookies from and dump cookie jar in
--cache-dir DIR Location in the filesystem where youtube-dl can store some downloaded information permanently. By default $XDG_CACHE_HOME/youtube-dl
@@ -168,7 +169,7 @@ which means you can modify it, redistribute it or use it however you like.
--no-progress Do not print progress bar
--console-title Display progress in console titlebar
-v, --verbose Print various debugging information
--dump-pages Print downloaded pages to debug problems (very verbose)
--dump-pages Print downloaded pages encoded using base64 to debug problems (very verbose)
--write-pages Write downloaded intermediary pages to files in the current directory to debug problems
--print-traffic Display sent and read HTTP traffic
-C, --call-home Contact the youtube-dl server for debugging
@@ -188,10 +189,9 @@ which means you can modify it, redistribute it or use it however you like.
-f, --format FORMAT Video format code, see the "FORMAT SELECTION" for all the info
--all-formats Download all available video formats
--prefer-free-formats Prefer free video formats unless a specific one is requested
--max-quality FORMAT Highest quality format to download
-F, --list-formats List all available formats
--youtube-skip-dash-manifest Do not download the DASH manifest on YouTube videos
--merge-output-format FORMAT If a merge is required (e.g. bestvideo+bestaudio), output to given container format. One of mkv, mp4, ogg, webm, flv.Ignored if no
--youtube-skip-dash-manifest Do not download the DASH manifests and related data on YouTube videos
--merge-output-format FORMAT If a merge is required (e.g. bestvideo+bestaudio), output to given container format. One of mkv, mp4, ogg, webm, flv. Ignored if no
merge is required
## Subtitle Options:
@@ -217,14 +217,14 @@ which means you can modify it, redistribute it or use it however you like.
--recode-video FORMAT Encode the video to another format if necessary (currently supported: mp4|flv|ogg|webm|mkv)
-k, --keep-video Keep the video file on disk after the post-processing; the video is erased by default
--no-post-overwrites Do not overwrite post-processed files; the post-processed files are overwritten by default
--embed-subs Embed subtitles in the video (only for mp4 videos)
--embed-subs Embed subtitles in the video (only for mkv and mp4 videos)
--embed-thumbnail Embed thumbnail in the audio as cover art
--add-metadata Write metadata to the video file
--metadata-from-title FORMAT Parse additional metadata like song title / artist from the video title. The format syntax is the same as --output, the parsed
parameters replace existing values. Additional templates: %(album), %(artist). Example: --metadata-from-title "%(artist)s -
parameters replace existing values. Additional templates: %(album)s, %(artist)s. Example: --metadata-from-title "%(artist)s -
%(title)s" matches a title like "Coldplay - Paradise"
--xattrs Write metadata to the video file's xattrs (using dublin core and xdg standards)
--fixup POLICY Automatically correct known faults of the file. One of never (do nothing), warn (only emit a warning), detect_or_warn(the default;
--fixup POLICY Automatically correct known faults of the file. One of never (do nothing), warn (only emit a warning), detect_or_warn (the default;
fix file if we can, warn otherwise)
--prefer-avconv Prefer avconv over ffmpeg for running the postprocessors (default)
--prefer-ffmpeg Prefer ffmpeg over avconv for running the postprocessors
@@ -270,9 +270,9 @@ The simplest case is requesting a specific format, for example `-f 22`. You can
If you want to download multiple videos and they don't have the same formats available, you can specify the order of preference using slashes, as in `-f 22/17/18`. You can also filter the video results by putting a condition in brackets, as in `-f "best[height=720]"` (or `-f "[filesize>10M]"`). This works for filesize, height, width, tbr, abr, vbr, asr, and fps and the comparisons <, <=, >, >=, =, != and for ext, acodec, vcodec, container, and protocol and the comparisons =, != . Formats for which the value is not known are excluded unless you put a question mark (?) after the operator. You can combine format filters, so `-f "[height <=? 720][tbr>500]"` selects up to 720p videos (or videos where the height is not known) with a bitrate of at least 500 KBit/s. Use commas to download multiple formats, such as `-f 136/137/mp4/bestvideo,140/m4a/bestaudio`. You can merge the video and audio of two formats into a single file using `-f <video-format>+<audio-format>` (requires ffmpeg or avconv), for example `-f bestvideo+bestaudio`.
Since the end of April 2015 youtube-dl uses `-f bestvideo+bestaudio/best` as default format selection (see #5447, #5456). If ffmpeg or avconv are installed this results in downloading `bestvideo` and `bestaudio` separately and muxing them together into a single file giving the best overall quality available. Otherwise it falls back to `best` and results in downloading best available quality served as a single file. `best` is also needed for videos that don't come from YouTube because they don't provide the audio and video in two different files. If you want to only download some dash formats (for example if you are not interested in getting videos with a resolution higher than 1080p), you can add `-f bestvideo[height<=?1080]+bestaudio/best` to your configuration file.
Since the end of April 2015 and version 2015.04.26 youtube-dl uses `-f bestvideo+bestaudio/best` as default format selection (see #5447, #5456). If ffmpeg or avconv are installed this results in downloading `bestvideo` and `bestaudio` separately and muxing them together into a single file giving the best overall quality available. Otherwise it falls back to `best` and results in downloading best available quality served as a single file. `best` is also needed for videos that don't come from YouTube because they don't provide the audio and video in two different files. If you want to only download some dash formats (for example if you are not interested in getting videos with a resolution higher than 1080p), you can add `-f bestvideo[height<=?1080]+bestaudio/best` to your configuration file. Note that if you use youtube-dl to stream to `stdout` (and most likely to pipe it to your media player then), i.e. you explicitly specify output template as `-o -`, youtube-dl still uses `-f best` format selection in order to start content delivery immediately to your player and not to wait until `bestvideo` and `bestaudio` are downloaded and muxed.
If you want to preserve the old format selection behavior (pre-April 2015), i.e. you want to download best available quality media served as a single file, you should explicitly specify your choice with `-f best`. You may want to add it to the [configuration file](#configuration) in order not to type it every time you run youtube-dl.
If you want to preserve the old format selection behavior (prior to youtube-dl 2015.04.26), i.e. you want to download best available quality media served as a single file, you should explicitly specify your choice with `-f best`. You may want to add it to the [configuration file](#configuration) in order not to type it every time you run youtube-dl.
# VIDEO SELECTION
@@ -324,9 +324,9 @@ YouTube changed their playlist format in March 2014 and later on, so you'll need
If you have installed youtube-dl with a package manager, pip, setup.py or a tarball, please use that to update. Note that Ubuntu packages do not seem to get updated anymore. Since we are not affiliated with Ubuntu, there is little we can do. Feel free to [report bugs](https://bugs.launchpad.net/ubuntu/+source/youtube-dl/+filebug) to the [Ubuntu packaging guys](mailto:ubuntu-motu@lists.ubuntu.com?subject=outdated%20version%20of%20youtube-dl) - all they have to do is update the package to a somewhat recent version. See above for a way to update.
### Do I always have to pass in `--max-quality FORMAT`, or `-citw`?
### Do I always have to pass `-citw`?
By default, youtube-dl intends to have the best options (incidentally, if you have a convincing case that these should be different, [please file an issue where you explain that](https://yt-dl.org/bug)). Therefore, it is unnecessary and sometimes harmful to copy long option strings from webpages. In particular, `--max-quality` *limits* the video quality (so if you want the best quality, do NOT pass it in), and the only option out of `-citw` that is regularly useful is `-i`.
By default, youtube-dl intends to have the best options (incidentally, if you have a convincing case that these should be different, [please file an issue where you explain that](https://yt-dl.org/bug)). Therefore, it is unnecessary and sometimes harmful to copy long option strings from webpages. In particular, the only option out of `-citw` that is regularly useful is `-i`.
### Can you please put the -b option back?
@@ -358,13 +358,29 @@ YouTube has switched to a new video info format in July 2011 which is not suppor
YouTube requires an additional signature since September 2012 which is not supported by old versions of youtube-dl. See [above](#how-do-i-update-youtube-dl) for how to update youtube-dl.
### Video URL contains an ampersand and I'm getting some strange output `[1] 2839` or `'v' is not recognized as an internal or external command` ###
That's actually the output from your shell. Since ampersand is one of the special shell characters it's interpreted by shell preventing you from passing the whole URL to youtube-dl. To disable your shell from interpreting the ampersands (or any other special characters) you have to either put the whole URL in quotes or escape them with a backslash (which approach will work depends on your shell).
For example if your URL is https://www.youtube.com/watch?t=4&v=BaW_jenozKc you should end up with following command:
```youtube-dl 'https://www.youtube.com/watch?t=4&v=BaW_jenozKc'```
or
```youtube-dl https://www.youtube.com/watch?t=4\&v=BaW_jenozKc```
For Windows you have to use the double quotes:
```youtube-dl "https://www.youtube.com/watch?t=4&v=BaW_jenozKc"```
### ExtractorError: Could not find JS function u'OF'
In February 2015, the new YouTube player contained a character sequence in a string that was misinterpreted by old versions of youtube-dl. See [above](#how-do-i-update-youtube-dl) for how to update youtube-dl.
### HTTP Error 429: Too Many Requests or 402: Payment Required
These two error codes indicate that the service is blocking your IP address because of overuse. Contact the service and ask them to unblock your IP address, or - if you have acquired a whitelisted IP address already - use the [`--proxy` or `--network-address` options](#network-options) to select another IP address.
These two error codes indicate that the service is blocking your IP address because of overuse. Contact the service and ask them to unblock your IP address, or - if you have acquired a whitelisted IP address already - use the [`--proxy` or `--source-address` options](#network-options) to select another IP address.
### SyntaxError: Non-ASCII character ###

View File

@@ -10,12 +10,14 @@
- **56.com**
- **5min**
- **8tracks**
- **91porn**
- **9gag**
- **abc.net.au**
- **Abc7News**
- **AcademicEarth:Course**
- **AddAnime**
- **AdobeTV**
- **AdobeTVVideo**
- **AdultSwim**
- **Aftenposten**
- **Aftonbladet**
@@ -26,8 +28,7 @@
- **anitube.se**
- **AnySex**
- **Aparat**
- **AppleDailyAnimationNews**
- **AppleDailyRealtimeNews**
- **AppleDaily**
- **AppleTrailers**
- **archive.org**: archive.org videos
- **ARD**
@@ -44,6 +45,7 @@
- **audiomack**
- **audiomack:album**
- **Azubu**
- **BaiduVideo**
- **bambuser**
- **bambuser:channel**
- **Bandcamp**
@@ -63,6 +65,8 @@
- **BR**: Bayerischer Rundfunk Mediathek
- **Break**
- **Brightcove**
- **bt:article**: Bergens Tidende Articles
- **bt:vestlendingen**: Bergens Tidende - Vestlendingen
- **BuzzFeed**
- **BYUtv**
- **Camdemy**
@@ -107,6 +111,7 @@
- **dailymotion**
- **dailymotion:playlist**
- **dailymotion:user**
- **DailymotionCloud**
- **daum.net**
- **DBTV**
- **DctpTv**
@@ -117,6 +122,8 @@
- **divxstage**: DivxStage
- **Dotsub**
- **DouyuTV**
- **dramafever**
- **dramafever:series**
- **DRBonanza**
- **Dropbox**
- **DrTuber**
@@ -139,6 +146,7 @@
- **Eporner**
- **EroProfile**
- **Escapist**
- **ESPN** (Currently broken)
- **EveryonesMixtape**
- **exfm**: ex.fm
- **ExpoTV**
@@ -148,13 +156,14 @@
- **fc2**
- **fernsehkritik.tv**
- **fernsehkritik.tv:postecke**
- **Firedrive**
- **Firstpost**
- **FiveTV**
- **Flickr**
- **Folketinget**: Folketinget (ft.dk; Danish parliament)
- **FootyRoom**
- **Foxgay**
- **FoxNews**
- **FoxSports**
- **france2.fr:generation-quoi**
- **FranceCulture**
- **FranceInter**
@@ -184,7 +193,6 @@
- **Golem**
- **GorillaVid**: GorillaVid.in, daclips.in, movpod.in, fastvideo.in and realvid.net
- **Goshgay**
- **Grooveshark**
- **Groupon**
- **Hark**
- **HearThisAt**
@@ -214,6 +222,7 @@
- **instagram:user**: Instagram user profile
- **InternetVideoArchive**
- **IPrima**
- **iqiyi**
- **ivi**: ivi.ru
- **ivi:compilation**: ivi.ru compilations
- **Izlesene**
@@ -226,6 +235,7 @@
- **KanalPlay**: Kanal 5/9/11 Play
- **Kankan**
- **Karaoketv**
- **KarriereVideos**
- **keek**
- **KeezMovies**
- **KhanAcademy**
@@ -239,6 +249,7 @@
- **LetvPlaylist**
- **LetvTv**
- **Libsyn**
- **life:embed**
- **lifenews**: LIFE | NEWS
- **LiveLeak**
- **livestream**
@@ -272,6 +283,7 @@
- **Motherless**
- **Motorsport**: motorsport.com
- **MovieClips**
- **MovieFap**
- **Moviezine**
- **movshare**: MovShare
- **MPORA**
@@ -287,6 +299,7 @@
- **MySpass**
- **myvideo**
- **MyVidster**
- **N-JOY**
- **n-tv.de**
- **NationalGeographic**
- **Naver**
@@ -314,8 +327,10 @@
- **Noco**
- **Normalboots**
- **NosVideo**
- **Nova**: TN.cz, Prásk.tv, Nova.cz, Novaplus.cz, FANDA.tv, Krásná.cz and Doma.cz
- **novamov**: NovaMov
- **Nowness**
- **NowTV**
- **nowvideo**: NowVideo
- **npo.nl**
- **npo.nl:live**
@@ -327,11 +342,14 @@
- **ntv.ru**
- **Nuvid**
- **NYTimes**
- **NYTimesArticle**
- **ocw.mit.edu**
- **Odnoklassniki**
- **OktoberfestTV**
- **on.aol.com**
- **OnionStudios**
- **Ooyala**
- **OoyalaExternal**
- **OpenFilm**
- **orf:fm4**: radio FM4
- **orf:iptv**: iptv.ORF.at
@@ -340,8 +358,10 @@
- **parliamentlive.tv**: UK parliament videos
- **Patreon**
- **PBS**
- **PhilharmonieDeParis**: Philharmonie de Paris
- **Phoenix**
- **Photobucket**
- **Pinkbike**
- **Pladform**
- **PlanetaPlay**
- **play.fm**
@@ -362,9 +382,11 @@
- **prosiebensat1**: ProSiebenSat.1 Digital
- **Puls4**
- **Pyvideo**
- **QQMusic**
- **QQMusicAlbum**
- **QQMusicSinger**
- **qqmusic**
- **qqmusic:album**
- **qqmusic:playlist**
- **qqmusic:singer**
- **qqmusic:toplist**
- **QuickVid**
- **R7**
- **radio.de**
@@ -383,7 +405,6 @@
- **Rte**
- **rtl.nl**: rtl.nl and rtlxl.nl
- **RTL2**
- **RTLnow**
- **RTP**
- **RTS**: RTS.ch
- **rtve.es:alacarta**: RTVE a la carta
@@ -396,6 +417,7 @@
- **rutube:movie**: Rutube movies
- **rutube:person**: Rutube person videos
- **RUTV**: RUTV.RU
- **Ruutu**
- **safari**: safaribooksonline.com online video
- **safari:course**: safaribooksonline.com online courses
- **Sandia**: Sandia National Laboratories
@@ -420,9 +442,12 @@
- **smotri:broadcast**: Smotri.com broadcasts
- **smotri:community**: Smotri.com community videos
- **smotri:user**: Smotri.com user videos
- **SnagFilms**
- **SnagFilmsEmbed**
- **Snotr**
- **Sockshare**
- **Sohu**
- **soompi**
- **soompi:show**
- **soundcloud**
- **soundcloud:playlist**
- **soundcloud:set**
@@ -432,6 +457,8 @@
- **southpark.cc.com**
- **southpark.cc.com:español**
- **southpark.de**
- **southpark.nl**
- **southparkstudios.dk**
- **Space**
- **SpankBang**
- **Spankwire**
@@ -441,6 +468,7 @@
- **Spike**
- **Sport5**
- **SportBox**
- **SportBoxEmbed**
- **SportDeutschland**
- **Srf**
- **SRMediathek**: Saarländischer Rundfunk
@@ -451,6 +479,7 @@
- **StreamCZ**
- **StreetVoice**
- **SunPorno**
- **SVT**
- **SVTPlay**: SVT Play and Öppet arkiv
- **SWRMediathek**
- **Syfy**
@@ -477,6 +506,7 @@
- **TheOnion**
- **ThePlatform**
- **TheSixtyOne**
- **ThisAmericanLife**
- **ThisAV**
- **THVideo**
- **THVideoPlaylist**
@@ -484,6 +514,7 @@
- **tlc.com**
- **tlc.de**
- **TMZ**
- **TMZArticle**
- **TNAFlix**
- **tou.tv**
- **Toypics**: Toypics user profile
@@ -492,13 +523,18 @@
- **Trilulilu**
- **TruTube**
- **Tube8**
- **TubiTv**
- **Tudou**
- **Tumblr**
- **TuneIn**
- **Turbo**
- **Tutv**
- **tv.dfb.de**
- **TV2**
- **TV2Article**
- **TV4**: tv4.se and tv4play.se
- **TVC**
- **TVCArticle**
- **tvigle**: Интернет-телевидение Tvigle.ru
- **tvp.pl**
- **tvp.pl:Series**
@@ -511,6 +547,7 @@
- **twitch:stream**
- **twitch:video**
- **twitch:vod**
- **TwitterCard**
- **Ubu**
- **udemy**
- **udemy:course**
@@ -527,7 +564,7 @@
- **Vessel**
- **Vesti**: Вести.Ru
- **Vevo**
- **VGTV**
- **VGTV**: VGTV and BTTV
- **vh1.com**
- **Vice**
- **Viddler**
@@ -547,6 +584,7 @@
- **vier:videos**
- **Viewster**
- **viki**
- **viki:channel**
- **vimeo**
- **vimeo:album**
- **vimeo:channel**
@@ -561,6 +599,7 @@
- **vk.com**
- **vk.com:user-videos**: vk.com:All of a user's videos
- **Vodlocker**
- **VoiceRepublic**
- **Vporn**
- **VRT**
- **vube**: Vube.com
@@ -583,8 +622,10 @@
- **XBef**
- **XboxClips**
- **XHamster**
- **XHamsterEmbed**
- **XMinus**
- **XNXX**
- **Xstream**
- **XTube**
- **XTubeUser**: XTube user profile
- **Xuite**
@@ -598,7 +639,7 @@
- **YesJapan**
- **Ynet**
- **YouJizz**
- **Youku**
- **youku**
- **YouPorn**
- **YourUpload**
- **youtube**: YouTube.com

View File

@@ -8,7 +8,6 @@
"forcetitle": false,
"forceurl": false,
"format": "best",
"format_limit": null,
"ignoreerrors": false,
"listformats": null,
"logtostderr": false,

View File

@@ -12,6 +12,7 @@ import copy
from test.helper import FakeYDL, assertRegexpMatches
from youtube_dl import YoutubeDL
from youtube_dl.compat import compat_str
from youtube_dl.extractor import YoutubeIE
from youtube_dl.postprocessor.common import PostProcessor
from youtube_dl.utils import match_filter_func
@@ -101,39 +102,6 @@ class TestFormatSelection(unittest.TestCase):
downloaded = ydl.downloaded_info_dicts[0]
self.assertEqual(downloaded['ext'], 'flv')
def test_format_limit(self):
formats = [
{'format_id': 'meh', 'url': 'http://example.com/meh', 'preference': 1},
{'format_id': 'good', 'url': 'http://example.com/good', 'preference': 2},
{'format_id': 'great', 'url': 'http://example.com/great', 'preference': 3},
{'format_id': 'excellent', 'url': 'http://example.com/exc', 'preference': 4},
]
info_dict = _make_result(formats)
ydl = YDL()
ydl.process_ie_result(info_dict)
downloaded = ydl.downloaded_info_dicts[0]
self.assertEqual(downloaded['format_id'], 'excellent')
ydl = YDL({'format_limit': 'good'})
assert ydl.params['format_limit'] == 'good'
ydl.process_ie_result(info_dict.copy())
downloaded = ydl.downloaded_info_dicts[0]
self.assertEqual(downloaded['format_id'], 'good')
ydl = YDL({'format_limit': 'great', 'format': 'all'})
ydl.process_ie_result(info_dict.copy())
self.assertEqual(ydl.downloaded_info_dicts[0]['format_id'], 'meh')
self.assertEqual(ydl.downloaded_info_dicts[1]['format_id'], 'good')
self.assertEqual(ydl.downloaded_info_dicts[2]['format_id'], 'great')
self.assertTrue('3' in ydl.msgs[0])
ydl = YDL()
ydl.params['format_limit'] = 'excellent'
ydl.process_ie_result(info_dict.copy())
downloaded = ydl.downloaded_info_dicts[0]
self.assertEqual(downloaded['format_id'], 'excellent')
def test_format_selection(self):
formats = [
{'format_id': '35', 'ext': 'mp4', 'preference': 1, 'url': TEST_URL},
@@ -270,7 +238,7 @@ class TestFormatSelection(unittest.TestCase):
f2['url'] = 'url:' + f2id
info_dict = _make_result([f1, f2], extractor='youtube')
ydl = YDL()
ydl = YDL({'format': 'best/bestvideo'})
yie = YoutubeIE(ydl)
yie._sort_formats(info_dict['formats'])
ydl.process_ie_result(info_dict)
@@ -278,7 +246,7 @@ class TestFormatSelection(unittest.TestCase):
self.assertEqual(downloaded['format_id'], f1id)
info_dict = _make_result([f2, f1], extractor='youtube')
ydl = YDL()
ydl = YDL({'format': 'best/bestvideo'})
yie = YoutubeIE(ydl)
yie._sort_formats(info_dict['formats'])
ydl.process_ie_result(info_dict)
@@ -540,6 +508,51 @@ class TestYoutubeDL(unittest.TestCase):
res = get_videos(f)
self.assertEqual(res, ['1'])
def test_playlist_items_selection(self):
entries = [{
'id': compat_str(i),
'title': compat_str(i),
'url': TEST_URL,
} for i in range(1, 5)]
playlist = {
'_type': 'playlist',
'id': 'test',
'entries': entries,
'extractor': 'test:playlist',
'extractor_key': 'test:playlist',
'webpage_url': 'http://example.com',
}
def get_ids(params):
ydl = YDL(params)
# make a copy because the dictionary can be modified
ydl.process_ie_result(playlist.copy())
return [int(v['id']) for v in ydl.downloaded_info_dicts]
result = get_ids({})
self.assertEqual(result, [1, 2, 3, 4])
result = get_ids({'playlistend': 10})
self.assertEqual(result, [1, 2, 3, 4])
result = get_ids({'playlistend': 2})
self.assertEqual(result, [1, 2])
result = get_ids({'playliststart': 10})
self.assertEqual(result, [])
result = get_ids({'playliststart': 2})
self.assertEqual(result, [2, 3, 4])
result = get_ids({'playlist_items': '2-4'})
self.assertEqual(result, [2, 3, 4])
result = get_ids({'playlist_items': '2,4'})
self.assertEqual(result, [2, 4])
result = get_ids({'playlist_items': '10'})
self.assertEqual(result, [])
if __name__ == '__main__':
unittest.main()

View File

@@ -39,7 +39,7 @@ class TestAES(unittest.TestCase):
encrypted = base64.b64encode(
intlist_to_bytes(self.iv[:8]) +
b'\x17\x15\x93\xab\x8d\x80V\xcdV\xe0\t\xcdo\xc2\xa5\xd8ksM\r\xe27N\xae'
)
).decode('utf-8')
decrypted = (aes_decrypt_text(encrypted, password, 16))
self.assertEqual(decrypted, self.secret_msg)
@@ -47,7 +47,7 @@ class TestAES(unittest.TestCase):
encrypted = base64.b64encode(
intlist_to_bytes(self.iv[:8]) +
b'\x0b\xe6\xa4\xd9z\x0e\xb8\xb9\xd0\xd4i_\x85\x1d\x99\x98_\xe5\x80\xe7.\xbf\xa5\x83'
)
).decode('utf-8')
decrypted = (aes_decrypt_text(encrypted, password, 32))
self.assertEqual(decrypted, self.secret_msg)

View File

@@ -266,7 +266,7 @@ class TestNRKSubtitles(BaseTestSubtitles):
self.DL.params['allsubtitles'] = True
subtitles = self.getSubtitles()
self.assertEqual(set(subtitles.keys()), set(['no']))
self.assertEqual(md5(subtitles['no']), '1d221e6458c95c5494dcd38e6a1f129a')
self.assertEqual(md5(subtitles['no']), '544fa917d3197fcbee64634559221cc2')
class TestRaiSubtitles(BaseTestSubtitles):

View File

@@ -40,7 +40,8 @@ from youtube_dl.utils import (
read_batch_urls,
sanitize_filename,
sanitize_path,
sanitize_url_path_consecutive_slashes,
prepend_extension,
replace_extension,
shell_quote,
smuggle_url,
str_to_int,
@@ -51,6 +52,7 @@ from youtube_dl.utils import (
unified_strdate,
unsmuggle_url,
uppercase_escape,
lowercase_escape,
url_basename,
urlencode_postdata,
version_tuple,
@@ -173,25 +175,21 @@ class TestUtil(unittest.TestCase):
self.assertEqual(sanitize_path('./abc'), 'abc')
self.assertEqual(sanitize_path('./../abc'), '..\\abc')
def test_sanitize_url_path_consecutive_slashes(self):
self.assertEqual(
sanitize_url_path_consecutive_slashes('http://hostname/foo//bar/filename.html'),
'http://hostname/foo/bar/filename.html')
self.assertEqual(
sanitize_url_path_consecutive_slashes('http://hostname//foo/bar/filename.html'),
'http://hostname/foo/bar/filename.html')
self.assertEqual(
sanitize_url_path_consecutive_slashes('http://hostname//'),
'http://hostname/')
self.assertEqual(
sanitize_url_path_consecutive_slashes('http://hostname/foo/bar/filename.html'),
'http://hostname/foo/bar/filename.html')
self.assertEqual(
sanitize_url_path_consecutive_slashes('http://hostname/'),
'http://hostname/')
self.assertEqual(
sanitize_url_path_consecutive_slashes('http://hostname/abc//'),
'http://hostname/abc/')
def test_prepend_extension(self):
self.assertEqual(prepend_extension('abc.ext', 'temp'), 'abc.temp.ext')
self.assertEqual(prepend_extension('abc.ext', 'temp', 'ext'), 'abc.temp.ext')
self.assertEqual(prepend_extension('abc.unexpected_ext', 'temp', 'ext'), 'abc.unexpected_ext.temp')
self.assertEqual(prepend_extension('abc', 'temp'), 'abc.temp')
self.assertEqual(prepend_extension('.abc', 'temp'), '.abc.temp')
self.assertEqual(prepend_extension('.abc.ext', 'temp'), '.abc.temp.ext')
def test_replace_extension(self):
self.assertEqual(replace_extension('abc.ext', 'temp'), 'abc.temp')
self.assertEqual(replace_extension('abc.ext', 'temp', 'ext'), 'abc.temp')
self.assertEqual(replace_extension('abc.unexpected_ext', 'temp', 'ext'), 'abc.unexpected_ext.temp')
self.assertEqual(replace_extension('abc', 'temp'), 'abc.temp')
self.assertEqual(replace_extension('.abc', 'temp'), '.abc.temp')
self.assertEqual(replace_extension('.abc.ext', 'temp'), '.abc.temp')
def test_ordered_set(self):
self.assertEqual(orderedSet([1, 1, 2, 3, 4, 4, 5, 6, 7, 3, 5]), [1, 2, 3, 4, 5, 6, 7])
@@ -400,6 +398,10 @@ class TestUtil(unittest.TestCase):
self.assertEqual(uppercase_escape(''), '')
self.assertEqual(uppercase_escape('\\U0001d550'), '𝕐')
def test_lowercase_escape(self):
self.assertEqual(lowercase_escape(''), '')
self.assertEqual(lowercase_escape('\\u0026'), '&')
def test_limit_length(self):
self.assertEqual(limit_length(None, 12), None)
self.assertEqual(limit_length('foo', 12), 'foo')
@@ -598,7 +600,7 @@ ffmpeg version 2.4.4 Copyright (c) 2000-2014 the FFmpeg ...'''), '2.4.4')
<div xml:lang="en">
<p begin="0" end="1">The following line contains Chinese characters and special symbols</p>
<p begin="1" end="2">第二行<br/>♪♪</p>
<p begin="2" end="3"><span>Third<br/>Line</span></p>
<p begin="2" dur="1"><span>Third<br/>Line</span></p>
</div>
</body>
</tt>'''
@@ -619,6 +621,21 @@ Line
'''
self.assertEqual(dfxp2srt(dfxp_data), srt_data)
dfxp_data_no_default_namespace = '''<?xml version="1.0" encoding="UTF-8"?>
<tt xml:lang="en" xmlns:tts="http://www.w3.org/ns/ttml#parameter">
<body>
<div xml:lang="en">
<p begin="0" end="1">The first line</p>
</div>
</body>
</tt>'''
srt_data = '''1
00:00:00,000 --> 00:00:01,000
The first line
'''
self.assertEqual(dfxp2srt(dfxp_data_no_default_namespace), srt_data)
if __name__ == '__main__':
unittest.main()

View File

@@ -4,6 +4,8 @@ envlist = py26,py27,py33,py34
deps =
nose
coverage
# We need a valid $HOME for test_compat_expanduser
passenv = HOME
defaultargs = test --exclude test_download.py --exclude test_age_restriction.py
--exclude test_subtitles.py --exclude test_write_annotations.py
--exclude test_youtube_lists.py

View File

@@ -49,6 +49,7 @@ from .utils import (
ExtractorError,
format_bytes,
formatSeconds,
HEADRequest,
locked_file,
make_HTTPS_handler,
MaxDownloadsReached,
@@ -64,7 +65,6 @@ from .utils import (
sanitize_path,
std_headers,
subtitles_filename,
takewhile_inclusive,
UnavailableVideoError,
url_basename,
version_tuple,
@@ -72,6 +72,7 @@ from .utils import (
write_string,
YoutubeDLHandler,
prepend_extension,
replace_extension,
args_to_str,
age_restricted,
)
@@ -118,7 +119,7 @@ class YoutubeDL(object):
username: Username for authentication purposes.
password: Password for authentication purposes.
videopassword: Password for acces a video.
videopassword: Password for accessing a video.
usenetrc: Use netrc for authentication instead.
verbose: Print additional info to stdout.
quiet: Do not print messages to stdout.
@@ -135,10 +136,10 @@ class YoutubeDL(object):
(or video) as a single JSON line.
simulate: Do not download the video files.
format: Video format code. See options.py for more information.
format_limit: Highest quality format to try.
outtmpl: Template for output names.
restrictfilenames: Do not allow "&" and spaces in file names
ignoreerrors: Do not stop on download errors.
force_generic_extractor: Force downloader to use the generic extractor
nooverwrites: Prevent overwriting files.
playliststart: Playlist item to start at.
playlistend: Playlist item to end at.
@@ -261,7 +262,6 @@ class YoutubeDL(object):
The following options are used by the post processors:
prefer_ffmpeg: If True, use ffmpeg instead of avconv if both are available,
otherwise prefer avconv.
exec_cmd: Arbitrary command to run after downloading
"""
params = None
@@ -627,13 +627,16 @@ class YoutubeDL(object):
info_dict.setdefault(key, value)
def extract_info(self, url, download=True, ie_key=None, extra_info={},
process=True):
process=True, force_generic_extractor=False):
'''
Returns a list with a dictionary for each video we find.
If 'download', also downloads the videos.
extra_info is a dict containing the extra values to add to each result
'''
if not ie_key and force_generic_extractor:
ie_key = 'Generic'
if ie_key:
ies = [self.get_info_extractor(ie_key)]
else:
@@ -761,7 +764,9 @@ class YoutubeDL(object):
if isinstance(ie_entries, list):
n_all_entries = len(ie_entries)
if playlistitems:
entries = [ie_entries[i - 1] for i in playlistitems]
entries = [
ie_entries[i - 1] for i in playlistitems
if -n_all_entries <= i - 1 < n_all_entries]
else:
entries = ie_entries[playliststart:playlistend]
n_entries = len(entries)
@@ -916,15 +921,17 @@ class YoutubeDL(object):
if not available_formats:
return None
if format_spec == 'best' or format_spec is None:
return available_formats[-1]
elif format_spec == 'worst':
if format_spec in ['best', 'worst', None]:
format_idx = 0 if format_spec == 'worst' else -1
audiovideo_formats = [
f for f in available_formats
if f.get('vcodec') != 'none' and f.get('acodec') != 'none']
if audiovideo_formats:
return audiovideo_formats[0]
return available_formats[0]
return audiovideo_formats[format_idx]
# for audio only (soundcloud) or video only (imgur) urls, select the best/worst audio format
elif (all(f.get('acodec') != 'none' for f in available_formats) or
all(f.get('vcodec') != 'none' for f in available_formats)):
return available_formats[format_idx]
elif format_spec == 'bestaudio':
audio_formats = [
f for f in available_formats
@@ -1001,7 +1008,7 @@ class YoutubeDL(object):
t.get('preference'), t.get('width'), t.get('height'),
t.get('id'), t.get('url')))
for i, t in enumerate(thumbnails):
if 'width' in t and 'height' in t:
if t.get('width') and t.get('height'):
t['resolution'] = '%dx%d' % (t['width'], t['height'])
if t.get('id') is None:
t['id'] = '%d' % i
@@ -1013,13 +1020,13 @@ class YoutubeDL(object):
info_dict['display_id'] = info_dict['id']
if info_dict.get('upload_date') is None and info_dict.get('timestamp') is not None:
# Working around negative timestamps in Windows
# (see http://bugs.python.org/issue1646728)
if info_dict['timestamp'] < 0 and os.name == 'nt':
info_dict['timestamp'] = 0
upload_date = datetime.datetime.utcfromtimestamp(
info_dict['timestamp'])
info_dict['upload_date'] = upload_date.strftime('%Y%m%d')
# Working around out-of-range timestamp values (e.g. negative ones on Windows,
# see http://bugs.python.org/issue1646728)
try:
upload_date = datetime.datetime.utcfromtimestamp(info_dict['timestamp'])
info_dict['upload_date'] = upload_date.strftime('%Y%m%d')
except (ValueError, OverflowError, OSError):
pass
if self.params.get('listsubtitles', False):
if 'automatic_captions' in info_dict:
@@ -1030,12 +1037,6 @@ class YoutubeDL(object):
info_dict['id'], info_dict.get('subtitles'),
info_dict.get('automatic_captions'))
# This extractors handle format selection themselves
if info_dict['extractor'] in ['Youku']:
if download:
self.process_info(info_dict)
return info_dict
# We now pick which formats have to be downloaded
if info_dict.get('formats') is None:
# There's only one format available
@@ -1046,6 +1047,8 @@ class YoutubeDL(object):
if not formats:
raise ExtractorError('No video formats found!')
formats_dict = {}
# We check that all the formats have the format and format_id fields
for i, format in enumerate(formats):
if 'url' not in format:
@@ -1053,6 +1056,18 @@ class YoutubeDL(object):
if format.get('format_id') is None:
format['format_id'] = compat_str(i)
format_id = format['format_id']
if format_id not in formats_dict:
formats_dict[format_id] = []
formats_dict[format_id].append(format)
# Make sure all formats have unique format_id
for format_id, ambiguous_formats in formats_dict.items():
if len(ambiguous_formats) > 1:
for i, format in enumerate(ambiguous_formats):
format['format_id'] = '%s-%d' % (format_id, i)
for i, format in enumerate(formats):
if format.get('format') is None:
format['format'] = '{id} - {res}{note}'.format(
id=format['format_id'],
@@ -1068,12 +1083,6 @@ class YoutubeDL(object):
full_format_info.update(format)
format['http_headers'] = self._calc_headers(full_format_info)
format_limit = self.params.get('format_limit', None)
if format_limit:
formats = list(takewhile_inclusive(
lambda f: f['format_id'] != format_limit, formats
))
# TODO Central sorting goes here
if formats[0] is not info_dict:
@@ -1092,8 +1101,11 @@ class YoutubeDL(object):
req_format = self.params.get('format')
if req_format is None:
req_format_list = []
if info_dict['extractor'] in ['youtube', 'ted'] and FFmpegMergerPP(self).available:
req_format_list.append('bestvideo+bestaudio')
if (self.params.get('outtmpl', DEFAULT_OUTTMPL) != '-' and
info_dict['extractor'] in ['youtube', 'ted']):
merger = FFmpegMergerPP(self)
if merger.available and merger.can_merge():
req_format_list.append('bestvideo+bestaudio')
req_format_list.append('best')
req_format = '/'.join(req_format_list)
formats_to_download = []
@@ -1277,7 +1289,7 @@ class YoutubeDL(object):
return
if self.params.get('writedescription', False):
descfn = filename + '.description'
descfn = replace_extension(filename, 'description', info_dict.get('ext'))
if self.params.get('nooverwrites', False) and os.path.exists(encodeFilename(descfn)):
self.to_screen('[info] Video description is already present')
elif info_dict.get('description') is None:
@@ -1292,7 +1304,7 @@ class YoutubeDL(object):
return
if self.params.get('writeannotations', False):
annofn = filename + '.annotations.xml'
annofn = replace_extension(filename, 'annotations.xml', info_dict.get('ext'))
if self.params.get('nooverwrites', False) and os.path.exists(encodeFilename(annofn)):
self.to_screen('[info] Video annotations are already present')
else:
@@ -1339,13 +1351,13 @@ class YoutubeDL(object):
return
if self.params.get('writeinfojson', False):
infofn = os.path.splitext(filename)[0] + '.info.json'
infofn = replace_extension(filename, 'info.json', info_dict.get('ext'))
if self.params.get('nooverwrites', False) and os.path.exists(encodeFilename(infofn)):
self.to_screen('[info] Video description metadata is already present')
else:
self.to_screen('[info] Writing video description metadata as JSON to: ' + infofn)
try:
write_json_file(info_dict, infofn)
write_json_file(self.filter_requested_info(info_dict), infofn)
except (OSError, IOError):
self.report_error('Cannot write metadata to JSON file ' + infofn)
return
@@ -1370,7 +1382,7 @@ class YoutubeDL(object):
postprocessors = []
self.report_warning('You have requested multiple '
'formats but ffmpeg or avconv are not installed.'
' The formats won\'t be merged')
' The formats won\'t be merged.')
else:
postprocessors = [merger]
@@ -1389,11 +1401,18 @@ class YoutubeDL(object):
# TODO: Check acodec/vcodec
return False
filename_real_ext = os.path.splitext(filename)[1][1:]
filename_wo_ext = (
os.path.splitext(filename)[0]
if filename_real_ext == info_dict['ext']
else filename)
requested_formats = info_dict['requested_formats']
if self.params.get('merge_output_format') is None and not compatible_formats(requested_formats):
filename = os.path.splitext(filename)[0] + '.mkv'
self.report_warning('You have requested formats uncompatible for merge. '
'The formats will be merged into mkv')
info_dict['ext'] = 'mkv'
self.report_warning(
'Requested formats are incompatible for merge and will be merged into mkv.')
# Ensure filename always has a correct extension for successful merge
filename = '%s.%s' % (filename_wo_ext, info_dict['ext'])
if os.path.exists(encodeFilename(filename)):
self.to_screen(
'[download] %s has already been downloaded and '
@@ -1403,7 +1422,7 @@ class YoutubeDL(object):
new_info = dict(info_dict)
new_info.update(f)
fname = self.prepare_filename(new_info)
fname = prepend_extension(fname, 'f%s' % f['format_id'])
fname = prepend_extension(fname, 'f%s' % f['format_id'], new_info['ext'])
downloaded.append(fname)
partial_success = dl(fname, new_info)
success = success and partial_success
@@ -1478,7 +1497,8 @@ class YoutubeDL(object):
for url in url_list:
try:
# It also downloads the videos
res = self.extract_info(url)
res = self.extract_info(
url, force_generic_extractor=self.params.get('force_generic_extractor', False))
except UnavailableVideoError:
self.report_error('unable to download video')
except MaxDownloadsReached:
@@ -1495,7 +1515,7 @@ class YoutubeDL(object):
[info_filename], mode='r',
openhook=fileinput.hook_encoded('utf-8'))) as f:
# FileInput doesn't have a read method, we can't call json.load
info = json.loads('\n'.join(f))
info = self.filter_requested_info(json.loads('\n'.join(f)))
try:
self.process_ie_result(info, download=True)
except DownloadError:
@@ -1507,6 +1527,12 @@ class YoutubeDL(object):
raise
return self._download_retcode
@staticmethod
def filter_requested_info(info_dict):
return dict(
(k, v) for k, v in info_dict.items()
if k not in ['requested_formats', 'requested_subtitles'])
def post_process(self, filename, ie_info):
"""Run all the postprocessors on the given file."""
info = dict(ie_info)
@@ -1516,6 +1542,7 @@ class YoutubeDL(object):
pps_chain.extend(ie_info['__postprocessors'])
pps_chain.extend(self._pps)
for pp in pps_chain:
files_to_delete = []
try:
files_to_delete, info = pp.run(info)
except PostProcessingError as e:
@@ -1694,7 +1721,8 @@ class YoutubeDL(object):
if req_is_string:
req = url_escaped
else:
req = compat_urllib_request.Request(
req_type = HEADRequest if req.get_method() == 'HEAD' else compat_urllib_request.Request
req = req_type(
url_escaped, data=req.data, headers=req.headers,
origin_req_host=req.origin_req_host, unverifiable=req.unverifiable)
@@ -1840,7 +1868,7 @@ class YoutubeDL(object):
thumb_ext = determine_ext(t['url'], 'jpg')
suffix = '_%s' % t['id'] if len(thumbnails) > 1 else ''
thumb_display_id = '%s ' % t['id'] if len(thumbnails) > 1 else ''
thumb_filename = os.path.splitext(filename)[0] + suffix + '.' + thumb_ext
t['filename'] = thumb_filename = os.path.splitext(filename)[0] + suffix + '.' + thumb_ext
if self.params.get('nooverwrites', False) and os.path.exists(encodeFilename(thumb_filename)):
self.to_screen('[%s] %s: Thumbnail %sis already present' %

View File

@@ -240,13 +240,18 @@ def _real_main(argv=None):
if opts.xattrs:
postprocessors.append({'key': 'XAttrMetadata'})
if opts.embedthumbnail:
postprocessors.append({'key': 'EmbedThumbnail'})
already_have_thumbnail = opts.writethumbnail or opts.write_all_thumbnails
postprocessors.append({
'key': 'EmbedThumbnail',
'already_have_thumbnail': already_have_thumbnail
})
if not already_have_thumbnail:
opts.writethumbnail = True
# Please keep ExecAfterDownload towards the bottom as it allows the user to modify the final file in any way.
# So if the user is able to remove the file before your postprocessor runs it might cause a few problems.
if opts.exec_cmd:
postprocessors.append({
'key': 'ExecAfterDownload',
'verboseOutput': opts.verbose,
'exec_cmd': opts.exec_cmd,
})
if opts.xattr_set_filesize:
@@ -283,12 +288,12 @@ def _real_main(argv=None):
'simulate': opts.simulate or any_getting,
'skip_download': opts.skip_download,
'format': opts.format,
'format_limit': opts.format_limit,
'listformats': opts.listformats,
'outtmpl': outtmpl,
'autonumber_size': opts.autonumber_size,
'restrictfilenames': opts.restrictfilenames,
'ignoreerrors': opts.ignoreerrors,
'force_generic_extractor': opts.force_generic_extractor,
'ratelimit': opts.ratelimit,
'nooverwrites': opts.nooverwrites,
'retries': opts_retries,
@@ -346,7 +351,6 @@ def _real_main(argv=None):
'default_search': opts.default_search,
'youtube_include_dash_manifest': opts.youtube_include_dash_manifest,
'encoding': opts.encoding,
'exec_cmd': opts.exec_cmd,
'extract_flat': opts.extract_flat,
'merge_output_format': opts.merge_output_format,
'postprocessors': postprocessors,

View File

@@ -152,7 +152,7 @@ def aes_decrypt_text(data, password, key_size_bytes):
"""
NONCE_LENGTH_BYTES = 8
data = bytes_to_intlist(base64.b64decode(data))
data = bytes_to_intlist(base64.b64decode(data.encode('utf-8')))
password = bytes_to_intlist(password.encode('utf-8'))
key = password[:key_size_bytes] + [0] * (key_size_bytes - len(password))

View File

@@ -46,11 +46,6 @@ try:
except ImportError: # Python 2
import htmlentitydefs as compat_html_entities
try:
import html.parser as compat_html_parser
except ImportError: # Python 2
import HTMLParser as compat_html_parser
try:
import http.client as compat_http_client
except ImportError: # Python 2
@@ -404,7 +399,6 @@ __all__ = [
'compat_getenv',
'compat_getpass',
'compat_html_entities',
'compat_html_parser',
'compat_http_client',
'compat_http_server',
'compat_kwargs',

View File

@@ -109,6 +109,14 @@ class Aria2cFD(ExternalFD):
cmd += ['--', info_dict['url']]
return cmd
class HttpieFD(ExternalFD):
def _make_cmd(self, tmpfilename, info_dict):
cmd = ['http', '--download', '--output', tmpfilename, info_dict['url']]
for key, val in info_dict['http_headers'].items():
cmd += ['%s:%s' % (key, val)]
return cmd
_BY_NAME = dict(
(klass.get_basename(), klass)
for name, klass in globals().items()
@@ -123,5 +131,6 @@ def list_external_downloaders():
def get_external_downloader(external_downloader):
""" Given the name of the executable, see whether we support the given
downloader . """
bn = os.path.basename(external_downloader)
# Drop .exe extension on Windows
bn = os.path.splitext(os.path.basename(external_downloader))[0]
return _BY_NAME[bn]

View File

@@ -28,13 +28,8 @@ class HttpFD(FileDownloader):
add_headers = info_dict.get('http_headers')
if add_headers:
headers.update(add_headers)
data = info_dict.get('http_post_data')
http_method = info_dict.get('http_method')
basic_request = compat_urllib_request.Request(url, data, headers)
request = compat_urllib_request.Request(url, data, headers)
if http_method is not None:
basic_request.get_method = lambda: http_method
request.get_method = lambda: http_method
basic_request = compat_urllib_request.Request(url, None, headers)
request = compat_urllib_request.Request(url, None, headers)
is_test = self.params.get('test', False)

View File

@@ -131,7 +131,7 @@ class RtmpFD(FileDownloader):
if play_path is not None:
basic_args += ['--playpath', play_path]
if tc_url is not None:
basic_args += ['--tcUrl', url]
basic_args += ['--tcUrl', tc_url]
if test:
basic_args += ['--stop', '1']
if flash_version is not None:

View File

@@ -4,7 +4,10 @@ from .abc import ABCIE
from .abc7news import Abc7NewsIE
from .academicearth import AcademicEarthCourseIE
from .addanime import AddAnimeIE
from .adobetv import AdobeTVIE
from .adobetv import (
AdobeTVIE,
AdobeTVVideoIE,
)
from .adultswim import AdultSwimIE
from .aftenposten import AftenpostenIE
from .aftonbladet import AftonbladetIE
@@ -32,6 +35,7 @@ from .atresplayer import AtresPlayerIE
from .atttechchannel import ATTTechChannelIE
from .audiomack import AudiomackIE, AudiomackAlbumIE
from .azubu import AzubuIE
from .baidu import BaiduVideoIE
from .bambuser import BambuserIE, BambuserChannelIE
from .bandcamp import BandcampIE, BandcampAlbumIE
from .bbccouk import BBCCoUkIE
@@ -102,6 +106,7 @@ from .dailymotion import (
DailymotionIE,
DailymotionPlaylistIE,
DailymotionUserIE,
DailymotionCloudIE,
)
from .daum import DaumIE
from .dbtv import DBTVIE
@@ -111,6 +116,10 @@ from .dfb import DFBIE
from .dhm import DHMIE
from .dotsub import DotsubIE
from .douyutv import DouyuTVIE
from .dramafever import (
DramaFeverIE,
DramaFeverSeriesIE,
)
from .dreisat import DreiSatIE
from .drbonanza import DRBonanzaIE
from .drtuber import DrTuberIE
@@ -135,11 +144,11 @@ from .ellentv import (
)
from .elpais import ElPaisIE
from .embedly import EmbedlyIE
from .empflix import EMPFlixIE
from .engadget import EngadgetIE
from .eporner import EpornerIE
from .eroprofile import EroProfileIE
from .escapist import EscapistIE
from .espn import ESPNIE
from .everyonesmixtape import EveryonesMixtapeIE
from .exfm import ExfmIE
from .expotv import ExpoTVIE
@@ -147,10 +156,10 @@ from .extremetube import ExtremeTubeIE
from .facebook import FacebookIE
from .faz import FazIE
from .fc2 import FC2IE
from .firedrive import FiredriveIE
from .firstpost import FirstpostIE
from .firsttv import FirstTVIE
from .fivemin import FiveMinIE
from .fivetv import FiveTVIE
from .fktv import (
FKTVIE,
FKTVPosteckeIE,
@@ -161,6 +170,7 @@ from .footyroom import FootyRoomIE
from .fourtube import FourTubeIE
from .foxgay import FoxgayIE
from .foxnews import FoxNewsIE
from .foxsports import FoxSportsIE
from .franceculture import FranceCultureIE
from .franceinter import FranceInterIE
from .francetv import (
@@ -198,7 +208,6 @@ from .googleplus import GooglePlusIE
from .googlesearch import GoogleSearchIE
from .gorillavid import GorillaVidIE
from .goshgay import GoshgayIE
from .grooveshark import GroovesharkIE
from .groupon import GrouponIE
from .hark import HarkIE
from .hearthisat import HearThisAtIE
@@ -228,6 +237,7 @@ from .infoq import InfoQIE
from .instagram import InstagramIE, InstagramUserIE
from .internetvideoarchive import InternetVideoArchiveIE
from .iprima import IPrimaIE
from .iqiyi import IqiyiIE
from .ivi import (
IviIE,
IviCompilationIE
@@ -242,6 +252,7 @@ from .kaltura import KalturaIE
from .kanalplay import KanalPlayIE
from .kankan import KankanIE
from .karaoketv import KaraoketvIE
from .karrierevideos import KarriereVideosIE
from .keezmovies import KeezMoviesIE
from .khanacademy import KhanAcademyIE
from .kickstarter import KickStarterIE
@@ -257,7 +268,10 @@ from .letv import (
LetvPlaylistIE
)
from .libsyn import LibsynIE
from .lifenews import LifeNewsIE
from .lifenews import (
LifeNewsIE,
LifeEmbedIE,
)
from .liveleak import LiveLeakIE
from .livestream import (
LivestreamIE,
@@ -320,7 +334,10 @@ from .nbc import (
NBCSportsIE,
NBCSportsVPlayerIE,
)
from .ndr import NDRIE
from .ndr import (
NDRIE,
NJoyIE,
)
from .ndtv import NDTVIE
from .netzkino import NetzkinoIE
from .nerdcubed import NerdCubedFeedIE
@@ -330,8 +347,7 @@ from .newstube import NewstubeIE
from .nextmedia import (
NextMediaIE,
NextMediaActionNewsIE,
AppleDailyRealtimeNewsIE,
AppleDailyAnimationNewsIE
AppleDailyIE,
)
from .nfb import NFBIE
from .nfl import NFLIE
@@ -345,8 +361,10 @@ from .ninegag import NineGagIE
from .noco import NocoIE
from .normalboots import NormalbootsIE
from .nosvideo import NosVideoIE
from .nova import NovaIE
from .novamov import NovaMovIE
from .nowness import NownessIE
from .nowtv import NowTVIE
from .nowvideo import NowVideoIE
from .npo import (
NPOIE,
@@ -362,11 +380,18 @@ from .nrk import (
)
from .ntvde import NTVDeIE
from .ntvru import NTVRuIE
from .nytimes import NYTimesIE
from .nytimes import (
NYTimesIE,
NYTimesArticleIE,
)
from .nuvid import NuvidIE
from .odnoklassniki import OdnoklassnikiIE
from .oktoberfesttv import OktoberfestTVIE
from .ooyala import OoyalaIE
from .onionstudios import OnionStudiosIE
from .ooyala import (
OoyalaIE,
OoyalaExternalIE,
)
from .openfilm import OpenFilmIE
from .orf import (
ORFTVthekIE,
@@ -377,8 +402,10 @@ from .orf import (
from .parliamentliveuk import ParliamentLiveUKIE
from .patreon import PatreonIE
from .pbs import PBSIE
from .philharmoniedeparis import PhilharmonieDeParisIE
from .phoenix import PhoenixIE
from .photobucket import PhotobucketIE
from .pinkbike import PinkbikeIE
from .planetaplay import PlanetaPlayIE
from .pladform import PladformIE
from .played import PlayedIE
@@ -386,6 +413,7 @@ from .playfm import PlayFMIE
from .playvid import PlayvidIE
from .playwire import PlaywireIE
from .podomatic import PodomaticIE
from .porn91 import Porn91IE
from .pornhd import PornHdIE
from .pornhub import (
PornHubIE,
@@ -403,6 +431,8 @@ from .qqmusic import (
QQMusicIE,
QQMusicSingerIE,
QQMusicAlbumIE,
QQMusicToplistIE,
QQMusicPlaylistIE,
)
from .quickvid import QuickVidIE
from .r7 import R7IE
@@ -422,7 +452,6 @@ from .roxwel import RoxwelIE
from .rtbf import RTBFIE
from .rte import RteIE
from .rtlnl import RtlNlIE
from .rtlnow import RTLnowIE
from .rtl2 import RTL2IE
from .rtp import RTPIE
from .rts import RTSIE
@@ -436,6 +465,7 @@ from .rutube import (
RutubePersonIE,
)
from .rutv import RUTVIE
from .ruutu import RuutuIE
from .sandia import SandiaIE
from .safari import (
SafariIE,
@@ -463,9 +493,16 @@ from .smotri import (
SmotriUserIE,
SmotriBroadcastIE,
)
from .snagfilms import (
SnagFilmsIE,
SnagFilmsEmbedIE,
)
from .snotr import SnotrIE
from .sockshare import SockshareIE
from .sohu import SohuIE
from .soompi import (
SoompiIE,
SoompiShowIE,
)
from .soundcloud import (
SoundcloudIE,
SoundcloudSetIE,
@@ -478,8 +515,10 @@ from .soundgasm import (
)
from .southpark import (
SouthParkIE,
SouthParkDeIE,
SouthParkDkIE,
SouthParkEsIE,
SouthparkDeIE,
SouthParkNlIE
)
from .space import SpaceIE
from .spankbang import SpankBangIE
@@ -488,7 +527,10 @@ from .spiegel import SpiegelIE, SpiegelArticleIE
from .spiegeltv import SpiegeltvIE
from .spike import SpikeIE
from .sport5 import Sport5IE
from .sportbox import SportBoxIE
from .sportbox import (
SportBoxIE,
SportBoxEmbedIE,
)
from .sportdeutschland import SportDeutschlandIE
from .srf import SrfIE
from .srmediathek import SRMediathekIE
@@ -499,7 +541,10 @@ from .streamcloud import StreamcloudIE
from .streamcz import StreamCZIE
from .streetvoice import StreetVoiceIE
from .sunporno import SunPornoIE
from .svtplay import SVTPlayIE
from .svt import (
SVTIE,
SVTPlayIE,
)
from .swrmediathek import SWRMediathekIE
from .syfy import SyfyIE
from .sztvhu import SztvHuIE
@@ -525,11 +570,19 @@ from .tf1 import TF1IE
from .theonion import TheOnionIE
from .theplatform import ThePlatformIE
from .thesixtyone import TheSixtyOneIE
from .thisamericanlife import ThisAmericanLifeIE
from .thisav import ThisAVIE
from .tinypic import TinyPicIE
from .tlc import TlcIE, TlcDeIE
from .tmz import TMZIE
from .tnaflix import TNAFlixIE
from .tmz import (
TMZIE,
TMZArticleIE,
)
from .tnaflix import (
TNAFlixIE,
EMPFlixIE,
MovieFapIE,
)
from .thvideo import (
THVideoIE,
THVideoPlaylistIE
@@ -540,12 +593,21 @@ from .traileraddict import TrailerAddictIE
from .trilulilu import TriluliluIE
from .trutube import TruTubeIE
from .tube8 import Tube8IE
from .tubitv import TubiTvIE
from .tudou import TudouIE
from .tumblr import TumblrIE
from .tunein import TuneInIE
from .turbo import TurboIE
from .tutv import TutvIE
from .tv2 import (
TV2IE,
TV2ArticleIE,
)
from .tv4 import TV4IE
from .tvc import (
TVCIE,
TVCArticleIE,
)
from .tvigle import TvigleIE
from .tvp import TvpIE, TvpSeriesIE
from .tvplay import TVPlayIE
@@ -564,6 +626,7 @@ from .twitch import (
TwitchBookmarksIE,
TwitchStreamIE,
)
from .twitter import TwitterCardIE
from .ubu import UbuIE
from .udemy import (
UdemyIE,
@@ -581,7 +644,11 @@ from .veoh import VeohIE
from .vessel import VesselIE
from .vesti import VestiIE
from .vevo import VevoIE
from .vgtv import VGTVIE
from .vgtv import (
BTArticleIE,
BTVestlendingenIE,
VGTVIE,
)
from .vh1 import VH1IE
from .vice import ViceIE
from .viddler import ViddlerIE
@@ -612,12 +679,16 @@ from .vine import (
VineIE,
VineUserIE,
)
from .viki import VikiIE
from .viki import (
VikiIE,
VikiChannelIE,
)
from .vk import (
VKIE,
VKUserVideosIE,
)
from .vodlocker import VodlockerIE
from .voicerepublic import VoiceRepublicIE
from .vporn import VpornIE
from .vrt import VRTIE
from .vube import VubeIE
@@ -641,12 +712,16 @@ from .wrzuta import WrzutaIE
from .wsj import WSJIE
from .xbef import XBefIE
from .xboxclips import XboxClipsIE
from .xhamster import XHamsterIE
from .xhamster import (
XHamsterIE,
XHamsterEmbedIE,
)
from .xminus import XMinusIE
from .xnxx import XNXXIE
from .xvideos import XVideosIE
from .xstream import XstreamIE
from .xtube import XTubeUserIE, XTubeIE
from .xuite import XuiteIE
from .xvideos import XVideosIE
from .xxxymovies import XXXYMoviesIE
from .yahoo import (
YahooIE,

View File

@@ -5,6 +5,8 @@ from ..utils import (
parse_duration,
unified_strdate,
str_to_int,
float_or_none,
ISO639Utils,
)
@@ -69,3 +71,61 @@ class AdobeTVIE(InfoExtractor):
'view_count': view_count,
'formats': formats,
}
class AdobeTVVideoIE(InfoExtractor):
_VALID_URL = r'https?://video\.tv\.adobe\.com/v/(?P<id>\d+)'
_TEST = {
# From https://helpx.adobe.com/acrobat/how-to/new-experience-acrobat-dc.html?set=acrobat--get-started--essential-beginners
'url': 'https://video.tv.adobe.com/v/2456/',
'md5': '43662b577c018ad707a63766462b1e87',
'info_dict': {
'id': '2456',
'ext': 'mp4',
'title': 'New experience with Acrobat DC',
'description': 'New experience with Acrobat DC',
'duration': 248.667,
},
}
def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
player_params = self._parse_json(self._search_regex(
r'var\s+bridge\s*=\s*([^;]+);', webpage, 'player parameters'),
video_id)
formats = [{
'url': source['src'],
'width': source.get('width'),
'height': source.get('height'),
'tbr': source.get('bitrate'),
} for source in player_params['sources']]
# For both metadata and downloaded files the duration varies among
# formats. I just pick the max one
duration = max(filter(None, [
float_or_none(source.get('duration'), scale=1000)
for source in player_params['sources']]))
subtitles = {}
for translation in player_params.get('translations', []):
lang_id = translation.get('language_w3c') or ISO639Utils.long2short(translation['language_medium'])
if lang_id not in subtitles:
subtitles[lang_id] = []
subtitles[lang_id].append({
'url': translation['vttPath'],
'ext': 'vtt',
})
return {
'id': video_id,
'formats': formats,
'title': player_params['title'],
'description': self._og_search_description(webpage),
'duration': duration,
'subtitles': subtitles,
}

View File

@@ -1,21 +1,11 @@
# coding: utf-8
from __future__ import unicode_literals
import re
from .common import InfoExtractor
from ..utils import (
int_or_none,
parse_iso8601,
xpath_with_ns,
xpath_text,
find_xpath_attr,
)
class AftenpostenIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?aftenposten\.no/webtv/(?:#!/)?video/(?P<id>\d+)'
_TEST = {
'url': 'http://www.aftenposten.no/webtv/#!/video/21039/trailer-sweatshop-i-can-t-take-any-more',
'md5': 'fd828cd29774a729bf4d4425fe192972',
@@ -30,69 +20,4 @@ class AftenpostenIE(InfoExtractor):
}
def _real_extract(self, url):
video_id = self._match_id(url)
data = self._download_xml(
'http://frontend.xstream.dk/ap/feed/video/?platform=web&id=%s' % video_id, video_id)
NS_MAP = {
'atom': 'http://www.w3.org/2005/Atom',
'xt': 'http://xstream.dk/',
'media': 'http://search.yahoo.com/mrss/',
}
entry = data.find(xpath_with_ns('./atom:entry', NS_MAP))
title = xpath_text(
entry, xpath_with_ns('./atom:title', NS_MAP), 'title')
description = xpath_text(
entry, xpath_with_ns('./atom:summary', NS_MAP), 'description')
timestamp = parse_iso8601(xpath_text(
entry, xpath_with_ns('./atom:published', NS_MAP), 'upload date'))
formats = []
media_group = entry.find(xpath_with_ns('./media:group', NS_MAP))
for media_content in media_group.findall(xpath_with_ns('./media:content', NS_MAP)):
media_url = media_content.get('url')
if not media_url:
continue
tbr = int_or_none(media_content.get('bitrate'))
mobj = re.search(r'^(?P<url>rtmp://[^/]+/(?P<app>[^/]+))/(?P<playpath>.+)$', media_url)
if mobj:
formats.append({
'url': mobj.group('url'),
'play_path': 'mp4:%s' % mobj.group('playpath'),
'app': mobj.group('app'),
'ext': 'flv',
'tbr': tbr,
'format_id': 'rtmp-%d' % tbr,
})
else:
formats.append({
'url': media_url,
'tbr': tbr,
})
self._sort_formats(formats)
link = find_xpath_attr(
entry, xpath_with_ns('./atom:link', NS_MAP), 'rel', 'original')
if link is not None:
formats.append({
'url': link.get('href'),
'format_id': link.get('rel'),
})
thumbnails = [{
'url': splash.get('url'),
'width': int_or_none(splash.get('width')),
'height': int_or_none(splash.get('height')),
} for splash in media_group.findall(xpath_with_ns('./xt:splash', NS_MAP))]
return {
'id': video_id,
'title': title,
'description': description,
'timestamp': timestamp,
'formats': formats,
'thumbnails': thumbnails,
}
return self.url_result('xstream:ap:%s' % self._match_id(url), 'Xstream')

View File

@@ -6,11 +6,11 @@ from ..utils import int_or_none
class AftonbladetIE(InfoExtractor):
_VALID_URL = r'http://tv\.aftonbladet\.se/webbtv.+?(?P<id>article[0-9]+)\.ab(?:$|[?#])'
_VALID_URL = r'http://tv\.aftonbladet\.se/abtv/articles/(?P<id>[0-9]+)'
_TEST = {
'url': 'http://tv.aftonbladet.se/webbtv/nyheter/vetenskap/rymden/article36015.ab',
'url': 'http://tv.aftonbladet.se/abtv/articles/36015',
'info_dict': {
'id': 'article36015',
'id': '36015',
'ext': 'mp4',
'title': 'Vulkanutbrott i rymden - nu släpper NASA bilderna',
'description': 'Jupiters måne mest aktiv av alla himlakroppar',
@@ -25,8 +25,9 @@ class AftonbladetIE(InfoExtractor):
# find internal video meta data
meta_url = 'http://aftonbladet-play.drlib.aptoma.no/video/%s.json'
internal_meta_id = self._html_search_regex(
r'data-aptomaId="([\w\d]+)"', webpage, 'internal_meta_id')
player_config = self._parse_json(self._html_search_regex(
r'data-player-config="([^"]+)"', webpage, 'player config'), video_id)
internal_meta_id = player_config['videoId']
internal_meta_url = meta_url % internal_meta_id
internal_meta_json = self._download_json(
internal_meta_url, video_id, 'Downloading video meta data')

View File

@@ -33,7 +33,7 @@ class ArchiveOrgIE(InfoExtractor):
def _real_extract(self, url):
video_id = self._match_id(url)
json_url = url + ('?' if '?' in url else '&') + 'output=json'
json_url = url + ('&' if '?' in url else '?') + 'output=json'
data = self._download_json(json_url, video_id)
def get_optional(data_dict, field):

View File

@@ -7,7 +7,6 @@ from .common import InfoExtractor
from ..utils import (
find_xpath_attr,
unified_strdate,
get_element_by_id,
get_element_by_attribute,
int_or_none,
qualities,
@@ -195,7 +194,9 @@ class ArteTVFutureIE(ArteTVPlus7IE):
def _real_extract(self, url):
anchor_id, lang = self._extract_url_info(url)
webpage = self._download_webpage(url, anchor_id)
row = get_element_by_id(anchor_id, webpage)
row = self._search_regex(
r'(?s)id="%s"[^>]*>.+?(<div[^>]*arte_vp_url[^>]*>)' % anchor_id,
webpage, 'row')
return self._extract_from_webpage(row, anchor_id, lang)

View File

@@ -0,0 +1,68 @@
# coding: utf-8
from __future__ import unicode_literals
import re
from .common import InfoExtractor
from ..compat import compat_urlparse
class BaiduVideoIE(InfoExtractor):
_VALID_URL = r'http://v\.baidu\.com/(?P<type>[a-z]+)/(?P<id>\d+)\.htm'
_TESTS = [{
'url': 'http://v.baidu.com/comic/1069.htm?frp=bdbrand&q=%E4%B8%AD%E5%8D%8E%E5%B0%8F%E5%BD%93%E5%AE%B6',
'info_dict': {
'id': '1069',
'title': '中华小当家 TV版 (全52集)',
'description': 'md5:395a419e41215e531c857bb037bbaf80',
},
'playlist_count': 52,
}, {
'url': 'http://v.baidu.com/show/11595.htm?frp=bdbrand',
'info_dict': {
'id': '11595',
'title': 're:^奔跑吧兄弟',
'description': 'md5:1bf88bad6d850930f542d51547c089b8',
},
'playlist_mincount': 3,
}]
def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)
playlist_id = mobj.group('id')
category = category2 = mobj.group('type')
if category == 'show':
category2 = 'tvshow'
webpage = self._download_webpage(url, playlist_id)
playlist_title = self._html_search_regex(
r'title\s*:\s*(["\'])(?P<title>[^\']+)\1', webpage,
'playlist title', group='title')
playlist_description = self._html_search_regex(
r'<input[^>]+class="j-data-intro"[^>]+value="([^"]+)"/>', webpage,
playlist_id, 'playlist description')
site = self._html_search_regex(
r'filterSite\s*:\s*["\']([^"]*)["\']', webpage,
'primary provider site')
api_result = self._download_json(
'http://v.baidu.com/%s_intro/?dtype=%sPlayUrl&id=%s&site=%s' % (
category, category2, playlist_id, site),
playlist_id, 'Get playlist links')
entries = []
for episode in api_result[0]['episodes']:
episode_id = '%s_%s' % (playlist_id, episode['episode'])
redirect_page = self._download_webpage(
compat_urlparse.urljoin(url, episode['url']), episode_id,
note='Download Baidu redirect page')
real_url = self._html_search_regex(
r'location\.replace\("([^"]+)"\)', redirect_page, 'real URL')
entries.append(self.url_result(
real_url, video_title=episode['single_title']))
return self.playlist_result(
entries, playlist_id, playlist_title, playlist_description)

View File

@@ -3,7 +3,10 @@ from __future__ import unicode_literals
import xml.etree.ElementTree
from .common import InfoExtractor
from ..utils import ExtractorError
from ..utils import (
ExtractorError,
int_or_none,
)
from ..compat import compat_HTTPError
@@ -112,6 +115,34 @@ class BBCCoUkIE(InfoExtractor):
# rtmp download
'skip_download': True,
}
}, {
'url': 'http://www.bbc.co.uk/iplayer/episode/b054fn09/ad/natural-world-20152016-2-super-powered-owls',
'info_dict': {
'id': 'p02n76xf',
'ext': 'flv',
'title': 'Natural World, 2015-2016: 2. Super Powered Owls',
'description': 'md5:e4db5c937d0e95a7c6b5e654d429183d',
'duration': 3540,
},
'params': {
# rtmp download
'skip_download': True,
},
'skip': 'geolocation',
}, {
'url': 'http://www.bbc.co.uk/iplayer/episode/b05zmgwn/royal-academy-summer-exhibition',
'info_dict': {
'id': 'b05zmgw1',
'ext': 'flv',
'description': 'Kirsty Wark and Morgan Quaintance visit the Royal Academy as it prepares for its annual artistic extravaganza, meeting people who have come together to make the show unique.',
'title': 'Royal Academy Summer Exhibition',
'duration': 3540,
},
'params': {
# rtmp download
'skip_download': True,
},
'skip': 'geolocation',
}, {
'url': 'http://www.bbc.co.uk/iplayer/playlist/p01dvks4',
'only_matching': True,
@@ -220,26 +251,11 @@ class BBCCoUkIE(InfoExtractor):
for connection in self._extract_connections(media):
captions = self._download_xml(connection.get('href'), programme_id, 'Downloading captions')
lang = captions.get('{http://www.w3.org/XML/1998/namespace}lang', 'en')
ps = captions.findall('./{0}body/{0}div/{0}p'.format('{http://www.w3.org/2006/10/ttaf1}'))
srt = ''
def _extract_text(p):
if p.text is not None:
stripped_text = p.text.strip()
if stripped_text:
return stripped_text
return ' '.join(span.text.strip() for span in p.findall('{http://www.w3.org/2006/10/ttaf1}span'))
for pos, p in enumerate(ps):
srt += '%s\r\n%s --> %s\r\n%s\r\n\r\n' % (str(pos), p.get('begin'), p.get('end'), _extract_text(p))
subtitles[lang] = [
{
'url': connection.get('href'),
'ext': 'ttml',
},
{
'data': srt,
'ext': 'srt',
},
]
return subtitles
@@ -250,7 +266,7 @@ class BBCCoUkIE(InfoExtractor):
programme_id, 'Downloading media selection XML')
except ExtractorError as ee:
if isinstance(ee.cause, compat_HTTPError) and ee.cause.code == 403:
media_selection = xml.etree.ElementTree.fromstring(ee.cause.read().encode('utf-8'))
media_selection = xml.etree.ElementTree.fromstring(ee.cause.read().decode('utf-8'))
else:
raise
@@ -326,16 +342,27 @@ class BBCCoUkIE(InfoExtractor):
webpage = self._download_webpage(url, group_id, 'Downloading video page')
programme_id = self._search_regex(
r'"vpid"\s*:\s*"([\da-z]{8})"', webpage, 'vpid', fatal=False, default=None)
programme_id = None
tviplayer = self._search_regex(
r'mediator\.bind\(({.+?})\s*,\s*document\.getElementById',
webpage, 'player', default=None)
if tviplayer:
player = self._parse_json(tviplayer, group_id).get('player', {})
duration = int_or_none(player.get('duration'))
programme_id = player.get('vpid')
if not programme_id:
programme_id = self._search_regex(
r'"vpid"\s*:\s*"([\da-z]{8})"', webpage, 'vpid', fatal=False, default=None)
if programme_id:
player = self._download_json(
'http://www.bbc.co.uk/iplayer/episode/%s.json' % group_id,
group_id)['jsConf']['player']
title = player['title']
description = player['subtitle']
duration = player['duration']
formats, subtitles = self._download_media_selector(programme_id)
title = self._og_search_title(webpage)
description = self._search_regex(
r'<p class="[^"]*medium-description[^"]*">([^<]+)</p>',
webpage, 'description', fatal=False)
else:
programme_id, title, description, duration, formats, subtitles = self._download_playlist(group_id)
@@ -345,6 +372,7 @@ class BBCCoUkIE(InfoExtractor):
'id': programme_id,
'title': title,
'description': description,
'thumbnail': self._og_search_thumbnail(webpage, default=None),
'duration': duration,
'formats': formats,
'subtitles': subtitles,

View File

@@ -16,11 +16,11 @@ class BetIE(InfoExtractor):
{
'url': 'http://www.bet.com/news/politics/2014/12/08/in-bet-exclusive-obama-talks-race-and-racism.html',
'info_dict': {
'id': '740ab250-bb94-4a8a-8787-fe0de7c74471',
'id': 'news/national/2014/a-conversation-with-president-obama',
'display_id': 'in-bet-exclusive-obama-talks-race-and-racism',
'ext': 'flv',
'title': 'BET News Presents: A Conversation With President Obama',
'description': 'md5:5a88d8ae912c1b33e090290af7ec33c6',
'title': 'A Conversation With President Obama',
'description': 'md5:699d0652a350cf3e491cd15cc745b5da',
'duration': 1534,
'timestamp': 1418075340,
'upload_date': '20141208',
@@ -35,7 +35,7 @@ class BetIE(InfoExtractor):
{
'url': 'http://www.bet.com/video/news/national/2014/justice-for-ferguson-a-community-reacts.html',
'info_dict': {
'id': 'bcd1b1df-673a-42cf-8d01-b282db608f2d',
'id': 'news/national/2014/justice-for-ferguson-a-community-reacts',
'display_id': 'justice-for-ferguson-a-community-reacts',
'ext': 'flv',
'title': 'Justice for Ferguson: A Community Reacts',
@@ -61,6 +61,9 @@ class BetIE(InfoExtractor):
[r'mediaURL\s*:\s*"([^"]+)"', r"var\s+mrssMediaUrl\s*=\s*'([^']+)'"],
webpage, 'media URL'))
video_id = self._search_regex(
r'/video/(.*)/_jcr_content/', media_url, 'video id')
mrss = self._download_xml(media_url, display_id)
item = mrss.find('./channel/item')
@@ -75,8 +78,6 @@ class BetIE(InfoExtractor):
description = xpath_text(
item, './description', 'description', fatal=False)
video_id = xpath_text(item, './guid', 'video id', fatal=False)
timestamp = parse_iso8601(xpath_text(
item, xpath_with_ns('./dc:date', NS_MAP),
'upload date', fatal=False))

View File

@@ -2,7 +2,10 @@
from __future__ import unicode_literals
from .common import InfoExtractor
from ..utils import int_or_none
from ..utils import (
int_or_none,
fix_xml_ampersands,
)
class BildIE(InfoExtractor):
@@ -15,7 +18,7 @@ class BildIE(InfoExtractor):
'id': '38184146',
'ext': 'mp4',
'title': 'BILD hat sie getestet',
'thumbnail': 'http://bilder.bild.de/fotos/stand-das-koennen-die-neuen-ipads-38184138/Bild/1.bild.jpg',
'thumbnail': 're:^https?://.*\.jpg$',
'duration': 196,
'description': 'Mit dem iPad Air 2 und dem iPad Mini 3 hat Apple zwei neue Tablet-Modelle präsentiert. BILD-Reporter Sven Stein durfte die Geräte bereits testen. ',
}
@@ -25,7 +28,7 @@ class BildIE(InfoExtractor):
video_id = self._match_id(url)
xml_url = url.split(".bild.html")[0] + ",view=xml.bild.xml"
doc = self._download_xml(xml_url, video_id)
doc = self._download_xml(xml_url, video_id, transform_source=fix_xml_ampersands)
duration = int_or_none(doc.attrib.get('duration'), scale=1000)

View File

@@ -2,6 +2,9 @@
from __future__ import unicode_literals
import re
import itertools
import json
import xml.etree.ElementTree as ET
from .common import InfoExtractor
from ..utils import (
@@ -14,18 +17,25 @@ from ..utils import (
class BiliBiliIE(InfoExtractor):
_VALID_URL = r'http://www\.bilibili\.(?:tv|com)/video/av(?P<id>[0-9]+)/'
_TEST = {
_TESTS = [{
'url': 'http://www.bilibili.tv/video/av1074402/',
'md5': '2c301e4dab317596e837c3e7633e7d86',
'info_dict': {
'id': '1074402',
'id': '1074402_part1',
'ext': 'flv',
'title': '【金坷垃】金泡沫',
'duration': 308,
'upload_date': '20140420',
'thumbnail': 're:^https?://.+\.jpg',
},
}
}, {
'url': 'http://www.bilibili.com/video/av1041170/',
'info_dict': {
'id': '1041170',
'title': '【BD1080P】刀语【诸神&异域】',
},
'playlist_count': 9,
}]
def _real_extract(self, url):
video_id = self._match_id(url)
@@ -57,19 +67,22 @@ class BiliBiliIE(InfoExtractor):
cid = self._search_regex(r'cid=(\d+)', webpage, 'cid')
lq_doc = self._download_xml(
entries = []
lq_page = self._download_webpage(
'http://interface.bilibili.com/v_cdn_play?appkey=1&cid=%s' % cid,
video_id,
note='Downloading LQ video info'
)
lq_durl = lq_doc.find('./durl')
formats = [{
'format_id': 'lq',
'quality': 1,
'url': lq_durl.find('./url').text,
'filesize': int_or_none(
lq_durl.find('./size'), get_attr='text'),
}]
try:
err_info = json.loads(lq_page)
raise ExtractorError(
'BiliBili said: ' + err_info['error_text'], expected=True)
except ValueError:
pass
lq_doc = ET.fromstring(lq_page)
lq_durls = lq_doc.findall('./durl')
hq_doc = self._download_xml(
'http://interface.bilibili.com/playurl?appkey=1&cid=%s' % cid,
@@ -78,22 +91,45 @@ class BiliBiliIE(InfoExtractor):
fatal=False,
)
if hq_doc is not False:
hq_durl = hq_doc.find('./durl')
formats.append({
'format_id': 'hq',
'quality': 2,
'ext': 'flv',
'url': hq_durl.find('./url').text,
hq_durls = hq_doc.findall('./durl')
assert len(lq_durls) == len(hq_durls)
else:
hq_durls = itertools.repeat(None)
i = 1
for lq_durl, hq_durl in zip(lq_durls, hq_durls):
formats = [{
'format_id': 'lq',
'quality': 1,
'url': lq_durl.find('./url').text,
'filesize': int_or_none(
hq_durl.find('./size'), get_attr='text'),
lq_durl.find('./size'), get_attr='text'),
}]
if hq_durl is not None:
formats.append({
'format_id': 'hq',
'quality': 2,
'ext': 'flv',
'url': hq_durl.find('./url').text,
'filesize': int_or_none(
hq_durl.find('./size'), get_attr='text'),
})
self._sort_formats(formats)
entries.append({
'id': '%s_part%d' % (video_id, i),
'title': title,
'formats': formats,
'duration': duration,
'upload_date': upload_date,
'thumbnail': thumbnail,
})
self._sort_formats(formats)
i += 1
return {
'_type': 'multi_video',
'entries': entries,
'id': video_id,
'title': title,
'formats': formats,
'duration': duration,
'upload_date': upload_date,
'thumbnail': thumbnail,
'title': title
}

View File

@@ -16,27 +16,38 @@ class BRIE(InfoExtractor):
_TESTS = [
{
'url': 'http://www.br.de/mediathek/video/sendungen/heimatsound/heimatsound-festival-2014-trailer-100.html',
'md5': '93556dd2bcb2948d9259f8670c516d59',
'url': 'http://www.br.de/mediathek/video/sendungen/abendschau/betriebliche-altersvorsorge-104.html',
'md5': '83a0477cf0b8451027eb566d88b51106',
'info_dict': {
'id': '25e279aa-1ffd-40fd-9955-5325bd48a53a',
'id': '48f656ef-287e-486f-be86-459122db22cc',
'ext': 'mp4',
'title': 'Wenn das Traditions-Theater wackelt',
'description': 'Heimatsound-Festival 2014: Wenn das Traditions-Theater wackelt',
'duration': 34,
'uploader': 'BR',
'upload_date': '20140802',
'title': 'Die böse Überraschung',
'description': 'Betriebliche Altersvorsorge: Die böse Überraschung',
'duration': 180,
'uploader': 'Reinhard Weber',
'upload_date': '20150422',
}
},
{
'url': 'http://www.br.de/nachrichten/schaeuble-haushaltsentwurf-bundestag-100.html',
'md5': '3db0df1a9a9cd9fa0c70e6ea8aa8e820',
'url': 'http://www.br.de/nachrichten/oberbayern/inhalt/muenchner-polizeipraesident-schreiber-gestorben-100.html',
'md5': 'a44396d73ab6a68a69a568fae10705bb',
'info_dict': {
'id': 'c6aae3de-2cf9-43f2-957f-f17fef9afaab',
'id': 'a4b83e34-123d-4b81-9f4e-c0d3121a4e05',
'ext': 'mp4',
'title': 'Manfred Schreiber ist tot',
'description': 'Abendschau kompakt: Manfred Schreiber ist tot',
'duration': 26,
}
},
{
'url': 'http://www.br.de/radio/br-klassik/sendungen/allegro/premiere-urauffuehrung-the-land-2015-dance-festival-muenchen-100.html',
'md5': '8b5b27c0b090f3b35eac4ab3f7a73d3d',
'info_dict': {
'id': '74c603c9-26d3-48bb-b85b-079aeed66e0b',
'ext': 'aac',
'title': '"Keine neuen Schulden im nächsten Jahr"',
'description': 'Haushaltsentwurf: "Keine neuen Schulden im nächsten Jahr"',
'duration': 64,
'title': 'Kurzweilig und sehr bewegend',
'description': '"The Land" von Peeping Tom: Kurzweilig und sehr bewegend',
'duration': 296,
}
},
{

View File

@@ -13,6 +13,7 @@ from ..compat import (
compat_urllib_parse_urlparse,
compat_urllib_request,
compat_urlparse,
compat_xml_parse_error,
)
from ..utils import (
determine_ext,
@@ -119,7 +120,7 @@ class BrightcoveIE(InfoExtractor):
try:
object_doc = xml.etree.ElementTree.fromstring(object_str.encode('utf-8'))
except xml.etree.ElementTree.ParseError:
except compat_xml_parse_error:
return
fv_el = find_xpath_attr(object_doc, './param', 'name', 'flashVars')
@@ -156,6 +157,28 @@ class BrightcoveIE(InfoExtractor):
linkBase = find_param('linkBaseURL')
if linkBase is not None:
params['linkBaseURL'] = linkBase
return cls._make_brightcove_url(params)
@classmethod
def _build_brighcove_url_from_js(cls, object_js):
# The layout of JS is as follows:
# customBC.createVideo = function (width, height, playerID, playerKey, videoPlayer, VideoRandomID) {
# // build Brightcove <object /> XML
# }
m = re.search(
r'''(?x)customBC.\createVideo\(
.*? # skipping width and height
["\'](?P<playerID>\d+)["\']\s*,\s* # playerID
["\'](?P<playerKey>AQ[^"\']{48})[^"\']*["\']\s*,\s* # playerKey begins with AQ and is 50 characters
# in length, however it's appended to itself
# in places, so truncate
["\'](?P<videoID>\d+)["\'] # @videoPlayer
''', object_js)
if m:
return cls._make_brightcove_url(m.groupdict())
@classmethod
def _make_brightcove_url(cls, params):
data = compat_urllib_parse.urlencode(params)
return cls._FEDERATED_URL_TEMPLATE % data
@@ -172,7 +195,7 @@ class BrightcoveIE(InfoExtractor):
"""Return a list of all Brightcove URLs from the webpage """
url_m = re.search(
r'<meta\s+property="og:video"\s+content="(https?://(?:secure|c)\.brightcove.com/[^"]+)"',
r'<meta\s+property=[\'"]og:video[\'"]\s+content=[\'"](https?://(?:secure|c)\.brightcove.com/[^\'"]+)[\'"]',
webpage)
if url_m:
url = unescapeHTML(url_m.group(1))
@@ -188,7 +211,12 @@ class BrightcoveIE(InfoExtractor):
[^>]*?>\s*<param\s+name="movie"\s+value="https?://[^/]*brightcove\.com/
).+?>\s*</object>''',
webpage)
return list(filter(None, [cls._build_brighcove_url(m) for m in matches]))
if matches:
return list(filter(None, [cls._build_brighcove_url(m) for m in matches]))
return list(filter(None, [
cls._build_brighcove_url_from_js(custom_bc)
for custom_bc in re.findall(r'(customBC\.createVideo\(.+?\);)', webpage)]))
def _real_extract(self, url):
url, smuggled_data = unsmuggle_url(url, {})

View File

@@ -16,7 +16,7 @@ class BYUtvIE(InfoExtractor):
'ext': 'mp4',
'description': 'md5:5438d33774b6bdc662f9485a340401cc',
'title': 'Season 5 Episode 5',
'thumbnail': 're:^https?://.*promo.*'
'thumbnail': 're:^https?://.*\.jpg$'
},
'params': {
'skip_download': True,

View File

@@ -25,14 +25,14 @@ class CanalplusIE(InfoExtractor):
}
_TESTS = [{
'url': 'http://www.canalplus.fr/c-infos-documentaires/pid1830-c-zapping.html?vid=922470',
'md5': '3db39fb48b9685438ecf33a1078023e4',
'url': 'http://www.canalplus.fr/c-emissions/pid1830-c-zapping.html?vid=1263092',
'md5': 'b3481d7ca972f61e37420798d0a9d934',
'info_dict': {
'id': '922470',
'id': '1263092',
'ext': 'flv',
'title': 'Zapping - 26/08/13',
'description': 'Le meilleur de toutes les chaînes, tous les jours.\nEmission du 26 août 2013',
'upload_date': '20130826',
'title': 'Le Zapping - 13/05/15',
'description': 'md5:09738c0d06be4b5d06a0940edb0da73f',
'upload_date': '20150513',
},
}, {
'url': 'http://www.piwiplus.fr/videos-piwi/pid1405-le-labyrinthe-boing-super-ranger.html?vid=1108190',
@@ -56,7 +56,7 @@ class CanalplusIE(InfoExtractor):
'skip': 'videos get deleted after a while',
}, {
'url': 'http://www.itele.fr/france/video/aubervilliers-un-lycee-en-colere-111559',
'md5': '65aa83ad62fe107ce29e564bb8712580',
'md5': 'f3a46edcdf28006598ffaf5b30e6a2d4',
'info_dict': {
'id': '1213714',
'ext': 'flv',

View File

@@ -4,12 +4,13 @@ from .common import InfoExtractor
class CBSIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?cbs\.com/shows/[^/]+/(?:video|artist)/(?P<id>[^/]+)/.*'
_VALID_URL = r'https?://(?:www\.)?(?:cbs\.com/shows/[^/]+/(?:video|artist)|colbertlateshow\.com/(?:video|podcasts))/[^/]+/(?P<id>[^/]+)'
_TESTS = [{
'url': 'http://www.cbs.com/shows/garth-brooks/video/_u7W953k6la293J7EPTd9oHkSPs6Xn6_/connect-chat-feat-garth-brooks/',
'info_dict': {
'id': '4JUVEwq3wUT7',
'display_id': 'connect-chat-feat-garth-brooks',
'ext': 'flv',
'title': 'Connect Chat feat. Garth Brooks',
'description': 'Connect with country music singer Garth Brooks, as he chats with fans on Wednesday November 27, 2013. Be sure to tune in to Garth Brooks: Live from Las Vegas, Friday November 29, at 9/8c on CBS!',
@@ -24,6 +25,7 @@ class CBSIE(InfoExtractor):
'url': 'http://www.cbs.com/shows/liveonletterman/artist/221752/st-vincent/',
'info_dict': {
'id': 'WWF_5KqY3PK1',
'display_id': 'st-vincent',
'ext': 'flv',
'title': 'Live on Letterman - St. Vincent',
'description': 'Live On Letterman: St. Vincent in concert from New York\'s Ed Sullivan Theater on Tuesday, July 16, 2014.',
@@ -34,12 +36,23 @@ class CBSIE(InfoExtractor):
'skip_download': True,
},
'_skip': 'Blocked outside the US',
}, {
'url': 'http://colbertlateshow.com/video/8GmB0oY0McANFvp2aEffk9jZZZ2YyXxy/the-colbeard/',
'only_matching': True,
}, {
'url': 'http://www.colbertlateshow.com/podcasts/dYSwjqPs_X1tvbV_P2FcPWRa_qT6akTC/in-the-bad-room-with-stephen/',
'only_matching': True,
}]
def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
display_id = self._match_id(url)
webpage = self._download_webpage(url, display_id)
real_id = self._search_regex(
r"video\.settings\.pid\s*=\s*'([^']+)';",
[r"video\.settings\.pid\s*=\s*'([^']+)';", r"cbsplayer\.pid\s*=\s*'([^']+)';"],
webpage, 'real video ID')
return self.url_result('theplatform:%s' % real_id)
return {
'_type': 'url_transparent',
'ie_key': 'ThePlatform',
'url': 'theplatform:%s' % real_id,
'display_id': display_id,
}

View File

@@ -32,7 +32,7 @@ class CBSNewsIE(InfoExtractor):
'id': 'fort-hood-shooting-army-downplays-mental-illness-as-cause-of-attack',
'ext': 'flv',
'title': 'Fort Hood shooting: Army downplays mental illness as cause of attack',
'thumbnail': 'http://cbsnews2.cbsistatic.com/hub/i/r/2014/04/04/0c9fbc66-576b-41ca-8069-02d122060dd2/thumbnail/140x90/6dad7a502f88875ceac38202984b6d58/en-0404-werner-replace-640x360.jpg',
'thumbnail': 're:^https?://.*\.jpg$',
'duration': 205,
},
'params': {

View File

@@ -16,7 +16,7 @@ class CCCIE(InfoExtractor):
_TEST = {
'url': 'http://media.ccc.de/browse/congress/2013/30C3_-_5443_-_en_-_saal_g_-_201312281830_-_introduction_to_processor_design_-_byterazor.html#video',
'md5': '205a365d0d57c0b1e43a12c9ffe8f9be',
'md5': '3a1eda8f3a29515d27f5adb967d7e740',
'info_dict': {
'id': '20131228183',
'ext': 'mp4',
@@ -51,7 +51,7 @@ class CCCIE(InfoExtractor):
matches = re.finditer(r'''(?xs)
<(?:span|div)\s+class='label\s+filetype'>(?P<format>.*?)</(?:span|div)>\s*
<a\s+href='(?P<http_url>[^']+)'>\s*
<a\s+download\s+href='(?P<http_url>[^']+)'>\s*
(?:
.*?
<a\s+href='(?P<torrent_url>[^']+\.torrent)'

View File

@@ -57,7 +57,7 @@ class ChilloutzoneIE(InfoExtractor):
base64_video_info = self._html_search_regex(
r'var cozVidData = "(.+?)";', webpage, 'video data')
decoded_video_info = base64.b64decode(base64_video_info).decode("utf-8")
decoded_video_info = base64.b64decode(base64_video_info.encode('utf-8')).decode('utf-8')
video_info_dict = json.loads(decoded_video_info)
# get video information from dict

View File

@@ -60,6 +60,17 @@ class CinemassacreIE(InfoExtractor):
'uploader_id': 'Cinemassacre',
'title': 'AVGN: McKids',
}
},
{
'url': 'http://cinemassacre.com/2015/05/25/mario-kart-64-nintendo-64-james-mike-mondays/',
'md5': '1376908e49572389e7b06251a53cdd08',
'info_dict': {
'id': 'Cinemassacre-555779690c440',
'ext': 'mp4',
'description': 'Lets Play Mario Kart 64 !! Mario Kart 64 is a classic go-kart racing game released for the Nintendo 64 (N64). Today James & Mike do 4 player Battle Mode with Kyle and Bootsy!',
'title': 'Mario Kart 64 (Nintendo 64) James & Mike Mondays',
'upload_date': '20150525',
}
}
]
@@ -72,7 +83,7 @@ class CinemassacreIE(InfoExtractor):
playerdata_url = self._search_regex(
[
r'src="(http://player\.screenwavemedia\.com/play/[a-zA-Z]+\.php\?[^"]*\bid=.+?)"',
r'src="(http://(?:player2\.screenwavemedia\.com|player\.screenwavemedia\.com/play)/[a-zA-Z]+\.php\?[^"]*\bid=.+?)"',
r'<iframe[^>]+src="((?:https?:)?//(?:[^.]+\.)?youtube\.com/.+?)"',
],
webpage, 'player data URL', default=None)

View File

@@ -11,7 +11,7 @@ from ..utils import (
class CNETIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?cnet\.com/videos/(?P<id>[^/]+)/'
_TEST = {
_TESTS = [{
'url': 'http://www.cnet.com/videos/hands-on-with-microsofts-windows-8-1-update/',
'info_dict': {
'id': '56f4ea68-bd21-4852-b08c-4de5b8354c60',
@@ -25,7 +25,20 @@ class CNETIE(InfoExtractor):
'params': {
'skip_download': 'requires rtmpdump',
}
}
}, {
'url': 'http://www.cnet.com/videos/whiny-pothole-tweets-at-local-government-when-hit-by-cars-tomorrow-daily-187/',
'info_dict': {
'id': '56527b93-d25d-44e3-b738-f989ce2e49ba',
'ext': 'flv',
'description': 'Khail and Ashley wonder what other civic woes can be solved by self-tweeting objects, investigate a new kind of VR camera and watch an origami robot self-assemble, walk, climb, dig and dissolve. #TDPothole',
'uploader_id': 'b163284d-6b73-44fc-b3e6-3da66c392d40',
'uploader': 'Ashley Esqueda',
'title': 'Whiny potholes tweet at local government when hit by cars (Tomorrow Daily 187)',
},
'params': {
'skip_download': True, # requires rtmpdump
},
}]
def _real_extract(self, url):
display_id = self._match_id(url)
@@ -42,7 +55,7 @@ class CNETIE(InfoExtractor):
raise ExtractorError('Cannot find video data')
mpx_account = data['config']['players']['default']['mpx_account']
vid = vdata['files']['rtmp']
vid = vdata['files'].get('rtmp', vdata['files']['hds'])
tp_link = 'http://link.theplatform.com/s/%s/%s' % (mpx_account, vid)
video_id = vdata['id']

View File

@@ -12,7 +12,7 @@ from ..utils import (
class CNNIE(InfoExtractor):
_VALID_URL = r'''(?x)https?://(?:(?:edition|www)\.)?cnn\.com/video/(?:data/.+?|\?)/
(?P<path>.+?/(?P<title>[^/]+?)(?:\.(?:[a-z]{3,5})(?:-ap)?|(?=&)))'''
(?P<path>.+?/(?P<title>[^/]+?)(?:\.(?:[a-z\-]+)|(?=&)))'''
_TESTS = [{
'url': 'http://edition.cnn.com/video/?/video/sports/2013/06/09/nadal-1-on-1.cnn',

View File

@@ -22,6 +22,7 @@ from ..compat import (
compat_str,
)
from ..utils import (
NO_DEFAULT,
age_restricted,
bug_reports_message,
clean_html,
@@ -33,7 +34,6 @@ from ..utils import (
sanitize_filename,
unescapeHTML,
)
_NO_DEFAULT = object()
class InfoExtractor(object):
@@ -47,7 +47,7 @@ class InfoExtractor(object):
information possibly downloading the video to the file system, among
other possible outcomes.
The type field determines the the type of the result.
The type field determines the type of the result.
By far the most common value (and the default if _type is missing) is
"video", which indicates a single video.
@@ -111,11 +111,8 @@ class InfoExtractor(object):
(quality takes higher priority)
-1 for default (order by other properties),
-2 or smaller for less than default.
* http_method HTTP method to use for the download.
* http_headers A dictionary of additional HTTP headers
to add to the request.
* http_post_data Additional data to send with a POST
request.
* stretched_ratio If given and not 1, indicates that the
video's pixels are not square.
width : height ratio as float.
@@ -526,7 +523,7 @@ class InfoExtractor(object):
video_info['description'] = playlist_description
return video_info
def _search_regex(self, pattern, string, name, default=_NO_DEFAULT, fatal=True, flags=0, group=None):
def _search_regex(self, pattern, string, name, default=NO_DEFAULT, fatal=True, flags=0, group=None):
"""
Perform a regex search on the given string, using a single or a list of
patterns returning the first matching group.
@@ -552,7 +549,7 @@ class InfoExtractor(object):
return next(g for g in mobj.groups() if g is not None)
else:
return mobj.group(group)
elif default is not _NO_DEFAULT:
elif default is not NO_DEFAULT:
return default
elif fatal:
raise RegexNotFoundError('Unable to extract %s' % _name)
@@ -560,7 +557,7 @@ class InfoExtractor(object):
self._downloader.report_warning('unable to extract %s' % _name + bug_reports_message())
return None
def _html_search_regex(self, pattern, string, name, default=_NO_DEFAULT, fatal=True, flags=0, group=None):
def _html_search_regex(self, pattern, string, name, default=NO_DEFAULT, fatal=True, flags=0, group=None):
"""
Like _search_regex, but strips HTML tags and unescapes entities.
"""
@@ -572,7 +569,7 @@ class InfoExtractor(object):
def _get_login_info(self):
"""
Get the the login info as (username, password)
Get the login info as (username, password)
It will look in the netrc file using the _NETRC_MACHINE value
If there's no info available, return (None, None)
"""
@@ -767,7 +764,7 @@ class InfoExtractor(object):
f.get('fps') if f.get('fps') is not None else -1,
f.get('filesize_approx') if f.get('filesize_approx') is not None else -1,
f.get('source_preference') if f.get('source_preference') is not None else -1,
f.get('format_id'),
f.get('format_id') if f.get('format_id') is not None else '',
)
formats.sort(key=_formats_key)
@@ -789,8 +786,8 @@ class InfoExtractor(object):
return True
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError):
self.report_warning(
'%s URL is invalid, skipping' % item, video_id)
self.to_screen(
'%s: %s URL is invalid, skipping' % (video_id, item))
return False
raise
@@ -849,7 +846,8 @@ class InfoExtractor(object):
def _extract_m3u8_formats(self, m3u8_url, video_id, ext=None,
entry_protocol='m3u8', preference=None,
m3u8_id=None):
m3u8_id=None, note=None, errnote=None,
fatal=True):
formats = [{
'format_id': '-'.join(filter(None, [m3u8_id, 'meta'])),
@@ -868,8 +866,11 @@ class InfoExtractor(object):
m3u8_doc = self._download_webpage(
m3u8_url, video_id,
note='Downloading m3u8 information',
errnote='Failed to download m3u8 information')
note=note or 'Downloading m3u8 information',
errnote=errnote or 'Failed to download m3u8 information',
fatal=fatal)
if m3u8_doc is False:
return m3u8_doc
last_info = None
last_media = None
kv_rex = re.compile(
@@ -899,7 +900,7 @@ class InfoExtractor(object):
format_id = []
if m3u8_id:
format_id.append(m3u8_id)
last_media_name = last_media.get('NAME') if last_media else None
last_media_name = last_media.get('NAME') if last_media and last_media.get('TYPE') != 'SUBTITLES' else None
format_id.append(last_media_name if last_media_name else '%d' % (tbr if tbr else len(formats)))
f = {
'format_id': '-'.join(format_id),
@@ -1075,9 +1076,6 @@ class InfoExtractor(object):
def _get_automatic_captions(self, *args, **kwargs):
raise NotImplementedError("This method must be implemented by subclasses")
def _subtitles_timecode(self, seconds):
return '%02d:%02d:%02d.%03d' % (seconds / 3600, (seconds % 3600) / 60, seconds % 60, (seconds % 1) * 1000)
class SearchInfoExtractor(InfoExtractor):
"""

View File

@@ -27,7 +27,7 @@ from ..aes import (
class CrunchyrollIE(InfoExtractor):
_VALID_URL = r'https?://(?:(?P<prefix>www|m)\.)?(?P<url>crunchyroll\.(?:com|fr)/(?:[^/]*/[^/?&]*?|media/\?id=)(?P<video_id>[0-9]+))(?:[/?&]|$)'
_VALID_URL = r'https?://(?:(?P<prefix>www|m)\.)?(?P<url>crunchyroll\.(?:com|fr)/(?:media(?:-|/\?id=)|[^/]*/[^/?&]*?)(?P<video_id>[0-9]+))(?:[/?&]|$)'
_NETRC_MACHINE = 'crunchyroll'
_TESTS = [{
'url': 'http://www.crunchyroll.com/wanna-be-the-strongest-in-the-world/episode-1-an-idol-wrestler-is-born-645513',
@@ -45,6 +45,22 @@ class CrunchyrollIE(InfoExtractor):
# rtmp
'skip_download': True,
},
}, {
'url': 'http://www.crunchyroll.com/media-589804/culture-japan-1',
'info_dict': {
'id': '589804',
'ext': 'flv',
'title': 'Culture Japan Episode 1 Rebuilding Japan after the 3.11',
'description': 'md5:fe2743efedb49d279552926d0bd0cd9e',
'thumbnail': 're:^https?://.*\.jpg$',
'uploader': 'Danny Choo Network',
'upload_date': '20120213',
},
'params': {
# rtmp
'skip_download': True,
},
}, {
'url': 'http://www.crunchyroll.fr/girl-friend-beta/episode-11-goodbye-la-mode-661697',
'only_matching': True,
@@ -76,8 +92,8 @@ class CrunchyrollIE(InfoExtractor):
self._login()
def _decrypt_subtitles(self, data, iv, id):
data = bytes_to_intlist(data)
iv = bytes_to_intlist(iv)
data = bytes_to_intlist(base64.b64decode(data.encode('utf-8')))
iv = bytes_to_intlist(base64.b64decode(iv.encode('utf-8')))
id = int(id)
def obfuscate_key_aux(count, modulo, start):
@@ -179,6 +195,16 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
return output
def _extract_subtitles(self, subtitle):
sub_root = xml.etree.ElementTree.fromstring(subtitle)
return [{
'ext': 'srt',
'data': self._convert_subtitles_to_srt(sub_root),
}, {
'ext': 'ass',
'data': self._convert_subtitles_to_ass(sub_root),
}]
def _get_subtitles(self, video_id, webpage):
subtitles = {}
for sub_id, sub_name in re.findall(r'\?ssid=([0-9]+)" title="([^"]+)', webpage):
@@ -190,25 +216,11 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
data = self._search_regex(r'<data>([^<]+)', sub_page, 'subtitle_data', fatal=False)
if not id or not iv or not data:
continue
id = int(id)
iv = base64.b64decode(iv)
data = base64.b64decode(data)
subtitle = self._decrypt_subtitles(data, iv, id).decode('utf-8')
lang_code = self._search_regex(r'lang_code=["\']([^"\']+)', subtitle, 'subtitle_lang_code', fatal=False)
if not lang_code:
continue
sub_root = xml.etree.ElementTree.fromstring(subtitle)
subtitles[lang_code] = [
{
'ext': 'srt',
'data': self._convert_subtitles_to_srt(sub_root),
},
{
'ext': 'ass',
'data': self._convert_subtitles_to_ass(sub_root),
},
]
subtitles[lang_code] = self._extract_subtitles(subtitle)
return subtitles
def _real_extract(self, url):
@@ -255,16 +267,17 @@ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
for fmt in re.findall(r'showmedia\.([0-9]{3,4})p', webpage):
stream_quality, stream_format = self._FORMAT_IDS[fmt]
video_format = fmt + 'p'
streamdata_req = compat_urllib_request.Request('http://www.crunchyroll.com/xml/')
# urlencode doesn't work!
streamdata_req.data = 'req=RpcApiVideoEncode%5FGetStreamInfo&video%5Fencode%5Fquality=' + stream_quality + '&media%5Fid=' + stream_id + '&video%5Fformat=' + stream_format
streamdata_req = compat_urllib_request.Request(
'http://www.crunchyroll.com/xml/?req=RpcApiVideoPlayer_GetStandardConfig&media_id=%s&video_format=%s&video_quality=%s'
% (stream_id, stream_format, stream_quality),
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-Length', str(len(streamdata_req.data)))
streamdata = self._download_xml(
streamdata_req, video_id,
note='Downloading media info for %s' % video_format)
video_url = streamdata.find('./host').text
video_play_path = streamdata.find('./file').text
stream_info = streamdata.find('./{default}preload/stream_info')
video_url = stream_info.find('./host').text
video_play_path = stream_info.find('./file').text
formats.append({
'url': video_url,
'play_path': video_play_path,

View File

@@ -52,6 +52,7 @@ class DailymotionIE(DailymotionBaseInfoExtractor):
'ext': 'mp4',
'uploader': 'IGN',
'title': 'Steam Machine Models, Pricing Listed on Steam Store - IGN News',
'upload_date': '20150306',
}
},
# Vevo video
@@ -85,7 +86,7 @@ class DailymotionIE(DailymotionBaseInfoExtractor):
def _real_extract(self, url):
video_id = self._match_id(url)
url = 'http://www.dailymotion.com/video/%s' % video_id
url = 'https://www.dailymotion.com/video/%s' % video_id
# Retrieve video webpage to extract further information
request = self._build_request(url)
@@ -106,11 +107,11 @@ class DailymotionIE(DailymotionBaseInfoExtractor):
age_limit = self._rta_search(webpage)
video_upload_date = None
mobj = re.search(r'<div class="[^"]*uploaded_cont[^"]*" title="[^"]*">([0-9]{2})-([0-9]{2})-([0-9]{4})</div>', webpage)
mobj = re.search(r'<meta property="video:release_date" content="([0-9]{4})-([0-9]{2})-([0-9]{2}).+?"/>', webpage)
if mobj is not None:
video_upload_date = mobj.group(3) + mobj.group(2) + mobj.group(1)
video_upload_date = mobj.group(1) + mobj.group(2) + mobj.group(3)
embed_url = 'http://www.dailymotion.com/embed/video/%s' % video_id
embed_url = 'https://www.dailymotion.com/embed/video/%s' % video_id
embed_request = self._build_request(embed_url)
embed_page = self._download_webpage(
embed_request, video_id, 'Downloading embed page')
@@ -224,7 +225,7 @@ class DailymotionPlaylistIE(DailymotionBaseInfoExtractor):
class DailymotionUserIE(DailymotionPlaylistIE):
IE_NAME = 'dailymotion:user'
_VALID_URL = r'https?://(?:www\.)?dailymotion\.[a-z]{2,3}/(?:old/)?user/(?P<user>[^/]+)'
_VALID_URL = r'https?://(?:www\.)?dailymotion\.[a-z]{2,3}/(?:(?:old/)?user/)?(?P<user>[^/]+)$'
_PAGE_TEMPLATE = 'http://www.dailymotion.com/user/%s/%s'
_TESTS = [{
'url': 'https://www.dailymotion.com/user/nqtv',
@@ -238,7 +239,8 @@ class DailymotionUserIE(DailymotionPlaylistIE):
def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)
user = mobj.group('user')
webpage = self._download_webpage(url, user)
webpage = self._download_webpage(
'https://www.dailymotion.com/user/%s' % user, user)
full_user = unescapeHTML(self._html_search_regex(
r'<a class="nav-image" title="([^"]+)" href="/%s">' % re.escape(user),
webpage, 'user'))
@@ -249,3 +251,53 @@ class DailymotionUserIE(DailymotionPlaylistIE):
'title': full_user,
'entries': self._extract_entries(user),
}
class DailymotionCloudIE(DailymotionBaseInfoExtractor):
_VALID_URL_PREFIX = r'http://api\.dmcloud\.net/(?:player/)?embed/'
_VALID_URL = r'%s[^/]+/(?P<id>[^/?]+)' % _VALID_URL_PREFIX
_VALID_EMBED_URL = r'%s[^/]+/[^\'"]+' % _VALID_URL_PREFIX
_TESTS = [{
# From http://www.francetvinfo.fr/economie/entreprises/les-entreprises-familiales-le-secret-de-la-reussite_933271.html
# Tested at FranceTvInfo_2
'url': 'http://api.dmcloud.net/embed/4e7343f894a6f677b10006b4/556e03339473995ee145930c?auth=1464865870-0-jyhsm84b-ead4c701fb750cf9367bf4447167a3db&autoplay=1',
'only_matching': True,
}, {
# http://www.francetvinfo.fr/societe/larguez-les-amarres-le-cobaturage-se-developpe_980101.html
'url': 'http://api.dmcloud.net/player/embed/4e7343f894a6f677b10006b4/559545469473996d31429f06?auth=1467430263-0-90tglw2l-a3a4b64ed41efe48d7fccad85b8b8fda&autoplay=1',
'only_matching': True,
}]
@classmethod
def _extract_dmcloud_url(self, webpage):
mobj = re.search(r'<iframe[^>]+src=[\'"](%s)[\'"]' % self._VALID_EMBED_URL, webpage)
if mobj:
return mobj.group(1)
mobj = re.search(
r'<input[^>]+id=[\'"]dmcloudUrlEmissionSelect[\'"][^>]+value=[\'"](%s)[\'"]' % self._VALID_EMBED_URL,
webpage)
if mobj:
return mobj.group(1)
def _real_extract(self, url):
video_id = self._match_id(url)
request = self._build_request(url)
webpage = self._download_webpage(request, video_id)
title = self._html_search_regex(r'<title>([^>]+)</title>', webpage, 'title')
video_info = self._parse_json(self._search_regex(
r'var\s+info\s*=\s*([^;]+);', webpage, 'video info'), video_id)
# TODO: parse ios_url, which is in fact a manifest
video_url = video_info['mp4_url']
return {
'id': video_id,
'url': video_url,
'title': title,
'thumbnail': video_info.get('thumbnail_url'),
}

View File

@@ -2,19 +2,19 @@ from __future__ import unicode_literals
from .common import InfoExtractor
from ..utils import (
parse_duration,
parse_iso8601,
int_or_none,
)
from ..compat import compat_str
class DiscoveryIE(InfoExtractor):
_VALID_URL = r'http://www\.discovery\.com\/[a-zA-Z0-9\-]*/[a-zA-Z0-9\-]*/videos/(?P<id>[a-zA-Z0-9_\-]*)(?:\.htm)?'
_TEST = {
_TESTS = [{
'url': 'http://www.discovery.com/tv-shows/mythbusters/videos/mission-impossible-outtakes.htm',
'md5': '3c69d77d9b0d82bfd5e5932a60f26504',
'info_dict': {
'id': 'mission-impossible-outtakes',
'ext': 'flv',
'id': '20769',
'ext': 'mp4',
'title': 'Mission Impossible Outtakes',
'description': ('Watch Jamie Hyneman and Adam Savage practice being'
' each other -- to the point of confusing Jamie\'s dog -- and '
@@ -24,22 +24,36 @@ class DiscoveryIE(InfoExtractor):
'timestamp': 1303099200,
'upload_date': '20110418',
},
}
'params': {
'skip_download': True, # requires ffmpeg
}
}, {
'url': 'http://www.discovery.com/tv-shows/mythbusters/videos/mythbusters-the-simpsons',
'info_dict': {
'id': 'mythbusters-the-simpsons',
'title': 'MythBusters: The Simpsons',
},
'playlist_count': 9,
}]
def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
info = self._download_json(url + '?flat=1', video_id)
info = self._parse_json(self._search_regex(
r'(?s)<script type="application/ld\+json">(.*?)</script>',
webpage, 'video info'), video_id)
video_title = info.get('playlist_title') or info.get('video_title')
return {
'id': video_id,
'title': info['name'],
'url': info['contentURL'],
'description': info.get('description'),
'thumbnail': info.get('thumbnailUrl'),
'timestamp': parse_iso8601(info.get('uploadDate')),
'duration': int_or_none(info.get('duration')),
}
entries = [{
'id': compat_str(video_info['id']),
'formats': self._extract_m3u8_formats(
video_info['src'], video_id, ext='mp4',
note='Download m3u8 information for video %d' % (idx + 1)),
'title': video_info['title'],
'description': video_info.get('description'),
'duration': parse_duration(video_info.get('video_length')),
'webpage_url': video_info.get('href'),
'thumbnail': video_info.get('thumbnailURL'),
'alt_title': video_info.get('secondary_title'),
'timestamp': parse_iso8601(video_info.get('publishedDate')),
} for idx, video_info in enumerate(info['playlist'])]
return self.playlist_result(entries, video_id, video_title)

View File

@@ -0,0 +1,197 @@
# encoding: utf-8
from __future__ import unicode_literals
import itertools
from .common import InfoExtractor
from ..compat import (
compat_HTTPError,
compat_urllib_parse,
compat_urllib_request,
compat_urlparse,
)
from ..utils import (
ExtractorError,
clean_html,
determine_ext,
int_or_none,
parse_iso8601,
)
class DramaFeverBaseIE(InfoExtractor):
_LOGIN_URL = 'https://www.dramafever.com/accounts/login/'
_NETRC_MACHINE = 'dramafever'
def _real_initialize(self):
self._login()
def _login(self):
(username, password) = self._get_login_info()
if username is None:
return
login_form = {
'username': username,
'password': password,
}
request = compat_urllib_request.Request(
self._LOGIN_URL, compat_urllib_parse.urlencode(login_form).encode('utf-8'))
response = self._download_webpage(
request, None, 'Logging in as %s' % username)
if all(logout_pattern not in response
for logout_pattern in ['href="/accounts/logout/"', '>Log out<']):
error = self._html_search_regex(
r'(?s)class="hidden-xs prompt"[^>]*>(.+?)<',
response, 'error message', default=None)
if error:
raise ExtractorError('Unable to login: %s' % error, expected=True)
raise ExtractorError('Unable to log in')
class DramaFeverIE(DramaFeverBaseIE):
IE_NAME = 'dramafever'
_VALID_URL = r'https?://(?:www\.)?dramafever\.com/drama/(?P<id>[0-9]+/[0-9]+)(?:/|$)'
_TEST = {
'url': 'http://www.dramafever.com/drama/4512/1/Cooking_with_Shin/',
'info_dict': {
'id': '4512.1',
'ext': 'flv',
'title': 'Cooking with Shin 4512.1',
'description': 'md5:a8eec7942e1664a6896fcd5e1287bfd0',
'thumbnail': 're:^https?://.*\.jpg',
'timestamp': 1404336058,
'upload_date': '20140702',
'duration': 343,
}
}
def _real_extract(self, url):
video_id = self._match_id(url).replace('/', '.')
try:
feed = self._download_json(
'http://www.dramafever.com/amp/episode/feed.json?guid=%s' % video_id,
video_id, 'Downloading episode JSON')['channel']['item']
except ExtractorError as e:
if isinstance(e.cause, compat_HTTPError):
raise ExtractorError(
'Currently unavailable in your country.', expected=True)
raise
media_group = feed.get('media-group', {})
formats = []
for media_content in media_group['media-content']:
src = media_content.get('@attributes', {}).get('url')
if not src:
continue
ext = determine_ext(src)
if ext == 'f4m':
formats.extend(self._extract_f4m_formats(
src, video_id, f4m_id='hds'))
elif ext == 'm3u8':
formats.extend(self._extract_m3u8_formats(
src, video_id, 'mp4', m3u8_id='hls'))
else:
formats.append({
'url': src,
})
self._sort_formats(formats)
title = media_group.get('media-title')
description = media_group.get('media-description')
duration = int_or_none(media_group['media-content'][0].get('@attributes', {}).get('duration'))
thumbnail = self._proto_relative_url(
media_group.get('media-thumbnail', {}).get('@attributes', {}).get('url'))
timestamp = parse_iso8601(feed.get('pubDate'), ' ')
subtitles = {}
for media_subtitle in media_group.get('media-subTitle', []):
lang = media_subtitle.get('@attributes', {}).get('lang')
href = media_subtitle.get('@attributes', {}).get('href')
if not lang or not href:
continue
subtitles[lang] = [{
'ext': 'ttml',
'url': href,
}]
return {
'id': video_id,
'title': title,
'description': description,
'thumbnail': thumbnail,
'timestamp': timestamp,
'duration': duration,
'formats': formats,
'subtitles': subtitles,
}
class DramaFeverSeriesIE(DramaFeverBaseIE):
IE_NAME = 'dramafever:series'
_VALID_URL = r'https?://(?:www\.)?dramafever\.com/drama/(?P<id>[0-9]+)(?:/(?:(?!\d+(?:/|$)).+)?)?$'
_TESTS = [{
'url': 'http://www.dramafever.com/drama/4512/Cooking_with_Shin/',
'info_dict': {
'id': '4512',
'title': 'Cooking with Shin',
'description': 'md5:84a3f26e3cdc3fb7f500211b3593b5c1',
},
'playlist_count': 4,
}, {
'url': 'http://www.dramafever.com/drama/124/IRIS/',
'info_dict': {
'id': '124',
'title': 'IRIS',
'description': 'md5:b3a30e587cf20c59bd1c01ec0ee1b862',
},
'playlist_count': 20,
}]
_CONSUMER_SECRET = 'DA59dtVXYLxajktV'
_PAGE_SIZE = 60 # max is 60 (see http://api.drama9.com/#get--api-4-episode-series-)
def _get_consumer_secret(self, video_id):
mainjs = self._download_webpage(
'http://www.dramafever.com/static/51afe95/df2014/scripts/main.js',
video_id, 'Downloading main.js', fatal=False)
if not mainjs:
return self._CONSUMER_SECRET
return self._search_regex(
r"var\s+cs\s*=\s*'([^']+)'", mainjs,
'consumer secret', default=self._CONSUMER_SECRET)
def _real_extract(self, url):
series_id = self._match_id(url)
consumer_secret = self._get_consumer_secret(series_id)
series = self._download_json(
'http://www.dramafever.com/api/4/series/query/?cs=%s&series_id=%s'
% (consumer_secret, series_id),
series_id, 'Downloading series JSON')['series'][series_id]
title = clean_html(series['name'])
description = clean_html(series.get('description') or series.get('description_short'))
entries = []
for page_num in itertools.count(1):
episodes = self._download_json(
'http://www.dramafever.com/api/4/episode/series/?cs=%s&series_id=%s&page_size=%d&page_number=%d'
% (consumer_secret, series_id, self._PAGE_SIZE, page_num),
series_id, 'Downloading episodes JSON page #%d' % page_num)
for episode in episodes.get('value', []):
episode_url = episode.get('episode_url')
if not episode_url:
continue
entries.append(self.url_result(
compat_urlparse.urljoin(url, episode_url),
'DramaFever', episode.get('guid')))
if page_num == episodes['num_pages']:
break
return self.playlist_result(entries, series_id, title, description)

View File

@@ -15,7 +15,6 @@ class DRBonanzaIE(InfoExtractor):
_TESTS = [{
'url': 'http://www.dr.dk/bonanza/serie/portraetter/Talkshowet.htm?assetId=65517',
'md5': 'fe330252ddea607635cf2eb2c99a0af3',
'info_dict': {
'id': '65517',
'ext': 'mp4',
@@ -26,6 +25,9 @@ class DRBonanzaIE(InfoExtractor):
'upload_date': '20110120',
'duration': 3664,
},
'params': {
'skip_download': True, # requires rtmp
},
}, {
'url': 'http://www.dr.dk/bonanza/radio/serie/sport/fodbold.htm?assetId=59410',
'md5': '6dfe039417e76795fb783c52da3de11d',
@@ -93,6 +95,11 @@ class DRBonanzaIE(InfoExtractor):
'format_id': file['Type'].replace('Video', ''),
'preference': preferencemap.get(file['Type'], -10),
})
if format['url'].startswith('rtmp'):
rtmp_url = format['url']
format['rtmp_live'] = True # --resume does not work
if '/bonanza/' in rtmp_url:
format['play_path'] = rtmp_url.split('/bonanza/')[1]
formats.append(format)
elif file['Type'] == "Thumb":
thumbnail = file['Location']
@@ -111,9 +118,6 @@ class DRBonanzaIE(InfoExtractor):
description = '%s\n%s\n%s\n' % (
info['Description'], info['Actors'], info['Colophon'])
for f in formats:
f['url'] = f['url'].replace('rtmp://vod-bonanza.gss.dr.dk/bonanza/', 'http://vodfiles.dr.dk/')
f['url'] = f['url'].replace('mp4:bonanza', 'bonanza')
self._sort_formats(formats)
display_id = re.sub(r'[^\w\d-]', '', re.sub(r' ', '-', title.lower())) + '-' + asset_id

View File

@@ -11,19 +11,25 @@ from ..utils import (
class DreiSatIE(InfoExtractor):
IE_NAME = '3sat'
_VALID_URL = r'(?:http://)?(?:www\.)?3sat\.de/mediathek/(?:index\.php)?\?(?:(?:mode|display)=[^&]+&)*obj=(?P<id>[0-9]+)$'
_TEST = {
'url': 'http://www.3sat.de/mediathek/index.php?mode=play&obj=45918',
'md5': 'be37228896d30a88f315b638900a026e',
'info_dict': {
'id': '45918',
'ext': 'mp4',
'title': 'Waidmannsheil',
'description': 'md5:cce00ca1d70e21425e72c86a98a56817',
'uploader': '3sat',
'upload_date': '20140913'
}
}
_VALID_URL = r'(?:http://)?(?:www\.)?3sat\.de/mediathek/(?:index\.php|mediathek\.php)?\?(?:(?:mode|display)=[^&]+&)*obj=(?P<id>[0-9]+)$'
_TESTS = [
{
'url': 'http://www.3sat.de/mediathek/index.php?mode=play&obj=45918',
'md5': 'be37228896d30a88f315b638900a026e',
'info_dict': {
'id': '45918',
'ext': 'mp4',
'title': 'Waidmannsheil',
'description': 'md5:cce00ca1d70e21425e72c86a98a56817',
'uploader': '3sat',
'upload_date': '20140913'
}
},
{
'url': 'http://www.3sat.de/mediathek/mediathek.php?mode=play&obj=51066',
'only_matching': True,
},
]
def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)

View File

@@ -36,25 +36,24 @@ class DrTuberIE(InfoExtractor):
r'<source src="([^"]+)"', webpage, 'video URL')
title = self._html_search_regex(
[r'class="hd_title" style="[^"]+">([^<]+)</h1>', r'<title>([^<]+) - \d+'],
[r'<p[^>]+class="title_substrate">([^<]+)</p>', r'<title>([^<]+) - \d+'],
webpage, 'title')
thumbnail = self._html_search_regex(
r'poster="([^"]+)"',
webpage, 'thumbnail', fatal=False)
like_count = str_to_int(self._html_search_regex(
r'<span id="rate_likes">\s*<img[^>]+>\s*<span>([\d,\.]+)</span>',
webpage, 'like count', fatal=False))
dislike_count = str_to_int(self._html_search_regex(
r'<span id="rate_dislikes">\s*<img[^>]+>\s*<span>([\d,\.]+)</span>',
webpage, 'like count', fatal=False))
comment_count = str_to_int(self._html_search_regex(
r'<span class="comments_count">([\d,\.]+)</span>',
webpage, 'comment count', fatal=False))
def extract_count(id_, name):
return str_to_int(self._html_search_regex(
r'<span[^>]+(?:class|id)="%s"[^>]*>([\d,\.]+)</span>' % id_,
webpage, '%s count' % name, fatal=False))
like_count = extract_count('rate_likes', 'like')
dislike_count = extract_count('rate_dislikes', 'dislike')
comment_count = extract_count('comments_count', 'comment')
cats_str = self._search_regex(
r'<span>Categories:</span><div>(.+?)</div>', webpage, 'categories', fatal=False)
r'<div[^>]+class="categories_list">(.+?)</div>', webpage, 'categories', fatal=False)
categories = [] if not cats_str else re.findall(r'<a title="([^"]+)"', cats_str)
return {

View File

@@ -1,8 +1,11 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor, ExtractorError
from ..utils import parse_iso8601
from .common import InfoExtractor
from ..utils import (
ExtractorError,
parse_iso8601,
)
class DRTVIE(InfoExtractor):
@@ -60,19 +63,31 @@ class DRTVIE(InfoExtractor):
restricted_to_denmark = asset['RestrictedToDenmark']
spoken_subtitles = asset['Target'] == 'SpokenSubtitles'
for link in asset['Links']:
target = link['Target']
uri = link['Uri']
target = link['Target']
format_id = target
preference = -1 if target == 'HDS' else -2
preference = None
if spoken_subtitles:
preference -= 2
preference = -1
format_id += '-spoken-subtitles'
formats.append({
'url': uri + '?hdcore=3.3.0&plugin=aasp-3.3.0.99.43' if target == 'HDS' else uri,
'format_id': format_id,
'ext': link['FileFormat'],
'preference': preference,
})
if target == 'HDS':
formats.extend(self._extract_f4m_formats(
uri + '?hdcore=3.3.0&plugin=aasp-3.3.0.99.43',
video_id, preference, f4m_id=format_id))
elif target == 'HLS':
formats.extend(self._extract_m3u8_formats(
uri, video_id, 'mp4', preference=preference,
m3u8_id=format_id))
else:
bitrate = link.get('Bitrate')
if bitrate:
format_id += '-%s' % bitrate
formats.append({
'url': uri,
'format_id': format_id,
'tbr': bitrate,
'ext': link.get('FileFormat'),
})
subtitles_list = asset.get('SubtitlesList')
if isinstance(subtitles_list, list):
LANGS = {

View File

@@ -26,7 +26,7 @@ class DumpertIE(InfoExtractor):
video_id = self._match_id(url)
req = compat_urllib_request.Request(url)
req.add_header('Cookie', 'nsfw=1')
req.add_header('Cookie', 'nsfw=1; cpc=10')
webpage = self._download_webpage(req, video_id)
files_base64 = self._search_regex(

View File

@@ -1,25 +0,0 @@
from __future__ import unicode_literals
from .tnaflix import TNAFlixIE
class EMPFlixIE(TNAFlixIE):
_VALID_URL = r'^https?://www\.empflix\.com/videos/(?P<display_id>[0-9a-zA-Z-]+)-(?P<id>[0-9]+)\.html'
_TITLE_REGEX = r'name="title" value="(?P<title>[^"]*)"'
_DESCRIPTION_REGEX = r'name="description" value="([^"]*)"'
_CONFIG_REGEX = r'flashvars\.config\s*=\s*escape\("([^"]+)"'
_TEST = {
'url': 'http://www.empflix.com/videos/Amateur-Finger-Fuck-33051.html',
'md5': 'b1bc15b6412d33902d6e5952035fcabc',
'info_dict': {
'id': '33051',
'display_id': 'Amateur-Finger-Fuck',
'ext': 'mp4',
'title': 'Amateur Finger Fuck',
'description': 'Amateur solo finger fucking.',
'thumbnail': 're:https?://.*\.jpg$',
'age_limit': 18,
}
}

View File

@@ -4,7 +4,10 @@ import re
from .common import InfoExtractor
from ..compat import compat_urllib_parse
from ..utils import ExtractorError
from ..utils import (
ExtractorError,
unescapeHTML
)
class EroProfileIE(InfoExtractor):
@@ -75,8 +78,8 @@ class EroProfileIE(InfoExtractor):
[r"glbUpdViews\s*\('\d*','(\d+)'", r'p/report/video/(\d+)'],
webpage, 'video id', default=None)
video_url = self._search_regex(
r'<source src="([^"]+)', webpage, 'video url')
video_url = unescapeHTML(self._search_regex(
r'<source src="([^"]+)', webpage, 'video url'))
title = self._html_search_regex(
r'Title:</th><td>([^<]+)</td>', webpage, 'title')
thumbnail = self._search_regex(

View File

@@ -1,128 +1,107 @@
from __future__ import unicode_literals
import json
from .common import InfoExtractor
from ..compat import (
compat_urllib_parse,
compat_urllib_request,
)
from ..compat import compat_urllib_request
from ..utils import (
ExtractorError,
js_to_json,
parse_duration,
determine_ext,
clean_html,
int_or_none,
float_or_none,
)
def _decrypt_config(key, string):
a = ''
i = ''
r = ''
while len(a) < (len(string) / 2):
a += key
a = a[0:int(len(string) / 2)]
t = 0
while t < len(string):
i += chr(int(string[t] + string[t + 1], 16))
t += 2
icko = [s for s in i]
for t, c in enumerate(a):
r += chr(ord(c) ^ ord(icko[t]))
return r
class EscapistIE(InfoExtractor):
_VALID_URL = r'https?://?(www\.)?escapistmagazine\.com/videos/view/[^/?#]+/(?P<id>[0-9]+)-[^/?#]*(?:$|[?#])'
_USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko'
_TEST = {
_VALID_URL = r'https?://?(?:www\.)?escapistmagazine\.com/videos/view/[^/?#]+/(?P<id>[0-9]+)-[^/?#]*(?:$|[?#])'
_TESTS = [{
'url': 'http://www.escapistmagazine.com/videos/view/the-escapist-presents/6618-Breaking-Down-Baldurs-Gate',
'md5': 'ab3a706c681efca53f0a35f1415cf0d1',
'info_dict': {
'id': '6618',
'ext': 'mp4',
'description': "Baldur's Gate: Original, Modded or Enhanced Edition? I'll break down what you can expect from the new Baldur's Gate: Enhanced Edition.",
'uploader_id': 'the-escapist-presents',
'uploader': 'The Escapist Presents',
'title': "Breaking Down Baldur's Gate",
'thumbnail': 're:^https?://.*\.jpg$',
'duration': 264,
'uploader': 'The Escapist',
}
}
}, {
'url': 'http://www.escapistmagazine.com/videos/view/zero-punctuation/10044-Evolve-One-vs-Multiplayer',
'md5': '9e8c437b0dbb0387d3bd3255ca77f6bf',
'info_dict': {
'id': '10044',
'ext': 'mp4',
'description': 'This week, Zero Punctuation reviews Evolve.',
'title': 'Evolve - One vs Multiplayer',
'thumbnail': 're:^https?://.*\.jpg$',
'duration': 304,
'uploader': 'The Escapist',
}
}]
def _real_extract(self, url):
video_id = self._match_id(url)
webpage_req = compat_urllib_request.Request(url)
webpage_req.add_header('User-Agent', self._USER_AGENT)
webpage = self._download_webpage(webpage_req, video_id)
webpage = self._download_webpage(url, video_id)
uploader_id = self._html_search_regex(
r"<h1\s+class='headline'>\s*<a\s+href='/videos/view/(.*?)'",
webpage, 'uploader ID', fatal=False)
uploader = self._html_search_regex(
r"<h1\s+class='headline'>(.*?)</a>",
webpage, 'uploader', fatal=False)
description = self._html_search_meta('description', webpage)
duration = parse_duration(self._html_search_meta('duration', webpage))
ims_video = self._parse_json(
self._search_regex(
r'imsVideo\.play\(({.+?})\);', webpage, 'imsVideo'),
video_id)
video_id = ims_video['videoID']
key = ims_video['hash']
raw_title = self._html_search_meta('title', webpage, fatal=True)
title = raw_title.partition(' : ')[2]
config_req = compat_urllib_request.Request(
'http://www.escapistmagazine.com/videos/'
'vidconfig.php?videoID=%s&hash=%s' % (video_id, key))
config_req.add_header('Referer', url)
config = self._download_webpage(config_req, video_id, 'Downloading video config')
config_url = compat_urllib_parse.unquote(self._html_search_regex(
r'''(?x)
(?:
<param\s+name="flashvars".*?\s+value="config=|
flashvars=&quot;config=
)
(https?://[^"&]+)
''',
webpage, 'config URL'))
data = json.loads(_decrypt_config(key, config))
formats = []
ad_formats = []
video_data = data['videoData']
def _add_format(name, cfg_url, quality):
cfg_req = compat_urllib_request.Request(cfg_url)
cfg_req.add_header('User-Agent', self._USER_AGENT)
config = self._download_json(
cfg_req, video_id,
'Downloading ' + name + ' configuration',
'Unable to download ' + name + ' configuration',
transform_source=js_to_json)
title = clean_html(video_data['title'])
duration = float_or_none(video_data.get('duration'), 1000)
uploader = video_data.get('publisher')
playlist = config['playlist']
for p in playlist:
if p.get('eventCategory') == 'Video':
ar = formats
elif p.get('eventCategory') == 'Video Postroll':
ar = ad_formats
else:
continue
ar.append({
'url': p['url'],
'format_id': name,
'quality': quality,
'http_headers': {
'User-Agent': self._USER_AGENT,
},
})
_add_format('normal', config_url, quality=0)
hq_url = (config_url +
('&hq=1' if '?' in config_url else config_url + '?hq=1'))
try:
_add_format('hq', hq_url, quality=1)
except ExtractorError:
pass # That's fine, we'll just use normal quality
formats = [{
'url': video['src'],
'format_id': '%s-%sp' % (determine_ext(video['src']), video['res']),
'height': int_or_none(video.get('res')),
} for video in data['files']['videos']]
self._sort_formats(formats)
if '/escapist/sales-marketing/' in formats[-1]['url']:
raise ExtractorError('This IP address has been blocked by The Escapist', expected=True)
res = {
return {
'id': video_id,
'formats': formats,
'uploader': uploader,
'uploader_id': uploader_id,
'title': title,
'thumbnail': self._og_search_thumbnail(webpage),
'description': description,
'description': self._og_search_description(webpage),
'duration': duration,
'uploader': uploader,
}
if self._downloader.params.get('include_ads') and ad_formats:
self._sort_formats(ad_formats)
ad_res = {
'id': '%s-ad' % video_id,
'title': '%s (Postroll)' % title,
'formats': ad_formats,
}
return {
'_type': 'playlist',
'entries': [res, ad_res],
'title': title,
'id': video_id,
}
return res

View File

@@ -0,0 +1,55 @@
from __future__ import unicode_literals
from .common import InfoExtractor
class ESPNIE(InfoExtractor):
_VALID_URL = r'https?://espn\.go\.com/(?:[^/]+/)*(?P<id>[^/]+)'
_WORKING = False
_TESTS = [{
'url': 'http://espn.go.com/video/clip?id=10365079',
'info_dict': {
'id': 'FkYWtmazr6Ed8xmvILvKLWjd4QvYZpzG',
'ext': 'mp4',
'title': 'dm_140128_30for30Shorts___JudgingJewellv2',
'description': '',
},
'params': {
# m3u8 download
'skip_download': True,
},
}, {
'url': 'https://espn.go.com/video/iframe/twitter/?cms=espn&id=10365079',
'only_matching': True,
}, {
'url': 'http://espn.go.com/nba/recap?gameId=400793786',
'only_matching': True,
}, {
'url': 'http://espn.go.com/blog/golden-state-warriors/post/_/id/593/how-warriors-rapidly-regained-a-winning-edge',
'only_matching': True,
}, {
'url': 'http://espn.go.com/sports/endurance/story/_/id/12893522/dzhokhar-tsarnaev-sentenced-role-boston-marathon-bombings',
'only_matching': True,
}, {
'url': 'http://espn.go.com/nba/playoffs/2015/story/_/id/12887571/john-wall-washington-wizards-no-swelling-left-hand-wrist-game-5-return',
'only_matching': True,
}]
def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
video_id = self._search_regex(
r'class="video-play-button"[^>]+data-id="(\d+)',
webpage, 'video id')
player = self._download_webpage(
'https://espn.go.com/video/iframe/twitter/?id=%s' % video_id, video_id)
pcode = self._search_regex(
r'["\']pcode=([^"\']+)["\']', player, 'pcode')
return self.url_result(
'ooyalaexternal:espn:%s:%s' % (video_id, pcode),
'OoyalaExternal')

View File

@@ -50,7 +50,10 @@ class FacebookIE(InfoExtractor):
'id': '274175099429670',
'ext': 'mp4',
'title': 'Facebook video #274175099429670',
}
},
'expected_warnings': [
'title'
]
}, {
'url': 'https://www.facebook.com/video.php?v=10204634152394104',
'only_matching': True,
@@ -149,12 +152,12 @@ class FacebookIE(InfoExtractor):
raise ExtractorError('Cannot find video formats')
video_title = self._html_search_regex(
r'<h2 class="uiHeaderTitle">([^<]*)</h2>', webpage, 'title',
fatal=False)
r'<h2\s+[^>]*class="uiHeaderTitle"[^>]*>([^<]*)</h2>', webpage, 'title',
default=None)
if not video_title:
video_title = self._html_search_regex(
r'(?s)<span class="fbPhotosPhotoCaption".*?id="fbPhotoPageCaption"><span class="hasCaption">(.*?)</span>',
webpage, 'alternative title', default=None)
webpage, 'alternative title', fatal=False)
video_title = limit_length(video_title, 80)
if not video_title:
video_title = 'Facebook video #%s' % video_id

View File

@@ -6,9 +6,9 @@ from .common import InfoExtractor
class FazIE(InfoExtractor):
IE_NAME = 'faz.net'
_VALID_URL = r'https?://www\.faz\.net/multimedia/videos/.*?-(?P<id>\d+)\.html'
_VALID_URL = r'https?://(?:www\.)?faz\.net/(?:[^/]+/)*.*?-(?P<id>\d+)\.html'
_TEST = {
_TESTS = [{
'url': 'http://www.faz.net/multimedia/videos/stockholm-chemie-nobelpreis-fuer-drei-amerikanische-forscher-12610585.html',
'info_dict': {
'id': '12610585',
@@ -16,7 +16,22 @@ class FazIE(InfoExtractor):
'title': 'Stockholm: Chemie-Nobelpreis für drei amerikanische Forscher',
'description': 'md5:1453fbf9a0d041d985a47306192ea253',
},
}
}, {
'url': 'http://www.faz.net/aktuell/politik/berlin-gabriel-besteht-zerreissprobe-ueber-datenspeicherung-13659345.html',
'only_matching': True,
}, {
'url': 'http://www.faz.net/berlin-gabriel-besteht-zerreissprobe-ueber-datenspeicherung-13659345.html',
'only_matching': True,
}, {
'url': 'http://www.faz.net/-13659345.html',
'only_matching': True,
}, {
'url': 'http://www.faz.net/aktuell/politik/-13659345.html',
'only_matching': True,
}, {
'url': 'http://www.faz.net/foobarblafasel-13659345.html',
'only_matching': True,
}]
def _real_extract(self, url):
video_id = self._match_id(url)

View File

@@ -1,80 +0,0 @@
# coding: utf-8
from __future__ import unicode_literals
import re
from .common import InfoExtractor
from ..compat import (
compat_urllib_parse,
compat_urllib_request,
)
from ..utils import (
ExtractorError,
)
class FiredriveIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?firedrive\.com/' + \
'(?:file|embed)/(?P<id>[0-9a-zA-Z]+)'
_FILE_DELETED_REGEX = r'<div class="removed_file_image">'
_TESTS = [{
'url': 'https://www.firedrive.com/file/FEB892FA160EBD01',
'md5': 'd5d4252f80ebeab4dc2d5ceaed1b7970',
'info_dict': {
'id': 'FEB892FA160EBD01',
'ext': 'flv',
'title': 'bbb_theora_486kbit.flv',
'thumbnail': 're:^http://.*\.jpg$',
},
}]
def _real_extract(self, url):
video_id = self._match_id(url)
url = 'http://firedrive.com/file/%s' % video_id
webpage = self._download_webpage(url, video_id)
if re.search(self._FILE_DELETED_REGEX, webpage) is not None:
raise ExtractorError('Video %s does not exist' % video_id,
expected=True)
fields = dict(re.findall(r'''(?x)<input\s+
type="hidden"\s+
name="([^"]+)"\s+
value="([^"]*)"
''', webpage))
post = compat_urllib_parse.urlencode(fields)
req = compat_urllib_request.Request(url, post)
req.add_header('Content-type', 'application/x-www-form-urlencoded')
# Apparently, this header is required for confirmation to work.
req.add_header('Host', 'www.firedrive.com')
webpage = self._download_webpage(req, video_id,
'Downloading video page')
title = self._search_regex(r'class="external_title_left">(.+)</div>',
webpage, 'title')
thumbnail = self._search_regex(r'image:\s?"(//[^\"]+)', webpage,
'thumbnail', fatal=False)
if thumbnail is not None:
thumbnail = 'http:' + thumbnail
ext = self._search_regex(r'type:\s?\'([^\']+)\',',
webpage, 'extension', fatal=False)
video_url = self._search_regex(
r'file:\s?loadURL\(\'(http[^\']+)\'\),', webpage, 'file url')
formats = [{
'format_id': 'sd',
'url': video_url,
'ext': ext,
}]
return {
'id': video_id,
'title': title,
'thumbnail': thumbnail,
'formats': formats,
}

View File

@@ -0,0 +1,88 @@
# coding: utf-8
from __future__ import unicode_literals
import re
from .common import InfoExtractor
from ..utils import int_or_none
class FiveTVIE(InfoExtractor):
_VALID_URL = r'''(?x)
http://
(?:www\.)?5-tv\.ru/
(?:
(?:[^/]+/)+(?P<id>\d+)|
(?P<path>[^/?#]+)(?:[/?#])?
)
'''
_TESTS = [{
'url': 'http://5-tv.ru/news/96814/',
'md5': 'bbff554ad415ecf5416a2f48c22d9283',
'info_dict': {
'id': '96814',
'ext': 'mp4',
'title': 'Россияне выбрали имя для общенациональной платежной системы',
'description': 'md5:a8aa13e2b7ad36789e9f77a74b6de660',
'thumbnail': 're:^https?://.*\.jpg$',
'duration': 180,
},
}, {
'url': 'http://5-tv.ru/video/1021729/',
'info_dict': {
'id': '1021729',
'ext': 'mp4',
'title': '3D принтер',
'description': 'md5:d76c736d29ef7ec5c0cf7d7c65ffcb41',
'thumbnail': 're:^https?://.*\.jpg$',
'duration': 180,
},
}, {
'url': 'http://www.5-tv.ru/glavnoe/#itemDetails',
'info_dict': {
'id': 'glavnoe',
'ext': 'mp4',
'title': 'Итоги недели с 8 по 14 июня 2015 года',
'thumbnail': 're:^https?://.*\.jpg$',
},
}, {
'url': 'http://www.5-tv.ru/glavnoe/broadcasts/508645/',
'only_matching': True,
}, {
'url': 'http://5-tv.ru/films/1507502/',
'only_matching': True,
}, {
'url': 'http://5-tv.ru/programs/broadcast/508713/',
'only_matching': True,
}, {
'url': 'http://5-tv.ru/angel/',
'only_matching': True,
}, {
'url': 'http://www.5-tv.ru/schedule/?iframe=true&width=900&height=450',
'only_matching': True,
}]
def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)
video_id = mobj.group('id') or mobj.group('path')
webpage = self._download_webpage(url, video_id)
video_url = self._search_regex(
r'<a[^>]+?href="([^"]+)"[^>]+?class="videoplayer"',
webpage, 'video url')
title = self._og_search_title(webpage, default=None) or self._search_regex(
r'<title>([^<]+)</title>', webpage, 'title')
duration = int_or_none(self._og_search_property(
'video:duration', webpage, 'duration', default=None))
return {
'id': video_id,
'url': video_url,
'title': title,
'description': self._og_search_description(webpage, default=None),
'thumbnail': self._og_search_thumbnail(webpage, default=None),
'duration': duration,
}

View File

@@ -0,0 +1,32 @@
from __future__ import unicode_literals
from .common import InfoExtractor
from ..utils import smuggle_url
class FoxSportsIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?foxsports\.com/(?:[^/]+/)*(?P<id>[^/]+)'
_TEST = {
'url': 'http://www.foxsports.com/video?vid=432609859715',
'info_dict': {
'id': 'gA0bHB3Ladz3',
'ext': 'flv',
'title': 'Courtney Lee on going up 2-0 in series vs. Blazers',
'description': 'Courtney Lee talks about Memphis being focused.',
},
'add_ie': ['ThePlatform'],
}
def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
config = self._parse_json(
self._search_regex(
r"data-player-config='([^']+)'", webpage, 'data player config'),
video_id)
return self.url_result(smuggle_url(
config['releaseURL'] + '&manifest=f4m', {'force_smil_url': True}))

View File

@@ -18,6 +18,7 @@ from ..utils import (
parse_duration,
determine_ext,
)
from .dailymotion import DailymotionCloudIE
class FranceTVBaseInfoExtractor(InfoExtractor):
@@ -60,7 +61,7 @@ class FranceTVBaseInfoExtractor(InfoExtractor):
continue
video_url_parsed = compat_urllib_parse_urlparse(video_url)
f4m_url = self._download_webpage(
'http://hdfauth.francetv.fr/esi/urltokengen2.html?url=%s' % video_url_parsed.path,
'http://hdfauth.francetv.fr/esi/TA?url=%s' % video_url_parsed.path,
video_id, 'Downloading f4m manifest token', fatal=False)
if f4m_url:
formats.extend(self._extract_f4m_formats(f4m_url, video_id, 1, format_id))
@@ -131,12 +132,26 @@ class FranceTvInfoIE(FranceTVBaseInfoExtractor):
'skip_download': 'HLS (reqires ffmpeg)'
},
'skip': 'Ce direct est terminé et sera disponible en rattrapage dans quelques minutes.',
}, {
'url': 'http://www.francetvinfo.fr/economie/entreprises/les-entreprises-familiales-le-secret-de-la-reussite_933271.html',
'md5': 'f485bda6e185e7d15dbc69b72bae993e',
'info_dict': {
'id': '556e03339473995ee145930c',
'ext': 'mp4',
'title': 'Les entreprises familiales : le secret de la réussite',
'thumbnail': 're:^https?://.*\.jpe?g$',
}
}]
def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)
page_title = mobj.group('title')
webpage = self._download_webpage(url, page_title)
dmcloud_url = DailymotionCloudIE._extract_dmcloud_url(webpage)
if dmcloud_url:
return self.url_result(dmcloud_url, 'DailymotionCloud')
video_id, catalogue = self._search_regex(
r'id-video=([^@]+@[^"]+)', webpage, 'video id').split('@')
return self._extract_video(video_id, catalogue)

View File

@@ -14,8 +14,8 @@ from ..utils import (
class GameSpotIE(InfoExtractor):
_VALID_URL = r'(?:http://)?(?:www\.)?gamespot\.com/.*-(?P<id>\d+)/?'
_TEST = {
_VALID_URL = r'http://(?:www\.)?gamespot\.com/.*-(?P<id>\d+)/?'
_TESTS = [{
'url': 'http://www.gamespot.com/videos/arma-3-community-guide-sitrep-i/2300-6410818/',
'md5': 'b2a30deaa8654fcccd43713a6b6a4825',
'info_dict': {
@@ -23,8 +23,16 @@ class GameSpotIE(InfoExtractor):
'ext': 'mp4',
'title': 'Arma 3 - Community Guide: SITREP I',
'description': 'Check out this video where some of the basics of Arma 3 is explained.',
}
}
},
}, {
'url': 'http://www.gamespot.com/videos/the-witcher-3-wild-hunt-xbox-one-now-playing/2300-6424837/',
'info_dict': {
'id': 'gs-2300-6424837',
'ext': 'flv',
'title': 'The Witcher 3: Wild Hunt [Xbox ONE] - Now Playing',
'description': 'Join us as we take a look at the early hours of The Witcher 3: Wild Hunt and more.',
},
}]
def _real_extract(self, url):
page_id = self._match_id(url)
@@ -32,25 +40,37 @@ class GameSpotIE(InfoExtractor):
data_video_json = self._search_regex(
r'data-video=["\'](.*?)["\']', webpage, 'data video')
data_video = json.loads(unescapeHTML(data_video_json))
streams = data_video['videoStreams']
# Transform the manifest url to a link to the mp4 files
# they are used in mobile devices.
f4m_url = data_video['videoStreams']['f4m_stream']
f4m_path = compat_urlparse.urlparse(f4m_url).path
QUALITIES_RE = r'((,\d+)+,?)'
qualities = self._search_regex(QUALITIES_RE, f4m_path, 'qualities').strip(',').split(',')
http_path = f4m_path[1:].split('/', 1)[1]
http_template = re.sub(QUALITIES_RE, r'%s', http_path)
http_template = http_template.replace('.csmil/manifest.f4m', '')
http_template = compat_urlparse.urljoin(
'http://video.gamespotcdn.com/', http_template)
formats = []
for q in qualities:
formats.append({
'url': http_template % q,
'ext': 'mp4',
'format_id': q,
})
f4m_url = streams.get('f4m_stream')
if f4m_url is not None:
# Transform the manifest url to a link to the mp4 files
# they are used in mobile devices.
f4m_path = compat_urlparse.urlparse(f4m_url).path
QUALITIES_RE = r'((,\d+)+,?)'
qualities = self._search_regex(QUALITIES_RE, f4m_path, 'qualities').strip(',').split(',')
http_path = f4m_path[1:].split('/', 1)[1]
http_template = re.sub(QUALITIES_RE, r'%s', http_path)
http_template = http_template.replace('.csmil/manifest.f4m', '')
http_template = compat_urlparse.urljoin(
'http://video.gamespotcdn.com/', http_template)
for q in qualities:
formats.append({
'url': http_template % q,
'ext': 'mp4',
'format_id': q,
})
else:
for quality in ['sd', 'hd']:
# It's actually a link to a flv file
flv_url = streams.get('f4m_{0}'.format(quality))
if flv_url is not None:
formats.append({
'url': flv_url,
'ext': 'flv',
'format_id': quality,
})
return {
'id': data_video['guid'],

View File

@@ -9,6 +9,8 @@ from .common import InfoExtractor
from .youtube import YoutubeIE
from ..compat import (
compat_urllib_parse,
compat_urllib_parse_unquote,
compat_urllib_request,
compat_urlparse,
compat_xml_parse_error,
)
@@ -32,11 +34,20 @@ from .brightcove import BrightcoveIE
from .nbc import NBCSportsVPlayerIE
from .ooyala import OoyalaIE
from .rutv import RUTVIE
from .tvc import TVCIE
from .sportbox import SportBoxEmbedIE
from .smotri import SmotriIE
from .condenast import CondeNastIE
from .udn import UDNEmbedIE
from .senateisvp import SenateISVPIE
from .bliptv import BlipTVIE
from .svt import SVTIE
from .pornhub import PornHubIE
from .xhamster import XHamsterEmbedIE
from .vimeo import VimeoIE
from .dailymotion import DailymotionCloudIE
from .onionstudios import OnionStudiosIE
from .snagfilms import SnagFilmsEmbedIE
class GenericIE(InfoExtractor):
@@ -44,6 +55,97 @@ class GenericIE(InfoExtractor):
_VALID_URL = r'.*'
IE_NAME = 'generic'
_TESTS = [
# Direct link to a video
{
'url': 'http://media.w3.org/2010/05/sintel/trailer.mp4',
'md5': '67d406c2bcb6af27fa886f31aa934bbe',
'info_dict': {
'id': 'trailer',
'ext': 'mp4',
'title': 'trailer',
'upload_date': '20100513',
}
},
# Direct link to media delivered compressed (until Accept-Encoding is *)
{
'url': 'http://calimero.tk/muzik/FictionJunction-Parallel_Hearts.flac',
'md5': '128c42e68b13950268b648275386fc74',
'info_dict': {
'id': 'FictionJunction-Parallel_Hearts',
'ext': 'flac',
'title': 'FictionJunction-Parallel_Hearts',
'upload_date': '20140522',
},
'expected_warnings': [
'URL could be a direct video link, returning it as such.'
]
},
# Direct download with broken HEAD
{
'url': 'http://ai-radio.org:8000/radio.opus',
'info_dict': {
'id': 'radio',
'ext': 'opus',
'title': 'radio',
},
'params': {
'skip_download': True, # infinite live stream
},
'expected_warnings': [
r'501.*Not Implemented'
],
},
# Direct link with incorrect MIME type
{
'url': 'http://ftp.nluug.nl/video/nluug/2014-11-20_nj14/zaal-2/5_Lennart_Poettering_-_Systemd.webm',
'md5': '4ccbebe5f36706d85221f204d7eb5913',
'info_dict': {
'url': 'http://ftp.nluug.nl/video/nluug/2014-11-20_nj14/zaal-2/5_Lennart_Poettering_-_Systemd.webm',
'id': '5_Lennart_Poettering_-_Systemd',
'ext': 'webm',
'title': '5_Lennart_Poettering_-_Systemd',
'upload_date': '20141120',
},
'expected_warnings': [
'URL could be a direct video link, returning it as such.'
]
},
# RSS feed
{
'url': 'http://phihag.de/2014/youtube-dl/rss2.xml',
'info_dict': {
'id': 'http://phihag.de/2014/youtube-dl/rss2.xml',
'title': 'Zero Punctuation',
'description': 're:.*groundbreaking video review series.*'
},
'playlist_mincount': 11,
},
# RSS feed with enclosure
{
'url': 'http://podcastfeeds.nbcnews.com/audio/podcast/MSNBC-MADDOW-NETCAST-M4V.xml',
'info_dict': {
'id': 'pdv_maddow_netcast_m4v-02-27-2015-201624',
'ext': 'm4v',
'upload_date': '20150228',
'title': 'pdv_maddow_netcast_m4v-02-27-2015-201624',
}
},
# google redirect
{
'url': 'http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCUQtwIwAA&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DcmQHVoWB5FY&ei=F-sNU-LLCaXk4QT52ICQBQ&usg=AFQjCNEw4hL29zgOohLXvpJ-Bdh2bils1Q&bvm=bv.61965928,d.bGE',
'info_dict': {
'id': 'cmQHVoWB5FY',
'ext': 'mp4',
'upload_date': '20130224',
'uploader_id': 'TheVerge',
'description': 're:^Chris Ziegler takes a look at the\.*',
'uploader': 'The Verge',
'title': 'First Firefox OS phones side-by-side',
},
'params': {
'skip_download': False,
}
},
{
'url': 'http://www.hodiho.fr/2013/02/regis-plante-sa-jeep.html',
'md5': '85b90ccc9d73b4acd9138d3af4c27f89',
@@ -123,17 +225,6 @@ class GenericIE(InfoExtractor):
'skip_download': True, # m3u8 download
},
},
# Direct link to a video
{
'url': 'http://media.w3.org/2010/05/sintel/trailer.mp4',
'md5': '67d406c2bcb6af27fa886f31aa934bbe',
'info_dict': {
'id': 'trailer',
'ext': 'mp4',
'title': 'trailer',
'upload_date': '20100513',
}
},
# ooyala video
{
'url': 'http://www.rollingstone.com/music/videos/norwegian-dj-cashmere-cat-goes-spartan-on-with-me-premiere-20131219',
@@ -158,22 +249,6 @@ class GenericIE(InfoExtractor):
},
'add_ie': ['Ooyala'],
},
# google redirect
{
'url': 'http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCUQtwIwAA&url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DcmQHVoWB5FY&ei=F-sNU-LLCaXk4QT52ICQBQ&usg=AFQjCNEw4hL29zgOohLXvpJ-Bdh2bils1Q&bvm=bv.61965928,d.bGE',
'info_dict': {
'id': 'cmQHVoWB5FY',
'ext': 'mp4',
'upload_date': '20130224',
'uploader_id': 'TheVerge',
'description': 're:^Chris Ziegler takes a look at the\.*',
'uploader': 'The Verge',
'title': 'First Firefox OS phones side-by-side',
},
'params': {
'skip_download': False,
}
},
# embed.ly video
{
'url': 'http://www.tested.com/science/weird/460206-tested-grinding-coffee-2000-frames-second/',
@@ -223,6 +298,55 @@ class GenericIE(InfoExtractor):
'skip_download': True,
},
},
# TVC embed
{
'url': 'http://sch1298sz.mskobr.ru/dou_edu/karamel_ki/filial_galleries/video/iframe_src_http_tvc_ru_video_iframe_id_55304_isplay_false_acc_video_id_channel_brand_id_11_show_episodes_episode_id_32307_frameb/',
'info_dict': {
'id': '55304',
'ext': 'mp4',
'title': 'Дошкольное воспитание',
},
},
# SportBox embed
{
'url': 'http://www.vestifinance.ru/articles/25753',
'info_dict': {
'id': '25753',
'title': 'Вести Экономика ― Прямые трансляции с Форума-выставки "Госзаказ-2013"',
},
'playlist': [{
'info_dict': {
'id': '370908',
'title': 'Госзаказ. День 3',
'ext': 'mp4',
}
}, {
'info_dict': {
'id': '370905',
'title': 'Госзаказ. День 2',
'ext': 'mp4',
}
}, {
'info_dict': {
'id': '370902',
'title': 'Госзаказ. День 1',
'ext': 'mp4',
}
}],
'params': {
# m3u8 download
'skip_download': True,
},
},
# XHamster embed
{
'url': 'http://www.numisc.com/forum/showthread.php?11696-FM15-which-pumiscer-was-this-%28-vid-%29-%28-alfa-as-fuck-srx-%29&s=711f5db534502e22260dec8c5e2d66d8',
'info_dict': {
'id': 'showthread',
'title': '[NSFL] [FM15] which pumiscer was this ( vid ) ( alfa as fuck srx )',
},
'playlist_mincount': 7,
},
# Embedded TED video
{
'url': 'http://en.support.wordpress.com/videos/ted-talks/',
@@ -374,16 +498,6 @@ class GenericIE(InfoExtractor):
'title': 'Busty Blonde Siri Tit Fuck While Wank at HandjobHub.com',
}
},
# RSS feed
{
'url': 'http://phihag.de/2014/youtube-dl/rss2.xml',
'info_dict': {
'id': 'http://phihag.de/2014/youtube-dl/rss2.xml',
'title': 'Zero Punctuation',
'description': 're:.*groundbreaking video review series.*'
},
'playlist_mincount': 11,
},
# Multiple brightcove videos
# https://github.com/rg3/youtube-dl/issues/2283
{
@@ -437,21 +551,6 @@ class GenericIE(InfoExtractor):
'uploader': 'thoughtworks.wistia.com',
},
},
# Direct download with broken HEAD
{
'url': 'http://ai-radio.org:8000/radio.opus',
'info_dict': {
'id': 'radio',
'ext': 'opus',
'title': 'radio',
},
'params': {
'skip_download': True, # infinite live stream
},
'expected_warnings': [
r'501.*Not Implemented'
],
},
# Soundcloud embed
{
'url': 'http://nakedsecurity.sophos.com/2014/10/29/sscc-171-are-you-sure-that-1234-is-a-bad-password-podcast/',
@@ -483,21 +582,6 @@ class GenericIE(InfoExtractor):
},
'playlist_mincount': 2,
},
# Direct link with incorrect MIME type
{
'url': 'http://ftp.nluug.nl/video/nluug/2014-11-20_nj14/zaal-2/5_Lennart_Poettering_-_Systemd.webm',
'md5': '4ccbebe5f36706d85221f204d7eb5913',
'info_dict': {
'url': 'http://ftp.nluug.nl/video/nluug/2014-11-20_nj14/zaal-2/5_Lennart_Poettering_-_Systemd.webm',
'id': '5_Lennart_Poettering_-_Systemd',
'ext': 'webm',
'title': '5_Lennart_Poettering_-_Systemd',
'upload_date': '20141120',
},
'expected_warnings': [
'URL could be a direct video link, returning it as such.'
]
},
# Cinchcast embed
{
'url': 'http://undergroundwellness.com/podcasts/306-5-steps-to-permanent-gut-healing/',
@@ -585,6 +669,18 @@ class GenericIE(InfoExtractor):
'title': 'John Carlson Postgame 2/25/15',
},
},
# Kaltura embed (different embed code)
{
'url': 'http://www.premierchristianradio.com/Shows/Saturday/Unbelievable/Conference-Videos/Os-Guinness-Is-It-Fools-Talk-Unbelievable-Conference-2014',
'info_dict': {
'id': '1_a52wc67y',
'ext': 'flv',
'upload_date': '20150127',
'uploader_id': 'PremierMedia',
'timestamp': int,
'title': 'Os Guinness // Is It Fools Talk? // Unbelievable? Conference 2014',
},
},
# Eagle.Platform embed (generic URL)
{
'url': 'http://lenta.ru/news/2015/03/06/navalny/',
@@ -645,15 +741,16 @@ class GenericIE(InfoExtractor):
'title': 'Facebook Creates "On This Day" | Crunch Report',
},
},
# RSS feed with enclosure
# SVT embed
{
'url': 'http://podcastfeeds.nbcnews.com/audio/podcast/MSNBC-MADDOW-NETCAST-M4V.xml',
'url': 'http://www.svt.se/sport/ishockey/jagr-tacklar-giroux-under-intervjun',
'info_dict': {
'id': 'pdv_maddow_netcast_m4v-02-27-2015-201624',
'ext': 'm4v',
'upload_date': '20150228',
'title': 'pdv_maddow_netcast_m4v-02-27-2015-201624',
}
'id': '2900353',
'ext': 'flv',
'title': 'Här trycker Jagr till Giroux (under SVT-intervjun)',
'duration': 27,
'age_limit': 0,
},
},
# Crooks and Liars embed
{
@@ -729,6 +826,62 @@ class GenericIE(InfoExtractor):
# rtmpe downloads
'skip_download': True,
}
},
# Brightcove URL in single quotes
{
'url': 'http://www.sportsnet.ca/baseball/mlb/sn-presents-russell-martin-world-citizen/',
'md5': '4ae374f1f8b91c889c4b9203c8c752af',
'info_dict': {
'id': '4255764656001',
'ext': 'mp4',
'title': 'SN Presents: Russell Martin, World Citizen',
'description': 'To understand why he was the Toronto Blue Jays top off-season priority is to appreciate his background and upbringing in Montreal, where he first developed his baseball skills. Written and narrated by Stephen Brunt.',
'uploader': 'Rogers Sportsnet',
},
},
# Dailymotion Cloud video
{
'url': 'http://replay.publicsenat.fr/vod/le-debat/florent-kolandjian,dominique-cena,axel-decourtye,laurence-abeille,bruno-parmentier/175910',
'md5': '49444254273501a64675a7e68c502681',
'info_dict': {
'id': '5585de919473990de4bee11b',
'ext': 'mp4',
'title': 'Le débat',
'thumbnail': 're:^https?://.*\.jpe?g$',
}
},
# OnionStudios embed
{
'url': 'http://www.clickhole.com/video/dont-understand-bitcoin-man-will-mumble-explanatio-2537',
'info_dict': {
'id': '2855',
'ext': 'mp4',
'title': 'Dont Understand Bitcoin? This Man Will Mumble An Explanation At You',
'thumbnail': 're:^https?://.*\.jpe?g$',
'uploader': 'ClickHole',
'uploader_id': 'clickhole',
}
},
# SnagFilms embed
{
'url': 'http://whilewewatch.blogspot.ru/2012/06/whilewewatch-whilewewatch-gripping.html',
'info_dict': {
'id': '74849a00-85a9-11e1-9660-123139220831',
'ext': 'mp4',
'title': '#whilewewatch',
}
},
# AdobeTVVideo embed
{
'url': 'https://helpx.adobe.com/acrobat/how-to/new-experience-acrobat-dc.html?set=acrobat--get-started--essential-beginners',
'md5': '43662b577c018ad707a63766462b1e87',
'info_dict': {
'id': '2456',
'ext': 'mp4',
'title': 'New experience with Acrobat DC',
'description': 'New experience with Acrobat DC',
'duration': 248.667,
},
}
]
@@ -850,7 +1003,7 @@ class GenericIE(InfoExtractor):
force_videoid = smuggled_data['force_videoid']
video_id = force_videoid
else:
video_id = os.path.splitext(url.rstrip('/').split('/')[-1])[0]
video_id = compat_urllib_parse_unquote(os.path.splitext(url.rstrip('/').split('/')[-1])[0])
self.to_screen('%s: Requesting header' % video_id)
@@ -872,7 +1025,9 @@ class GenericIE(InfoExtractor):
full_response = None
if head_response is False:
full_response = self._request_webpage(url, video_id)
request = compat_urllib_request.Request(url)
request.add_header('Accept-Encoding', '*')
full_response = self._request_webpage(request, video_id)
head_response = full_response
# Check for direct link to a video
@@ -883,7 +1038,7 @@ class GenericIE(InfoExtractor):
head_response.headers.get('Last-Modified'))
return {
'id': video_id,
'title': os.path.splitext(url_basename(url))[0],
'title': compat_urllib_parse_unquote(os.path.splitext(url_basename(url))[0]),
'direct': True,
'formats': [{
'format_id': m.group('format_id'),
@@ -894,10 +1049,22 @@ class GenericIE(InfoExtractor):
}
if not self._downloader.params.get('test', False) and not is_intentional:
self._downloader.report_warning('Falling back on generic information extractor.')
force = self._downloader.params.get('force_generic_extractor', False)
self._downloader.report_warning(
'%s on generic information extractor.' % ('Forcing' if force else 'Falling back'))
if not full_response:
full_response = self._request_webpage(url, video_id)
request = compat_urllib_request.Request(url)
# Some webservers may serve compressed content of rather big size (e.g. gzipped flac)
# making it impossible to download only chunk of the file (yet we need only 512kB to
# test whether it's HTML or not). According to youtube-dl default Accept-Encoding
# that will always result in downloading the whole file that is not desirable.
# Therefore for extraction pass we have to override Accept-Encoding to any in order
# to accept raw bytes and being able to download only a chunk.
# It may probably better to solve this by checking Content-Type for application/octet-stream
# after HEAD request finishes, but not sure if we can rely on this.
request.add_header('Accept-Encoding', '*')
full_response = self._request_webpage(request, video_id)
# Maybe it's a direct link to a video?
# Be careful not to download the whole thing!
@@ -909,7 +1076,7 @@ class GenericIE(InfoExtractor):
head_response.headers.get('Last-Modified'))
return {
'id': video_id,
'title': os.path.splitext(url_basename(url))[0],
'title': compat_urllib_parse_unquote(os.path.splitext(url_basename(url))[0]),
'direct': True,
'url': url,
'upload_date': upload_date,
@@ -989,23 +1156,14 @@ class GenericIE(InfoExtractor):
# Look for embedded rtl.nl player
matches = re.findall(
r'<iframe\s+(?:[a-zA-Z-]+="[^"]+"\s+)*?src="((?:https?:)?//(?:www\.)?rtl\.nl/system/videoplayer/[^"]+video_embed[^"]+)"',
r'<iframe[^>]+?src="((?:https?:)?//(?:www\.)?rtl\.nl/system/videoplayer/[^"]+(?:video_)?embed[^"]+)"',
webpage)
if matches:
return _playlist_from_matches(matches, ie='RtlNl')
# Look for embedded (iframe) Vimeo player
mobj = re.search(
r'<iframe[^>]+?src=(["\'])(?P<url>(?:https?:)?//player\.vimeo\.com/video/.+?)\1', webpage)
if mobj:
player_url = unescapeHTML(mobj.group('url'))
surl = smuggle_url(player_url, {'Referer': url})
return self.url_result(surl)
# Look for embedded (swf embed) Vimeo player
mobj = re.search(
r'<embed[^>]+?src="((?:https?:)?//(?:www\.)?vimeo\.com/moogaloop\.swf.+?)"', webpage)
if mobj:
return self.url_result(mobj.group(1))
vimeo_url = VimeoIE._extract_vimeo_url(url, webpage)
if vimeo_url is not None:
return self.url_result(vimeo_url)
# Look for embedded YouTube player
matches = re.findall(r'''(?x)
@@ -1078,6 +1236,11 @@ class GenericIE(InfoExtractor):
if bliptv_url:
return self.url_result(bliptv_url, 'BlipTV')
# Look for SVT player
svt_url = SVTIE._extract_url(webpage)
if svt_url:
return self.url_result(svt_url, 'SVT')
# Look for embedded condenast player
matches = re.findall(
r'<iframe\s+(?:[a-zA-Z-]+="[^"]+"\s+)*?src="(https?://player\.cnevids\.com/embed/[^"]+")',
@@ -1212,6 +1375,32 @@ class GenericIE(InfoExtractor):
if rutv_url:
return self.url_result(rutv_url, 'RUTV')
# Look for embedded TVC player
tvc_url = TVCIE._extract_url(webpage)
if tvc_url:
return self.url_result(tvc_url, 'TVC')
# Look for embedded SportBox player
sportbox_urls = SportBoxEmbedIE._extract_urls(webpage)
if sportbox_urls:
return _playlist_from_matches(sportbox_urls, ie='SportBoxEmbed')
# Look for embedded PornHub player
pornhub_url = PornHubIE._extract_url(webpage)
if pornhub_url:
return self.url_result(pornhub_url, 'PornHub')
# Look for embedded XHamster player
xhamster_urls = XHamsterEmbedIE._extract_urls(webpage)
if xhamster_urls:
return _playlist_from_matches(xhamster_urls, ie='XHamsterEmbed')
# Look for embedded Tvigle player
mobj = re.search(
r'<iframe[^>]+?src=(["\'])(?P<url>(?:https?:)?//cloud\.tvigle\.ru/video/.+?)\1', webpage)
if mobj is not None:
return self.url_result(mobj.group('url'), 'Tvigle')
# Look for embedded TED player
mobj = re.search(
r'<iframe[^>]+?src=(["\'])(?P<url>https?://embed(?:-ssl)?\.ted\.com/.+?)\1', webpage)
@@ -1289,6 +1478,10 @@ class GenericIE(InfoExtractor):
mobj = re.search(
r'<iframe[^>]+?src=(["\'])(?P<url>https?://m(?:lb)?\.mlb\.com/shared/video/embed/embed\.html\?.+?)\1',
webpage)
if not mobj:
mobj = re.search(
r'data-video-link=["\'](?P<url>http://m.mlb.com/video/[^"\']+)',
webpage)
if mobj is not None:
return self.url_result(mobj.group('url'), 'MLB')
@@ -1311,8 +1504,8 @@ class GenericIE(InfoExtractor):
return self.url_result(mobj.group('url'), 'Zapiks')
# Look for Kaltura embeds
mobj = re.search(
r"(?s)kWidget\.(?:thumb)?[Ee]mbed\(\{.*?'wid'\s*:\s*'_?(?P<partner_id>[^']+)',.*?'entry_id'\s*:\s*'(?P<id>[^']+)',", webpage)
mobj = (re.search(r"(?s)kWidget\.(?:thumb)?[Ee]mbed\(\{.*?'wid'\s*:\s*'_?(?P<partner_id>[^']+)',.*?'entry_id'\s*:\s*'(?P<id>[^']+)',", webpage) or
re.search(r'(?s)(["\'])(?:https?:)?//cdnapisec\.kaltura\.com/.*?(?:p|partner_id)/(?P<partner_id>\d+).*?\1.*?entry_id\s*:\s*(["\'])(?P<id>[^\2]+?)\2', webpage))
if mobj is not None:
return self.url_result('kaltura:%(partner_id)s:%(id)s' % mobj.groupdict(), 'Kaltura')
@@ -1367,7 +1560,31 @@ class GenericIE(InfoExtractor):
# Look for Senate ISVP iframe
senate_isvp_url = SenateISVPIE._search_iframe_url(webpage)
if senate_isvp_url:
return self.url_result(surl, 'SenateISVP')
return self.url_result(senate_isvp_url, 'SenateISVP')
# Look for Dailymotion Cloud videos
dmcloud_url = DailymotionCloudIE._extract_dmcloud_url(webpage)
if dmcloud_url:
return self.url_result(dmcloud_url, 'DailymotionCloud')
# Look for OnionStudios embeds
onionstudios_url = OnionStudiosIE._extract_url(webpage)
if onionstudios_url:
return self.url_result(onionstudios_url)
# Look for SnagFilms embeds
snagfilms_url = SnagFilmsEmbedIE._extract_url(webpage)
if snagfilms_url:
return self.url_result(snagfilms_url)
# Look for AdobeTVVideo embeds
mobj = re.search(
r'<iframe[^>]+src=[\'"]((?:https?:)?//video\.tv\.adobe\.com/v/\d+[^"]+)[\'"]',
webpage)
if mobj is not None:
return self.url_result(
self._proto_relative_url(unescapeHTML(mobj.group(1))),
'AdobeTVVideo')
def check_video(vurl):
if YoutubeIE.suitable(vurl):
@@ -1436,7 +1653,7 @@ class GenericIE(InfoExtractor):
if refresh_header:
found = re.search(REDIRECT_REGEX, refresh_header)
if found:
new_url = found.group(1)
new_url = compat_urlparse.urljoin(url, found.group(1))
self.report_following_redirect(new_url)
return {
'_type': 'url',

View File

@@ -6,12 +6,13 @@ from ..utils import (
int_or_none,
float_or_none,
qualities,
ExtractorError,
)
class GfycatIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?gfycat\.com/(?P<id>[^/?#]+)'
_TEST = {
_VALID_URL = r'https?://(?:www\.)?gfycat\.com/(?:ifr/)?(?P<id>[^/?#]+)'
_TESTS = [{
'url': 'http://gfycat.com/DeadlyDecisiveGermanpinscher',
'info_dict': {
'id': 'DeadlyDecisiveGermanpinscher',
@@ -27,14 +28,33 @@ class GfycatIE(InfoExtractor):
'categories': list,
'age_limit': 0,
}
}
}, {
'url': 'http://gfycat.com/ifr/JauntyTimelyAmazontreeboa',
'info_dict': {
'id': 'JauntyTimelyAmazontreeboa',
'ext': 'mp4',
'title': 'JauntyTimelyAmazontreeboa',
'timestamp': 1411720126,
'upload_date': '20140926',
'uploader': 'anonymous',
'duration': 3.52,
'view_count': int,
'like_count': int,
'dislike_count': int,
'categories': list,
'age_limit': 0,
}
}]
def _real_extract(self, url):
video_id = self._match_id(url)
gfy = self._download_json(
'http://gfycat.com/cajax/get/%s' % video_id,
video_id, 'Downloading video info')['gfyItem']
video_id, 'Downloading video info')
if 'error' in gfy:
raise ExtractorError('Gfycat said: ' + gfy['error'], expected=True)
gfy = gfy['gfyItem']
title = gfy.get('title') or gfy['gfyName']
description = gfy.get('description')

View File

@@ -85,7 +85,8 @@ class GigaIE(InfoExtractor):
r'class="author">([^<]+)</a>', webpage, 'uploader', fatal=False)
view_count = str_to_int(self._search_regex(
r'<span class="views"><strong>([\d.]+)</strong>', webpage, 'view count', fatal=False))
r'<span class="views"><strong>([\d.,]+)</strong>',
webpage, 'view count', fatal=False))
return {
'id': video_id,

View File

@@ -35,13 +35,7 @@ class GorillaVidIE(InfoExtractor):
},
}, {
'url': 'http://gorillavid.in/embed-z08zf8le23c6-960x480.html',
'md5': 'c9e293ca74d46cad638e199c3f3fe604',
'info_dict': {
'id': 'z08zf8le23c6',
'ext': 'mp4',
'title': 'Say something nice',
'thumbnail': 're:http://.*\.jpg',
},
'only_matching': True,
}, {
'url': 'http://daclips.in/3rso4kdn6f9m',
'md5': '1ad8fd39bb976eeb66004d3a4895f106',

View File

@@ -1,191 +0,0 @@
# coding: utf-8
from __future__ import unicode_literals
import time
import math
import os.path
import re
from .common import InfoExtractor
from ..compat import (
compat_html_parser,
compat_urllib_parse,
compat_urllib_request,
compat_urlparse,
)
from ..utils import ExtractorError
class GroovesharkHtmlParser(compat_html_parser.HTMLParser):
def __init__(self):
self._current_object = None
self.objects = []
compat_html_parser.HTMLParser.__init__(self)
def handle_starttag(self, tag, attrs):
attrs = dict((k, v) for k, v in attrs)
if tag == 'object':
self._current_object = {'attrs': attrs, 'params': []}
elif tag == 'param':
self._current_object['params'].append(attrs)
def handle_endtag(self, tag):
if tag == 'object':
self.objects.append(self._current_object)
self._current_object = None
@classmethod
def extract_object_tags(cls, html):
p = cls()
p.feed(html)
p.close()
return p.objects
class GroovesharkIE(InfoExtractor):
_VALID_URL = r'https?://(www\.)?grooveshark\.com/#!/s/([^/]+)/([^/]+)'
_TEST = {
'url': 'http://grooveshark.com/#!/s/Jolene+Tenth+Key+Remix+Ft+Will+Sessions/6SS1DW?src=5',
'md5': '7ecf8aefa59d6b2098517e1baa530023',
'info_dict': {
'id': '6SS1DW',
'title': 'Jolene (Tenth Key Remix ft. Will Sessions)',
'ext': 'mp3',
'duration': 227,
}
}
do_playerpage_request = True
do_bootstrap_request = True
def _parse_target(self, target):
uri = compat_urlparse.urlparse(target)
hash = uri.fragment[1:].split('?')[0]
token = os.path.basename(hash.rstrip('/'))
return (uri, hash, token)
def _build_bootstrap_url(self, target):
(uri, hash, token) = self._parse_target(target)
query = 'getCommunicationToken=1&hash=%s&%d' % (compat_urllib_parse.quote(hash, safe=''), self.ts)
return (compat_urlparse.urlunparse((uri.scheme, uri.netloc, '/preload.php', None, query, None)), token)
def _build_meta_url(self, target):
(uri, hash, token) = self._parse_target(target)
query = 'hash=%s&%d' % (compat_urllib_parse.quote(hash, safe=''), self.ts)
return (compat_urlparse.urlunparse((uri.scheme, uri.netloc, '/preload.php', None, query, None)), token)
def _build_stream_url(self, meta):
return compat_urlparse.urlunparse(('http', meta['streamKey']['ip'], '/stream.php', None, None, None))
def _build_swf_referer(self, target, obj):
(uri, _, _) = self._parse_target(target)
return compat_urlparse.urlunparse((uri.scheme, uri.netloc, obj['attrs']['data'], None, None, None))
def _transform_bootstrap(self, js):
return re.split('(?m)^\s*try\s*\{', js)[0] \
.split(' = ', 1)[1].strip().rstrip(';')
def _transform_meta(self, js):
return js.split('\n')[0].split('=')[1].rstrip(';')
def _get_meta(self, target):
(meta_url, token) = self._build_meta_url(target)
self.to_screen('Metadata URL: %s' % meta_url)
headers = {'Referer': compat_urlparse.urldefrag(target)[0]}
req = compat_urllib_request.Request(meta_url, headers=headers)
res = self._download_json(req, token,
transform_source=self._transform_meta)
if 'getStreamKeyWithSong' not in res:
raise ExtractorError(
'Metadata not found. URL may be malformed, or Grooveshark API may have changed.')
if res['getStreamKeyWithSong'] is None:
raise ExtractorError(
'Metadata download failed, probably due to Grooveshark anti-abuse throttling. Wait at least an hour before retrying from this IP.',
expected=True)
return res['getStreamKeyWithSong']
def _get_bootstrap(self, target):
(bootstrap_url, token) = self._build_bootstrap_url(target)
headers = {'Referer': compat_urlparse.urldefrag(target)[0]}
req = compat_urllib_request.Request(bootstrap_url, headers=headers)
res = self._download_json(req, token, fatal=False,
note='Downloading player bootstrap data',
errnote='Unable to download player bootstrap data',
transform_source=self._transform_bootstrap)
return res
def _get_playerpage(self, target):
(_, _, token) = self._parse_target(target)
webpage = self._download_webpage(
target, token,
note='Downloading player page',
errnote='Unable to download player page',
fatal=False)
if webpage is not None:
# Search (for example German) error message
error_msg = self._html_search_regex(
r'<div id="content">\s*<h2>(.*?)</h2>', webpage,
'error message', default=None)
if error_msg is not None:
error_msg = error_msg.replace('\n', ' ')
raise ExtractorError('Grooveshark said: %s' % error_msg)
if webpage is not None:
o = GroovesharkHtmlParser.extract_object_tags(webpage)
return webpage, [x for x in o if x['attrs']['id'] == 'jsPlayerEmbed']
return webpage, None
def _real_initialize(self):
self.ts = int(time.time() * 1000) # timestamp in millis
def _real_extract(self, url):
(target_uri, _, token) = self._parse_target(url)
# 1. Fill cookiejar by making a request to the player page
swf_referer = None
if self.do_playerpage_request:
(_, player_objs) = self._get_playerpage(url)
if player_objs:
swf_referer = self._build_swf_referer(url, player_objs[0])
self.to_screen('SWF Referer: %s' % swf_referer)
# 2. Ask preload.php for swf bootstrap data to better mimic webapp
if self.do_bootstrap_request:
bootstrap = self._get_bootstrap(url)
self.to_screen('CommunicationToken: %s' % bootstrap['getCommunicationToken'])
# 3. Ask preload.php for track metadata.
meta = self._get_meta(url)
# 4. Construct stream request for track.
stream_url = self._build_stream_url(meta)
duration = int(math.ceil(float(meta['streamKey']['uSecs']) / 1000000))
post_dict = {'streamKey': meta['streamKey']['streamKey']}
post_data = compat_urllib_parse.urlencode(post_dict).encode('utf-8')
headers = {
'Content-Length': len(post_data),
'Content-Type': 'application/x-www-form-urlencoded'
}
if swf_referer is not None:
headers['Referer'] = swf_referer
return {
'id': token,
'title': meta['song']['Name'],
'http_method': 'POST',
'url': stream_url,
'ext': 'mp3',
'format': 'mp3 audio',
'duration': duration,
'http_post_data': post_data,
'http_headers': headers,
}

View File

@@ -1,7 +1,5 @@
from __future__ import unicode_literals
import re
from .common import InfoExtractor
@@ -19,20 +17,19 @@ class HentaiStigmaIE(InfoExtractor):
}
def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)
video_id = mobj.group('id')
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
title = self._html_search_regex(
r'<h2 class="posttitle"><a[^>]*>([^<]+)</a>',
r'<h2[^>]+class="posttitle"[^>]*><a[^>]*>([^<]+)</a>',
webpage, 'title')
wrap_url = self._html_search_regex(
r'<iframe src="([^"]+mp4)"', webpage, 'wrapper url')
r'<iframe[^>]+src="([^"]+mp4)"', webpage, 'wrapper url')
wrap_webpage = self._download_webpage(wrap_url, video_id)
video_url = self._html_search_regex(
r'clip:\s*{\s*url: "([^"]*)"', wrap_webpage, 'video url')
r'file\s*:\s*"([^"]+)"', wrap_webpage, 'video url')
return {
'id': video_id,

View File

@@ -25,7 +25,8 @@ class HistoricFilmsIE(InfoExtractor):
webpage = self._download_webpage(url, video_id)
tape_id = self._search_regex(
r'class="tapeId">([^<]+)<', webpage, 'tape id')
[r'class="tapeId"[^>]*>([^<]+)<', r'tapeId\s*:\s*"([^"]+)"'],
webpage, 'tape id')
title = self._og_search_title(webpage)
description = self._og_search_description(webpage)

View File

@@ -1,8 +1,7 @@
from __future__ import unicode_literals
import re
from .common import InfoExtractor
from ..utils import parse_iso8601
class HowcastIE(InfoExtractor):
@@ -13,29 +12,31 @@ class HowcastIE(InfoExtractor):
'info_dict': {
'id': '390161',
'ext': 'mp4',
'description': 'The square knot, also known as the reef knot, is one of the oldest, most basic knots to tie, and can be used in many different ways. Here\'s the proper way to tie a square knot.',
'title': 'How to Tie a Square Knot Properly',
}
'description': 'md5:dbe792e5f6f1489027027bf2eba188a3',
'timestamp': 1276081287,
'upload_date': '20100609',
},
'params': {
# m3u8 download
'skip_download': True,
},
}
def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)
video_id = self._match_id(url)
video_id = mobj.group('id')
webpage = self._download_webpage(url, video_id)
self.report_extraction(video_id)
video_url = self._search_regex(r'\'?file\'?: "(http://mobile-media\.howcast\.com/[0-9]+\.mp4)',
webpage, 'video URL')
video_description = self._html_search_regex(r'<meta content=(?:"([^"]+)"|\'([^\']+)\') name=\'description\'',
webpage, 'description', fatal=False)
embed_code = self._search_regex(
r'<iframe[^>]+src="[^"]+\bembed_code=([^\b]+)\b',
webpage, 'ooyala embed code')
return {
'_type': 'url_transparent',
'ie_key': 'Ooyala',
'url': 'ooyala:%s' % embed_code,
'id': video_id,
'url': video_url,
'title': self._og_search_title(webpage),
'description': video_description,
'thumbnail': self._og_search_thumbnail(webpage),
'timestamp': parse_iso8601(self._html_search_meta(
'article:published_time', webpage, 'timestamp')),
}

View File

@@ -1,36 +1,75 @@
from __future__ import unicode_literals
from .common import InfoExtractor
from ..utils import int_or_none
class IconosquareIE(InfoExtractor):
_VALID_URL = r'https?://(www\.)?(?:iconosquare\.com|statigr\.am)/p/(?P<id>[^/]+)'
_VALID_URL = r'https?://(?:www\.)?(?:iconosquare\.com|statigr\.am)/p/(?P<id>[^/]+)'
_TEST = {
'url': 'http://statigr.am/p/522207370455279102_24101272',
'md5': '6eb93b882a3ded7c378ee1d6884b1814',
'info_dict': {
'id': '522207370455279102_24101272',
'ext': 'mp4',
'uploader_id': 'aguynamedpatrick',
'title': 'Instagram photo by @aguynamedpatrick (Patrick Janelle)',
'title': 'Instagram media by @aguynamedpatrick (Patrick Janelle)',
'description': 'md5:644406a9ec27457ed7aa7a9ebcd4ce3d',
'timestamp': 1376471991,
'upload_date': '20130814',
'uploader': 'aguynamedpatrick',
'uploader_id': '24101272',
'comment_count': int,
'like_count': int,
},
}
def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
media = self._parse_json(
self._search_regex(
r'window\.media\s*=\s*({.+?});\n', webpage, 'media'),
video_id)
formats = [{
'url': f['url'],
'format_id': format_id,
'width': int_or_none(f.get('width')),
'height': int_or_none(f.get('height'))
} for format_id, f in media['videos'].items()]
self._sort_formats(formats)
title = self._html_search_regex(
r'<title>(.+?)(?: *\(Videos?\))? \| (?:Iconosquare|Statigram)</title>',
webpage, 'title')
uploader_id = self._html_search_regex(
r'@([^ ]+)', title, 'uploader name', fatal=False)
timestamp = int_or_none(media.get('created_time') or media.get('caption', {}).get('created_time'))
description = media.get('caption', {}).get('text')
uploader = media.get('user', {}).get('username')
uploader_id = media.get('user', {}).get('id')
comment_count = int_or_none(media.get('comments', {}).get('count'))
like_count = int_or_none(media.get('likes', {}).get('count'))
thumbnails = [{
'url': t['url'],
'id': thumbnail_id,
'width': int_or_none(t.get('width')),
'height': int_or_none(t.get('height'))
} for thumbnail_id, t in media.get('images', {}).items()]
return {
'id': video_id,
'url': self._og_search_video_url(webpage),
'title': title,
'description': self._og_search_description(webpage),
'thumbnail': self._og_search_thumbnail(webpage),
'uploader_id': uploader_id
'description': description,
'thumbnails': thumbnails,
'timestamp': timestamp,
'uploader': uploader,
'uploader_id': uploader_id,
'comment_count': comment_count,
'like_count': like_count,
'formats': formats,
}

View File

@@ -46,7 +46,7 @@ class ImdbIE(InfoExtractor):
format_info = info['videoPlayerObject']['video']
formats.append({
'format_id': f_id,
'url': format_info['url'],
'url': format_info['videoInfoList'][0]['videoUrl'],
})
return {

View File

@@ -3,6 +3,7 @@ from __future__ import unicode_literals
import re
from .common import InfoExtractor
from ..compat import compat_urlparse
from ..utils import (
int_or_none,
js_to_json,
@@ -12,7 +13,7 @@ from ..utils import (
class ImgurIE(InfoExtractor):
_VALID_URL = r'https?://(?:i\.)?imgur\.com/(?P<id>[a-zA-Z0-9]+)(?:\.mp4|\.gifv)?'
_VALID_URL = r'https?://(?:i\.)?imgur\.com/(?P<id>[a-zA-Z0-9]+)'
_TESTS = [{
'url': 'https://i.imgur.com/A61SaA1.gifv',
@@ -34,7 +35,8 @@ class ImgurIE(InfoExtractor):
def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
webpage = self._download_webpage(
compat_urlparse.urljoin(url, video_id), video_id)
width = int_or_none(self._search_regex(
r'<param name="width" value="([0-9]+)"',

View File

@@ -7,7 +7,7 @@ from .common import InfoExtractor
class InaIE(InfoExtractor):
_VALID_URL = r'http://(?:www\.)?ina\.fr/video/(?P<id>I?[A-Z0-9]+)'
_VALID_URL = r'https?://(?:www\.)?ina\.fr/video/(?P<id>I?[A-Z0-9]+)'
_TEST = {
'url': 'http://www.ina.fr/video/I12055569/francois-hollande-je-crois-que-c-est-clair-video.html',
'md5': 'a667021bf2b41f8dc6049479d9bb38a3',

View File

@@ -5,13 +5,14 @@ import base64
from .common import InfoExtractor
from ..compat import (
compat_urllib_parse,
compat_urlparse,
)
class InfoQIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?infoq\.com/[^/]+/(?P<id>[^/]+)$'
_VALID_URL = r'https?://(?:www\.)?infoq\.com/(?:[^/]+/)+(?P<id>[^/]+)'
_TEST = {
_TESTS = [{
'url': 'http://www.infoq.com/presentations/A-Few-of-My-Favorite-Python-Things',
'md5': 'b5ca0e0a8c1fed93b0e65e48e462f9a2',
'info_dict': {
@@ -20,7 +21,10 @@ class InfoQIE(InfoExtractor):
'description': 'Mike Pirnat presents some tips and tricks, standard libraries and third party packages that make programming in Python a richer experience.',
'title': 'A Few of My Favorite [Python] Things',
},
}
}, {
'url': 'http://www.infoq.com/fr/presentations/changez-avis-sur-javascript',
'only_matching': True,
}]
def _real_extract(self, url):
video_id = self._match_id(url)
@@ -42,7 +46,7 @@ class InfoQIE(InfoExtractor):
video_id, extension = video_filename.split('.')
http_base = self._search_regex(
r'EXPRESSINSTALL_SWF\s*=\s*"(https?://[^/"]+/)', webpage,
r'EXPRESSINSTALL_SWF\s*=\s*[^"]*"((?:https?:)?//[^/"]+/)', webpage,
'HTTP base URL')
formats = [{
@@ -52,7 +56,7 @@ class InfoQIE(InfoExtractor):
'play_path': playpath,
}, {
'format_id': 'http',
'url': http_base + real_id,
'url': compat_urlparse.urljoin(url, http_base) + real_id,
}]
self._sort_formats(formats)

View File

@@ -3,13 +3,16 @@ from __future__ import unicode_literals
import re
from .common import InfoExtractor
from ..utils import int_or_none
from ..utils import (
int_or_none,
limit_length,
)
class InstagramIE(InfoExtractor):
_VALID_URL = r'https?://instagram\.com/p/(?P<id>[\da-zA-Z]+)'
_VALID_URL = r'https://instagram\.com/p/(?P<id>[\da-zA-Z]+)'
_TEST = {
'url': 'http://instagram.com/p/aye83DjauH/?foo=bar#abc',
'url': 'https://instagram.com/p/aye83DjauH/?foo=bar#abc',
'md5': '0d2da106a9d2631273e192b372806516',
'info_dict': {
'id': 'aye83DjauH',
@@ -41,11 +44,11 @@ class InstagramIE(InfoExtractor):
class InstagramUserIE(InfoExtractor):
_VALID_URL = r'http://instagram\.com/(?P<username>[^/]{2,})/?(?:$|[?#])'
_VALID_URL = r'https://instagram\.com/(?P<username>[^/]{2,})/?(?:$|[?#])'
IE_DESC = 'Instagram user profile'
IE_NAME = 'instagram:user'
_TEST = {
'url': 'http://instagram.com/porsche',
'url': 'https://instagram.com/porsche',
'info_dict': {
'id': 'porsche',
'title': 'porsche',
@@ -100,11 +103,13 @@ class InstagramUserIE(InfoExtractor):
thumbnails_el = it.get('images', {})
thumbnail = thumbnails_el.get('thumbnail', {}).get('url')
title = it.get('caption', {}).get('text', it['id'])
# In some cases caption is null, which corresponds to None
# in python. As a result, it.get('caption', {}) gives None
title = (it.get('caption') or {}).get('text', it['id'])
entries.append({
'id': it['id'],
'title': title,
'title': limit_length(title, 80),
'formats': formats,
'thumbnail': thumbnail,
'webpage_url': it.get('link'),

View File

@@ -11,11 +11,12 @@ from ..compat import (
)
from ..utils import (
ExtractorError,
remove_end,
)
class IPrimaIE(InfoExtractor):
_VALID_URL = r'https?://play\.iprima\.cz/[^?#]+/(?P<id>[^?#]+)'
_VALID_URL = r'https?://play\.iprima\.cz/(?:[^/]+/)*(?P<id>[^?#]+)'
_TESTS = [{
'url': 'http://play.iprima.cz/particka/particka-92',
@@ -23,7 +24,7 @@ class IPrimaIE(InfoExtractor):
'id': '39152',
'ext': 'flv',
'title': 'Partička (92)',
'description': 'md5:3740fda51464da35a2d4d0670b8e4fd6',
'description': 'md5:74e9617e51bca67c3ecfb2c6f9766f45',
'thumbnail': 'http://play.iprima.cz/sites/default/files/image_crops/image_620x349/3/491483_particka-92_image_620x349.jpg',
},
'params': {
@@ -35,13 +36,14 @@ class IPrimaIE(InfoExtractor):
'id': '9718337',
'ext': 'flv',
'title': 'Tchibo Partička - Jarní móda',
'description': 'md5:589f8f59f414220621ff8882eb3ce7be',
'thumbnail': 're:^http:.*\.jpg$',
},
'params': {
'skip_download': True, # requires rtmpdump
},
'skip': 'Do not have permission to access this page',
}, {
'url': 'http://play.iprima.cz/zpravy-ftv-prima-2752015',
'only_matching': True,
}]
def _real_extract(self, url):
@@ -102,8 +104,10 @@ class IPrimaIE(InfoExtractor):
return {
'id': real_id,
'title': self._og_search_title(webpage),
'title': remove_end(self._og_search_title(webpage), ' | Prima PLAY'),
'thumbnail': self._og_search_thumbnail(webpage),
'formats': formats,
'description': self._og_search_description(webpage),
'description': self._search_regex(
r'<p[^>]+itemprop="description"[^>]*>([^<]+)',
webpage, 'description', default=None),
}

View File

@@ -0,0 +1,296 @@
# coding: utf-8
from __future__ import unicode_literals
import hashlib
import math
import os.path
import random
import re
import time
import uuid
import zlib
from .common import InfoExtractor
from ..compat import compat_urllib_parse
from ..utils import (
ExtractorError,
url_basename,
)
class IqiyiIE(InfoExtractor):
IE_NAME = 'iqiyi'
_VALID_URL = r'http://(?:www\.)iqiyi.com/v_.+?\.html'
_TESTS = [{
'url': 'http://www.iqiyi.com/v_19rrojlavg.html',
'md5': '2cb594dc2781e6c941a110d8f358118b',
'info_dict': {
'id': '9c1fb1b99d192b21c559e5a1a2cb3c73',
'title': '美国德州空中惊现奇异云团 酷似UFO',
'ext': 'f4v',
}
}, {
'url': 'http://www.iqiyi.com/v_19rrhnnclk.html',
'info_dict': {
'id': 'e3f585b550a280af23c98b6cb2be19fb',
'title': '名侦探柯南第752集',
},
'playlist': [{
'md5': '7e49376fecaffa115d951634917fe105',
'info_dict': {
'id': 'e3f585b550a280af23c98b6cb2be19fb_part1',
'ext': 'f4v',
'title': '名侦探柯南第752集',
},
}, {
'md5': '41b75ba13bb7ac0e411131f92bc4f6ca',
'info_dict': {
'id': 'e3f585b550a280af23c98b6cb2be19fb_part2',
'ext': 'f4v',
'title': '名侦探柯南第752集',
},
}, {
'md5': '0cee1dd0a3d46a83e71e2badeae2aab0',
'info_dict': {
'id': 'e3f585b550a280af23c98b6cb2be19fb_part3',
'ext': 'f4v',
'title': '名侦探柯南第752集',
},
}, {
'md5': '4f8ad72373b0c491b582e7c196b0b1f9',
'info_dict': {
'id': 'e3f585b550a280af23c98b6cb2be19fb_part4',
'ext': 'f4v',
'title': '名侦探柯南第752集',
},
}, {
'md5': 'd89ad028bcfad282918e8098e811711d',
'info_dict': {
'id': 'e3f585b550a280af23c98b6cb2be19fb_part5',
'ext': 'f4v',
'title': '名侦探柯南第752集',
},
}, {
'md5': '9cb1e5c95da25dff0660c32ae50903b7',
'info_dict': {
'id': 'e3f585b550a280af23c98b6cb2be19fb_part6',
'ext': 'f4v',
'title': '名侦探柯南第752集',
},
}, {
'md5': '155116e0ff1867bbc9b98df294faabc9',
'info_dict': {
'id': 'e3f585b550a280af23c98b6cb2be19fb_part7',
'ext': 'f4v',
'title': '名侦探柯南第752集',
},
}, {
'md5': '53f5db77622ae14fa493ed2a278a082b',
'info_dict': {
'id': 'e3f585b550a280af23c98b6cb2be19fb_part8',
'ext': 'f4v',
'title': '名侦探柯南第752集',
},
}],
}]
_FORMATS_MAP = [
('1', 'h6'),
('2', 'h5'),
('3', 'h4'),
('4', 'h3'),
('5', 'h2'),
('10', 'h1'),
]
def construct_video_urls(self, data, video_id, _uuid):
def do_xor(x, y):
a = y % 3
if a == 1:
return x ^ 121
if a == 2:
return x ^ 72
return x ^ 103
def get_encode_code(l):
a = 0
b = l.split('-')
c = len(b)
s = ''
for i in range(c - 1, -1, -1):
a = do_xor(int(b[c - i - 1], 16), i)
s += chr(a)
return s[::-1]
def get_path_key(x, format_id, segment_index):
mg = ')(*&^flash@#$%a'
tm = self._download_json(
'http://data.video.qiyi.com/t?tn=' + str(random.random()), video_id,
note='Download path key of segment %d for format %s' % (segment_index + 1, format_id)
)['t']
t = str(int(math.floor(int(tm) / (600.0))))
return hashlib.md5((t + mg + x).encode('utf8')).hexdigest()
video_urls_dict = {}
for format_item in data['vp']['tkl'][0]['vs']:
if 0 < int(format_item['bid']) <= 10:
format_id = self.get_format(format_item['bid'])
else:
continue
video_urls = []
video_urls_info = format_item['fs']
if not format_item['fs'][0]['l'].startswith('/'):
t = get_encode_code(format_item['fs'][0]['l'])
if t.endswith('mp4'):
video_urls_info = format_item['flvs']
for segment_index, segment in enumerate(video_urls_info):
vl = segment['l']
if not vl.startswith('/'):
vl = get_encode_code(vl)
key = get_path_key(
vl.split('/')[-1].split('.')[0], format_id, segment_index)
filesize = segment['b']
base_url = data['vp']['du'].split('/')
base_url.insert(-1, key)
base_url = '/'.join(base_url)
param = {
'su': _uuid,
'qyid': uuid.uuid4().hex,
'client': '',
'z': '',
'bt': '',
'ct': '',
'tn': str(int(time.time()))
}
api_video_url = base_url + vl + '?' + \
compat_urllib_parse.urlencode(param)
js = self._download_json(
api_video_url, video_id,
note='Download video info of segment %d for format %s' % (segment_index + 1, format_id))
video_url = js['l']
video_urls.append(
(video_url, filesize))
video_urls_dict[format_id] = video_urls
return video_urls_dict
def get_format(self, bid):
matched_format_ids = [_format_id for _bid, _format_id in self._FORMATS_MAP if _bid == str(bid)]
return matched_format_ids[0] if len(matched_format_ids) else None
def get_bid(self, format_id):
matched_bids = [_bid for _bid, _format_id in self._FORMATS_MAP if _format_id == format_id]
return matched_bids[0] if len(matched_bids) else None
def get_raw_data(self, tvid, video_id, enc_key, _uuid):
tm = str(int(time.time()))
param = {
'key': 'fvip',
'src': hashlib.md5(b'youtube-dl').hexdigest(),
'tvId': tvid,
'vid': video_id,
'vinfo': 1,
'tm': tm,
'enc': hashlib.md5(
(enc_key + tm + tvid).encode('utf8')).hexdigest(),
'qyid': _uuid,
'tn': random.random(),
'um': 0,
'authkey': hashlib.md5(
(tm + tvid).encode('utf8')).hexdigest()
}
api_url = 'http://cache.video.qiyi.com/vms' + '?' + \
compat_urllib_parse.urlencode(param)
raw_data = self._download_json(api_url, video_id)
return raw_data
def get_enc_key(self, swf_url, video_id):
filename, _ = os.path.splitext(url_basename(swf_url))
enc_key_json = self._downloader.cache.load('iqiyi-enc-key', filename)
if enc_key_json is not None:
return enc_key_json[0]
req = self._request_webpage(
swf_url, video_id, note='download swf content')
cn = req.read()
cn = zlib.decompress(cn[8:])
pt = re.compile(b'MixerRemote\x08(?P<enc_key>.+?)\$&vv')
enc_key = self._search_regex(pt, cn, 'enc_key').decode('utf8')
self._downloader.cache.store('iqiyi-enc-key', filename, [enc_key])
return enc_key
def _real_extract(self, url):
webpage = self._download_webpage(
url, 'temp_id', note='download video page')
tvid = self._search_regex(
r'data-player-tvid\s*=\s*[\'"](\d+)', webpage, 'tvid')
video_id = self._search_regex(
r'data-player-videoid\s*=\s*[\'"]([a-f\d]+)', webpage, 'video_id')
swf_url = self._search_regex(
r'(http://[^\'"]+MainPlayer[^.]+\.swf)', webpage, 'swf player URL')
_uuid = uuid.uuid4().hex
enc_key = self.get_enc_key(swf_url, video_id)
raw_data = self.get_raw_data(tvid, video_id, enc_key, _uuid)
if raw_data['code'] != 'A000000':
raise ExtractorError('Unable to load data. Error code: ' + raw_data['code'])
if not raw_data['data']['vp']['tkl']:
raise ExtractorError('No support iQiqy VIP video')
data = raw_data['data']
title = data['vi']['vn']
# generate video_urls_dict
video_urls_dict = self.construct_video_urls(
data, video_id, _uuid)
# construct info
entries = []
for format_id in video_urls_dict:
video_urls = video_urls_dict[format_id]
for i, video_url_info in enumerate(video_urls):
if len(entries) < i + 1:
entries.append({'formats': []})
entries[i]['formats'].append(
{
'url': video_url_info[0],
'filesize': video_url_info[-1],
'format_id': format_id,
'preference': int(self.get_bid(format_id))
}
)
for i in range(len(entries)):
self._sort_formats(entries[i]['formats'])
entries[i].update(
{
'id': '%s_part%d' % (video_id, i + 1),
'title': title,
}
)
if len(entries) > 1:
info = {
'_type': 'multi_video',
'id': video_id,
'title': title,
'entries': entries,
}
else:
info = entries[0]
info['id'] = video_id
info['title'] = title
return info

View File

@@ -4,6 +4,7 @@ from __future__ import unicode_literals
import re
from .common import InfoExtractor
from ..compat import compat_urllib_parse_unquote
from ..utils import (
determine_ext,
float_or_none,
@@ -30,7 +31,7 @@ class IzleseneIE(InfoExtractor):
'description': 'md5:253753e2655dde93f59f74b572454f6d',
'thumbnail': 're:^http://.*\.jpg',
'uploader_id': 'pelikzzle',
'timestamp': 1404302298,
'timestamp': int,
'upload_date': '20140702',
'duration': 95.395,
'age_limit': 0,
@@ -46,7 +47,7 @@ class IzleseneIE(InfoExtractor):
'description': 'Tarkan Dortmund 2006 Konseri',
'thumbnail': 're:^http://.*\.jpg',
'uploader_id': 'parlayankiz',
'timestamp': 1163322193,
'timestamp': int,
'upload_date': '20061112',
'duration': 253.666,
'age_limit': 0,
@@ -67,9 +68,9 @@ class IzleseneIE(InfoExtractor):
uploader = self._html_search_regex(
r"adduserUsername\s*=\s*'([^']+)';",
webpage, 'uploader', fatal=False, default='')
webpage, 'uploader', fatal=False)
timestamp = parse_iso8601(self._html_search_meta(
'uploadDate', webpage, 'upload date', fatal=False))
'uploadDate', webpage, 'upload date'))
duration = float_or_none(self._html_search_regex(
r'"videoduration"\s*:\s*"([^"]+)"',
@@ -86,8 +87,7 @@ class IzleseneIE(InfoExtractor):
# Might be empty for some videos.
streams = self._html_search_regex(
r'"qualitylevel"\s*:\s*"([^"]+)"',
webpage, 'streams', fatal=False, default='')
r'"qualitylevel"\s*:\s*"([^"]+)"', webpage, 'streams', default='')
formats = []
if streams:
@@ -95,15 +95,15 @@ class IzleseneIE(InfoExtractor):
quality, url = re.search(r'\[(\w+)\](.+)', stream).groups()
formats.append({
'format_id': '%sp' % quality if quality else 'sd',
'url': url,
'url': compat_urllib_parse_unquote(url),
'ext': ext,
})
else:
stream_url = self._search_regex(
r'"streamurl"\s?:\s?"([^"]+)"', webpage, 'stream URL')
r'"streamurl"\s*:\s*"([^"]+)"', webpage, 'stream URL')
formats.append({
'format_id': 'sd',
'url': stream_url,
'url': compat_urllib_parse_unquote(stream_url),
'ext': ext,
})

View File

@@ -7,6 +7,7 @@ from .common import InfoExtractor
from ..utils import (
ExtractorError,
float_or_none,
srt_subtitles_timecode,
)
@@ -39,8 +40,8 @@ class KanalPlayIE(InfoExtractor):
'%s\r\n%s --> %s\r\n%s'
% (
num,
self._subtitles_timecode(item['startMillis'] / 1000.0),
self._subtitles_timecode(item['endMillis'] / 1000.0),
srt_subtitles_timecode(item['startMillis'] / 1000.0),
srt_subtitles_timecode(item['endMillis'] / 1000.0),
item['text'],
) for num, item in enumerate(subs, 1))

View File

@@ -0,0 +1,96 @@
# coding: utf-8
from __future__ import unicode_literals
from .common import InfoExtractor
from ..compat import compat_urlparse
from ..utils import (
fix_xml_ampersands,
float_or_none,
xpath_with_ns,
xpath_text,
)
class KarriereVideosIE(InfoExtractor):
_VALID_URL = r'http://(?:www\.)?karrierevideos\.at(?:/[^/]+)+/(?P<id>[^/]+)'
_TESTS = [{
'url': 'http://www.karrierevideos.at/berufsvideos/mittlere-hoehere-schulen/altenpflegerin',
'info_dict': {
'id': '32c91',
'ext': 'flv',
'title': 'AltenpflegerIn',
'description': 'md5:dbadd1259fde2159a9b28667cb664ae2',
'thumbnail': 're:^http://.*\.png',
},
'params': {
# rtmp download
'skip_download': True,
}
}, {
# broken ampersands
'url': 'http://www.karrierevideos.at/orientierung/vaeterkarenz-und-neue-chancen-fuer-muetter-baby-was-nun',
'info_dict': {
'id': '5sniu',
'ext': 'flv',
'title': 'Väterkarenz und neue Chancen für Mütter - "Baby - was nun?"',
'description': 'md5:97092c6ad1fd7d38e9d6a5fdeb2bcc33',
'thumbnail': 're:^http://.*\.png',
},
'params': {
# rtmp download
'skip_download': True,
}
}]
def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
title = (self._html_search_meta('title', webpage, default=None) or
self._search_regex(r'<h1 class="title">([^<]+)</h1>'))
video_id = self._search_regex(
r'/config/video/(.+?)\.xml', webpage, 'video id')
playlist = self._download_xml(
'http://www.karrierevideos.at/player-playlist.xml.php?p=%s' % video_id,
video_id, transform_source=fix_xml_ampersands)
NS_MAP = {
'jwplayer': 'http://developer.longtailvideo.com/trac/wiki/FlashFormats'
}
def ns(path):
return xpath_with_ns(path, NS_MAP)
item = playlist.find('./tracklist/item')
video_file = xpath_text(
item, ns('./jwplayer:file'), 'video url', fatal=True)
streamer = xpath_text(
item, ns('./jwplayer:streamer'), 'streamer', fatal=True)
uploader = xpath_text(
item, ns('./jwplayer:author'), 'uploader')
duration = float_or_none(
xpath_text(item, ns('./jwplayer:duration'), 'duration'))
description = self._html_search_regex(
r'(?s)<div class="leadtext">(.+?)</div>',
webpage, 'description')
thumbnail = self._html_search_meta(
'thumbnail', webpage, 'thumbnail')
if thumbnail:
thumbnail = compat_urlparse.urljoin(url, thumbnail)
return {
'id': video_id,
'url': streamer.replace('rtmpt', 'rtmp'),
'play_path': 'mp4:%s' % video_file,
'ext': 'flv',
'title': title,
'description': description,
'thumbnail': thumbnail,
'uploader': uploader,
'duration': duration,
}

View File

@@ -28,6 +28,14 @@ class KickStarterIE(InfoExtractor):
'uploader': 'Pebble Technology',
'title': 'Pebble iOS Notifications',
}
}, {
'url': 'https://www.kickstarter.com/projects/1420158244/power-drive-2000/widget/video.html',
'info_dict': {
'id': '1420158244',
'ext': 'mp4',
'title': 'Power Drive 2000',
},
'expected_warnings': ['OpenGraph description'],
}]
def _real_extract(self, url):
@@ -48,10 +56,15 @@ class KickStarterIE(InfoExtractor):
'title': title,
}
thumbnail = self._og_search_thumbnail(webpage, default=None)
if thumbnail is None:
thumbnail = self._html_search_regex(
r'<img[^>]+class="[^"]+\s*poster\s*[^"]+"[^>]+src="([^"]+)"',
webpage, 'thumbnail image', fatal=False)
return {
'id': video_id,
'url': video_url,
'title': title,
'description': self._og_search_description(webpage),
'thumbnail': self._og_search_thumbnail(webpage),
'thumbnail': thumbnail,
}

View File

@@ -50,9 +50,7 @@ class LetvIE(InfoExtractor):
'title': '与龙共舞 完整版',
'description': 'md5:7506a5eeb1722bb9d4068f85024e3986',
},
'params': {
'cn_verification_proxy': 'http://proxy.uku.im:8888'
},
'skip': 'Only available in China',
}]
@staticmethod

View File

@@ -4,8 +4,11 @@ from __future__ import unicode_literals
import re
from .common import InfoExtractor
from ..compat import compat_urlparse
from ..utils import (
determine_ext,
int_or_none,
remove_end,
unified_strdate,
ExtractorError,
)
@@ -14,9 +17,9 @@ from ..utils import (
class LifeNewsIE(InfoExtractor):
IE_NAME = 'lifenews'
IE_DESC = 'LIFE | NEWS'
_VALID_URL = r'http://lifenews\.ru/(?:mobile/)?news/(?P<id>\d+)'
_VALID_URL = r'http://lifenews\.ru/(?:mobile/)?(?P<section>news|video)/(?P<id>\d+)'
_TEST = {
_TESTS = [{
'url': 'http://lifenews.ru/news/126342',
'md5': 'e1b50a5c5fb98a6a544250f2e0db570a',
'info_dict': {
@@ -27,48 +30,139 @@ class LifeNewsIE(InfoExtractor):
'thumbnail': 're:http://.*\.jpg',
'upload_date': '20140130',
}
}
}, {
# video in <iframe>
'url': 'http://lifenews.ru/news/152125',
'md5': '77d19a6f0886cd76bdbf44b4d971a273',
'info_dict': {
'id': '152125',
'ext': 'mp4',
'title': 'В Сети появилось видео захвата «Правым сектором» колхозных полей ',
'description': 'Жители двух поселков Днепропетровской области не простили радикалам угрозу лишения плодородных земель и пошли в лобовую. ',
'upload_date': '20150402',
}
}, {
'url': 'http://lifenews.ru/news/153461',
'md5': '9b6ef8bc0ffa25aebc8bdb40d89ab795',
'info_dict': {
'id': '153461',
'ext': 'mp4',
'title': 'В Москве спасли потерявшегося медвежонка, который спрятался на дереве',
'description': 'Маленький хищник не смог найти дорогу домой и обрел временное убежище на тополе недалеко от жилого массива, пока его не нашла соседская собака.',
'upload_date': '20150505',
}
}, {
'url': 'http://lifenews.ru/video/13035',
'only_matching': True,
}]
def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)
video_id = mobj.group('id')
section = mobj.group('section')
webpage = self._download_webpage('http://lifenews.ru/news/%s' % video_id, video_id, 'Downloading page')
webpage = self._download_webpage(
'http://lifenews.ru/%s/%s' % (section, video_id),
video_id, 'Downloading page')
videos = re.findall(r'<video.*?poster="(?P<poster>[^"]+)".*?src="(?P<video>[^"]+)".*?></video>', webpage)
if not videos:
iframe_link = self._html_search_regex(
'<iframe[^>]+src=["\']([^"\']+)["\']', webpage, 'iframe link', default=None)
if not videos and not iframe_link:
raise ExtractorError('No media links available for %s' % video_id)
title = self._og_search_title(webpage)
TITLE_SUFFIX = ' - Первый по срочным новостям — LIFE | NEWS'
if title.endswith(TITLE_SUFFIX):
title = title[:-len(TITLE_SUFFIX)]
title = remove_end(
self._og_search_title(webpage),
' - Первый по срочным новостям — LIFE | NEWS')
description = self._og_search_description(webpage)
view_count = self._html_search_regex(
r'<div class=\'views\'>(\d+)</div>', webpage, 'view count', fatal=False)
r'<div class=\'views\'>\s*(\d+)\s*</div>', webpage, 'view count', fatal=False)
comment_count = self._html_search_regex(
r'<div class=\'comments\'>\s*<span class=\'counter\'>(\d+)</span>', webpage, 'comment count', fatal=False)
r'=\'commentCount\'[^>]*>\s*(\d+)\s*<',
webpage, 'comment count', fatal=False)
upload_date = self._html_search_regex(
r'<time datetime=\'([^\']+)\'>', webpage, 'upload date', fatal=False)
r'<time[^>]*datetime=\'([^\']+)\'', webpage, 'upload date', fatal=False)
if upload_date is not None:
upload_date = unified_strdate(upload_date)
common_info = {
'description': description,
'view_count': int_or_none(view_count),
'comment_count': int_or_none(comment_count),
'upload_date': upload_date,
}
def make_entry(video_id, media, video_number=None):
return {
cur_info = dict(common_info)
cur_info.update({
'id': video_id,
'url': media[1],
'thumbnail': media[0],
'title': title if video_number is None else '%s-video%s' % (title, video_number),
'description': description,
'view_count': int_or_none(view_count),
'comment_count': int_or_none(comment_count),
'upload_date': upload_date,
}
})
return cur_info
if iframe_link:
iframe_link = self._proto_relative_url(iframe_link, 'http:')
cur_info = dict(common_info)
cur_info.update({
'_type': 'url_transparent',
'id': video_id,
'title': title,
'url': iframe_link,
})
return cur_info
if len(videos) == 1:
return make_entry(video_id, videos[0])
else:
return [make_entry(video_id, media, video_number + 1) for video_number, media in enumerate(videos)]
class LifeEmbedIE(InfoExtractor):
IE_NAME = 'life:embed'
_VALID_URL = r'http://embed\.life\.ru/embed/(?P<id>[\da-f]{32})'
_TEST = {
'url': 'http://embed.life.ru/embed/e50c2dec2867350528e2574c899b8291',
'md5': 'b889715c9e49cb1981281d0e5458fbbe',
'info_dict': {
'id': 'e50c2dec2867350528e2574c899b8291',
'ext': 'mp4',
'title': 'e50c2dec2867350528e2574c899b8291',
'thumbnail': 're:http://.*\.jpg',
}
}
def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
formats = []
for video_url in re.findall(r'"file"\s*:\s*"([^"]+)', webpage):
video_url = compat_urlparse.urljoin(url, video_url)
ext = determine_ext(video_url)
if ext == 'm3u8':
formats.extend(self._extract_m3u8_formats(
video_url, video_id, 'mp4', m3u8_id='m3u8'))
else:
formats.append({
'url': video_url,
'format_id': ext,
'preference': 1,
})
self._sort_formats(formats)
thumbnail = self._search_regex(
r'"image"\s*:\s*"([^"]+)', webpage, 'thumbnail', default=None)
return {
'id': video_id,
'title': video_id,
'thumbnail': thumbnail,
'formats': formats,
}

View File

@@ -40,6 +40,17 @@ class LiveLeakIE(InfoExtractor):
'title': 'Man is Fatally Struck by Reckless Car While Packing up a Moving Truck',
'age_limit': 18,
}
}, {
# Covers https://github.com/rg3/youtube-dl/pull/5983
'url': 'http://www.liveleak.com/view?i=801_1409392012',
'md5': '0b3bec2d888c20728ca2ad3642f0ef15',
'info_dict': {
'id': '801_1409392012',
'ext': 'mp4',
'description': "Happened on 27.7.2014. \r\nAt 0:53 you can see people still swimming at near beach.",
'uploader': 'bony333',
'title': 'Crazy Hungarian tourist films close call waterspout in Croatia'
}
}]
def _real_extract(self, url):
@@ -85,7 +96,10 @@ class LiveLeakIE(InfoExtractor):
'url': s['file'],
} for i, s in enumerate(sources)]
for i, s in enumerate(sources):
orig_url = s['file'].replace('.h264_base.mp4', '')
# Removing '.h264_*.mp4' gives the raw video, which is essentially
# the same video without the LiveLeak logo at the top (see
# https://github.com/rg3/youtube-dl/pull/4768)
orig_url = re.sub(r'\.h264_.+?\.mp4', '', s['file'])
if s['file'] != orig_url:
formats.append({
'format_id': 'original-%s' % i,

View File

@@ -194,23 +194,19 @@ class LivestreamIE(InfoExtractor):
# The original version of Livestream uses a different system
class LivestreamOriginalIE(InfoExtractor):
IE_NAME = 'livestream:original'
_VALID_URL = r'''(?x)https?://www\.livestream\.com/
_VALID_URL = r'''(?x)https?://original\.livestream\.com/
(?P<user>[^/]+)/(?P<type>video|folder)
(?:\?.*?Id=|/)(?P<id>.*?)(&|$)
'''
_TESTS = [{
'url': 'http://www.livestream.com/dealbook/video?clipId=pla_8aa4a3f1-ba15-46a4-893b-902210e138fb',
'url': 'http://original.livestream.com/dealbook/video?clipId=pla_8aa4a3f1-ba15-46a4-893b-902210e138fb',
'info_dict': {
'id': 'pla_8aa4a3f1-ba15-46a4-893b-902210e138fb',
'ext': 'flv',
'ext': 'mp4',
'title': 'Spark 1 (BitCoin) with Cameron Winklevoss & Tyler Winklevoss of Winklevoss Capital',
},
'params': {
# rtmp
'skip_download': True,
},
}, {
'url': 'https://www.livestream.com/newplay/folder?dirId=a07bf706-d0e4-4e75-a747-b021d84f2fd3',
'url': 'https://original.livestream.com/newplay/folder?dirId=a07bf706-d0e4-4e75-a747-b021d84f2fd3',
'info_dict': {
'id': 'a07bf706-d0e4-4e75-a747-b021d84f2fd3',
},
@@ -221,19 +217,17 @@ class LivestreamOriginalIE(InfoExtractor):
api_url = 'http://x{0}x.api.channel.livestream.com/2.0/clipdetails?extendedInfo=true&id={1}'.format(user, video_id)
info = self._download_xml(api_url, video_id)
# this url is used on mobile devices
stream_url = 'http://x{0}x.api.channel.livestream.com/3.0/getstream.json?id={1}'.format(user, video_id)
stream_info = self._download_json(stream_url, video_id)
item = info.find('channel').find('item')
ns = {'media': 'http://search.yahoo.com/mrss'}
thumbnail_url = item.find(xpath_with_ns('media:thumbnail', ns)).attrib['url']
# Remove the extension and number from the path (like 1.jpg)
path = self._search_regex(r'(user-files/.+)_.*?\.jpg$', thumbnail_url, 'path')
return {
'id': video_id,
'title': item.find('title').text,
'url': 'rtmp://extondemand.livestream.com/ondemand',
'play_path': 'trans/dv15/mogulus-{0}'.format(path),
'player_url': 'http://static.livestream.com/chromelessPlayer/v21/playerapi.swf?hash=5uetk&v=0803&classid=D27CDB6E-AE6D-11cf-96B8-444553540000&jsEnabled=false&wmode=opaque',
'ext': 'flv',
'url': stream_info['progressiveUrl'],
'thumbnail': thumbnail_url,
}

View File

@@ -30,13 +30,13 @@ class LyndaBaseIE(InfoExtractor):
return
login_form = {
'username': username,
'password': password,
'username': username.encode('utf-8'),
'password': password.encode('utf-8'),
'remember': 'false',
'stayPut': 'false'
}
request = compat_urllib_request.Request(
self._LOGIN_URL, compat_urllib_parse.urlencode(login_form))
self._LOGIN_URL, compat_urllib_parse.urlencode(login_form).encode('utf-8'))
login_page = self._download_webpage(
request, None, 'Logging in as %s' % username)
@@ -65,7 +65,7 @@ class LyndaBaseIE(InfoExtractor):
'stayPut': 'false',
}
request = compat_urllib_request.Request(
self._LOGIN_URL, compat_urllib_parse.urlencode(confirm_form))
self._LOGIN_URL, compat_urllib_parse.urlencode(confirm_form).encode('utf-8'))
login_page = self._download_webpage(
request, None,
'Confirming log in and log out from another device')

View File

@@ -20,7 +20,6 @@ class MiTeleIE(InfoExtractor):
_TESTS = [{
'url': 'http://www.mitele.es/programas-tv/diario-de/la-redaccion/programa-144/',
'md5': '6a75fe9d0d3275bead0cb683c616fddb',
'info_dict': {
'id': '0fce117d',
'ext': 'mp4',
@@ -29,6 +28,10 @@ class MiTeleIE(InfoExtractor):
'display_id': 'programa-144',
'duration': 2913,
},
'params': {
# m3u8 download
'skip_download': True,
},
}]
def _real_extract(self, url):
@@ -56,12 +59,14 @@ class MiTeleIE(InfoExtractor):
episode,
transform_source=strip_jsonp
)
formats = self._extract_m3u8_formats(
token_info['tokenizedUrl'], episode, ext='mp4')
return {
'id': embed_data['videoId'],
'display_id': episode,
'title': info_el.find('title').text,
'url': token_info['tokenizedUrl'],
'formats': formats,
'description': get_element_by_attribute('class', 'text', webpage),
'thumbnail': info_el.find('thumb').text,
'duration': parse_duration(info_el.find('duration').text),

View File

@@ -10,7 +10,21 @@ from ..utils import (
class MLBIE(InfoExtractor):
_VALID_URL = r'https?://m(?:lb)?\.(?:[\da-z_-]+\.)?mlb\.com/(?:(?:.*?/)?video/(?:topic/[\da-z_-]+/)?v|(?:shared/video/embed/embed\.html|[^/]+/video/play\.jsp)\?.*?\bcontent_id=)(?P<id>n?\d+)'
_VALID_URL = r'''(?x)
https?://
(?:[\da-z_-]+\.)*mlb\.com/
(?:
(?:
(?:.*?/)?video/(?:topic/[\da-z_-]+/)?v|
(?:
shared/video/embed/(?:embed|m-internal-embed)\.html|
(?:[^/]+/)+(?:play|index)\.jsp|
)\?.*?\bcontent_id=
)
(?P<id>n?\d+)|
(?:[^/]+/)*(?P<path>[^/]+)
)
'''
_TESTS = [
{
'url': 'http://m.mlb.com/sea/video/topic/51231442/v34698933/nymsea-ackley-robs-a-home-run-with-an-amazing-catch/?c_id=sea',
@@ -68,6 +82,18 @@ class MLBIE(InfoExtractor):
'thumbnail': 're:^https?://.*\.jpg$',
},
},
{
'url': 'http://m.mlb.com/news/article/118550098/blue-jays-kevin-pillar-goes-spidey-up-the-wall-to-rob-tim-beckham-of-a-homer',
'md5': 'b190e70141fb9a1552a85426b4da1b5d',
'info_dict': {
'id': '75609783',
'ext': 'mp4',
'title': 'Must C: Pillar climbs for catch',
'description': '4/15/15: Blue Jays outfielder Kevin Pillar continues his defensive dominance by climbing the wall in left to rob Tim Beckham of a home run',
'timestamp': 1429124820,
'upload_date': '20150415',
}
},
{
'url': 'http://m.mlb.com/shared/video/embed/embed.html?content_id=35692085&topic_id=6479266&width=400&height=224&property=mlb',
'only_matching': True,
@@ -83,6 +109,15 @@ class MLBIE(InfoExtractor):
{
'url': 'http://m.cardinals.mlb.com/stl/video/v51175783/atlstl-piscotty-makes-great-sliding-catch-on-line/?partnerId=as_mlb_20150321_42500876&adbid=579409712979910656&adbpl=tw&adbpr=52847728',
'only_matching': True,
},
{
# From http://m.mlb.com/news/article/118550098/blue-jays-kevin-pillar-goes-spidey-up-the-wall-to-rob-tim-beckham-of-a-homer
'url': 'http://mlb.mlb.com/shared/video/embed/m-internal-embed.html?content_id=75609783&property=mlb&autoplay=true&hashmode=false&siteSection=mlb/multimedia/article_118550098/article_embed&club=mlb',
'only_matching': True,
},
{
'url': 'http://washington.nationals.mlb.com/mlb/gameday/index.jsp?c_id=was&gid=2015_05_09_atlmlb_wasmlb_1&lang=en&content_id=108309983&mode=video#',
'only_matching': True,
}
]
@@ -90,6 +125,12 @@ class MLBIE(InfoExtractor):
mobj = re.match(self._VALID_URL, url)
video_id = mobj.group('id')
if not video_id:
video_path = mobj.group('path')
webpage = self._download_webpage(url, video_path)
video_id = self._search_regex(
[r'data-video-?id="(\d+)"', r'content_id=(\d+)'], webpage, 'video id')
detail = self._download_xml(
'http://m.mlb.com/gen/multimedia/detail/%s/%s/%s/%s.xml'
% (video_id[-3], video_id[-2], video_id[-1], video_id), video_id)

View File

@@ -9,6 +9,7 @@ from ..compat import (
compat_urllib_parse,
compat_urllib_request,
)
from ..utils import ExtractorError
class MonikerIE(InfoExtractor):
@@ -40,6 +41,15 @@ class MonikerIE(InfoExtractor):
video_id = self._match_id(url)
orig_webpage = self._download_webpage(url, video_id)
if '>File Not Found<' in orig_webpage:
raise ExtractorError('Video %s does not exist' % video_id, expected=True)
error = self._search_regex(
r'class="err">([^<]+)<', orig_webpage, 'error', default=None)
if error:
raise ExtractorError(
'%s returned error: %s' % (self.IE_NAME, error), expected=True)
fields = re.findall(r'type="hidden" name="(.+?)"\s* value="?(.+?)">', orig_webpage)
data = dict(fields)

View File

@@ -6,6 +6,7 @@ import re
from .common import InfoExtractor
from ..compat import (
compat_urllib_parse,
compat_urlparse,
)
from ..utils import (
ExtractorError,
@@ -16,7 +17,7 @@ from ..utils import (
class NaverIE(InfoExtractor):
_VALID_URL = r'https?://(?:m\.)?tvcast\.naver\.com/v/(?P<id>\d+)'
_TEST = {
_TESTS = [{
'url': 'http://tvcast.naver.com/v/81652',
'info_dict': {
'id': '81652',
@@ -25,7 +26,18 @@ class NaverIE(InfoExtractor):
'description': '합격불변의 법칙 메가스터디 | 메가스터디 수학 김상희 선생님이 9월 모의고사 수학A형 16번에서 20번까지 해설강의를 공개합니다.',
'upload_date': '20130903',
},
}
}, {
'url': 'http://tvcast.naver.com/v/395837',
'md5': '638ed4c12012c458fefcddfd01f173cd',
'info_dict': {
'id': '395837',
'ext': 'mp4',
'title': '9년이 지나도 아픈 기억, 전효성의 아버지',
'description': 'md5:5bf200dcbf4b66eb1b350d1eb9c753f7',
'upload_date': '20150519',
},
'skip': 'Georestricted',
}]
def _real_extract(self, url):
video_id = self._match_id(url)
@@ -35,7 +47,7 @@ class NaverIE(InfoExtractor):
webpage)
if m_id is None:
m_error = re.search(
r'(?s)<div class="nation_error">\s*(?:<!--.*?-->)?\s*<p class="[^"]+">(?P<msg>.+?)</p>\s*</div>',
r'(?s)<div class="(?:nation_error|nation_box)">\s*(?:<!--.*?-->)?\s*<p class="[^"]+">(?P<msg>.+?)</p>\s*</div>',
webpage)
if m_error:
raise ExtractorError(clean_html(m_error.group('msg')), expected=True)
@@ -58,14 +70,18 @@ class NaverIE(InfoExtractor):
formats = []
for format_el in urls.findall('EncodingOptions/EncodingOption'):
domain = format_el.find('Domain').text
uri = format_el.find('uri').text
f = {
'url': domain + format_el.find('uri').text,
'url': compat_urlparse.urljoin(domain, uri),
'ext': 'mp4',
'width': int(format_el.find('width').text),
'height': int(format_el.find('height').text),
}
if domain.startswith('rtmp'):
# urlparse does not support custom schemes
# https://bugs.python.org/issue18828
f.update({
'url': domain + uri,
'ext': 'flv',
'rtmp_protocol': '1', # rtmpt
})

View File

@@ -22,6 +22,18 @@ class NBAIE(InfoExtractor):
}, {
'url': 'http://www.nba.com/video/games/hornets/2014/12/05/0021400276-nyk-cha-play5.nba/',
'only_matching': True,
}, {
'url': 'http://watch.nba.com/nba/video/channels/playoffs/2015/05/20/0041400301-cle-atl-recap.nba',
'info_dict': {
'id': '0041400301-cle-atl-recap.nba',
'ext': 'mp4',
'title': 'NBA GAME TIME | Video: Hawks vs. Cavaliers Game 1',
'description': 'md5:8094c3498d35a9bd6b1a8c396a071b4d',
'duration': 228,
},
'params': {
'skip_download': True,
}
}]
def _real_extract(self, url):
@@ -35,8 +47,12 @@ class NBAIE(InfoExtractor):
self._og_search_title(webpage, default=shortened_video_id), ' : NBA.com')
description = self._og_search_description(webpage)
duration = parse_duration(
self._html_search_meta('duration', webpage, 'duration'))
duration_str = self._html_search_meta(
'duration', webpage, 'duration', default=None)
if not duration_str:
duration_str = self._html_search_regex(
r'Duration:</b>\s*(\d+:\d+)', webpage, 'duration', fatal=False)
duration = parse_duration(duration_str)
return {
'id': shortened_video_id,

View File

@@ -10,6 +10,8 @@ from ..compat import (
from ..utils import (
ExtractorError,
find_xpath_attr,
lowercase_escape,
unescapeHTML,
)
@@ -37,14 +39,32 @@ class NBCIE(InfoExtractor):
},
'skip': 'Only works from US',
},
{
'url': 'http://www.nbc.com/saturday-night-live/video/star-wars-teaser/2832821',
'info_dict': {
'id': '8iUuyzWDdYUZ',
'ext': 'flv',
'title': 'Star Wars Teaser',
'description': 'md5:0b40f9cbde5b671a7ff62fceccc4f442',
},
'skip': 'Only works from US',
},
{
# This video has expired but with an escaped embedURL
'url': 'http://www.nbc.com/parenthood/episode-guide/season-5/just-like-at-home/515',
'skip': 'Expired'
}
]
def _real_extract(self, url):
video_id = self._match_id(url)
webpage = self._download_webpage(url, video_id)
theplatform_url = self._search_regex(
'(?:class="video-player video-player-full" data-mpx-url|class="player" src)="(.*?)"',
webpage, 'theplatform url').replace('_no_endcard', '')
theplatform_url = unescapeHTML(lowercase_escape(self._html_search_regex(
[
r'(?:class="video-player video-player-full" data-mpx-url|class="player" src)="(.*?)"',
r'"embedURL"\s*:\s*"([^"]+)"'
],
webpage, 'theplatform url').replace('_no_endcard', '').replace('\\/', '/')))
if theplatform_url.startswith('//'):
theplatform_url = 'http:' + theplatform_url
return self.url_result(theplatform_url)

View File

@@ -8,41 +8,11 @@ from ..utils import (
ExtractorError,
int_or_none,
qualities,
parse_duration,
)
class NDRIE(InfoExtractor):
IE_NAME = 'ndr'
IE_DESC = 'NDR.de - Mediathek'
_VALID_URL = r'https?://www\.ndr\.de/.+?(?P<id>\d+)\.html'
_TESTS = [
{
'url': 'http://www.ndr.de/fernsehen/sendungen/nordmagazin/Kartoffeltage-in-der-Lewitz,nordmagazin25866.html',
'md5': '5bc5f5b92c82c0f8b26cddca34f8bb2c',
'note': 'Video file',
'info_dict': {
'id': '25866',
'ext': 'mp4',
'title': 'Kartoffeltage in der Lewitz',
'description': 'md5:48c4c04dde604c8a9971b3d4e3b9eaa8',
'duration': 166,
}
},
{
'url': 'http://www.ndr.de/info/audio51535.html',
'md5': 'bb3cd38e24fbcc866d13b50ca59307b8',
'note': 'Audio file',
'info_dict': {
'id': '51535',
'ext': 'mp3',
'title': 'La Valette entgeht der Hinrichtung',
'description': 'md5:22f9541913a40fe50091d5cdd7c9f536',
'duration': 884,
}
}
]
class NDRBaseIE(InfoExtractor):
def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)
video_id = mobj.group('id')
@@ -54,7 +24,11 @@ class NDRIE(InfoExtractor):
if description:
description = description.strip()
duration = int_or_none(self._html_search_regex(r'duration: (\d+),\n', page, 'duration', fatal=False))
duration = int_or_none(self._html_search_regex(r'duration: (\d+),\n', page, 'duration', default=None))
if not duration:
duration = parse_duration(self._html_search_regex(
r'(<span class="min">\d+</span>:<span class="sec">\d+</span>)',
page, 'duration', default=None))
formats = []
@@ -92,3 +66,65 @@ class NDRIE(InfoExtractor):
'duration': duration,
'formats': formats,
}
class NDRIE(NDRBaseIE):
IE_NAME = 'ndr'
IE_DESC = 'NDR.de - Mediathek'
_VALID_URL = r'https?://www\.ndr\.de/.+?(?P<id>\d+)\.html'
_TESTS = [
{
'url': 'http://www.ndr.de/fernsehen/sendungen/nordmagazin/Kartoffeltage-in-der-Lewitz,nordmagazin25866.html',
'md5': '5bc5f5b92c82c0f8b26cddca34f8bb2c',
'note': 'Video file',
'info_dict': {
'id': '25866',
'ext': 'mp4',
'title': 'Kartoffeltage in der Lewitz',
'description': 'md5:48c4c04dde604c8a9971b3d4e3b9eaa8',
'duration': 166,
},
'skip': '404 Not found',
},
{
'url': 'http://www.ndr.de/fernsehen/Party-Poette-und-Parade,hafengeburtstag988.html',
'md5': 'dadc003c55ae12a5d2f6bd436cd73f59',
'info_dict': {
'id': '988',
'ext': 'mp4',
'title': 'Party, Pötte und Parade',
'description': 'Hunderttausende feiern zwischen Speicherstadt und St. Pauli den 826. Hafengeburtstag. Die NDR Sondersendung zeigt die schönsten und spektakulärsten Bilder vom Auftakt.',
'duration': 3498,
},
},
{
'url': 'http://www.ndr.de/info/audio51535.html',
'md5': 'bb3cd38e24fbcc866d13b50ca59307b8',
'note': 'Audio file',
'info_dict': {
'id': '51535',
'ext': 'mp3',
'title': 'La Valette entgeht der Hinrichtung',
'description': 'md5:22f9541913a40fe50091d5cdd7c9f536',
'duration': 884,
}
}
]
class NJoyIE(NDRBaseIE):
IE_NAME = 'N-JOY'
_VALID_URL = r'https?://www\.n-joy\.de/.+?(?P<id>\d+)\.html'
_TEST = {
'url': 'http://www.n-joy.de/entertainment/comedy/comedy_contest/Benaissa-beim-NDR-Comedy-Contest,comedycontest2480.html',
'md5': 'cb63be60cd6f9dd75218803146d8dc67',
'info_dict': {
'id': '2480',
'ext': 'mp4',
'title': 'Benaissa beim NDR Comedy Contest',
'description': 'Von seinem sehr "behaarten" Leben lässt sich Benaissa trotz aller Schwierigkeiten nicht unterkriegen.',
'duration': 654,
}
}

View File

@@ -49,7 +49,7 @@ class NetzkinoIE(InfoExtractor):
'http://www.netzkino.de/beta/dist/production.min.js', video_id,
note='Downloading player code')
avo_js = self._search_regex(
r'window\.avoCore\s*=.*?urlTemplate:\s*(\{.*?"\})',
r'var urlTemplate=(\{.*?"\})',
production_js, 'URL templates')
templates = self._parse_json(
avo_js, video_id, transform_source=js_to_json)

View File

@@ -31,7 +31,7 @@ class NewstubeIE(InfoExtractor):
page = self._download_webpage(url, video_id, 'Downloading page')
video_guid = self._html_search_regex(
r'<meta property="og:video" content="https?://(?:www\.)?newstube\.ru/freshplayer\.swf\?guid=(?P<guid>[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12})',
r'<meta property="og:video:url" content="https?://(?:www\.)?newstube\.ru/freshplayer\.swf\?guid=(?P<guid>[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12})',
page, 'video GUID')
player = self._download_xml(

View File

@@ -89,8 +89,8 @@ class NextMediaActionNewsIE(NextMediaIE):
return self._extract_from_nextmedia_page(news_id, url, article_page)
class AppleDailyRealtimeNewsIE(NextMediaIE):
_VALID_URL = r'http://(www|ent).appledaily.com.tw/(realtimenews|enews)/[^/]+/[^/]+/(?P<date>\d+)/(?P<id>\d+)(/.*)?'
class AppleDailyIE(NextMediaIE):
_VALID_URL = r'http://(www|ent).appledaily.com.tw/(?:animation|appledaily|enews|realtimenews)/[^/]+/[^/]+/(?P<date>\d+)/(?P<id>\d+)(/.*)?'
_TESTS = [{
'url': 'http://ent.appledaily.com.tw/enews/article/entertainment/20150128/36354694',
'md5': 'a843ab23d150977cc55ef94f1e2c1e4d',
@@ -99,7 +99,7 @@ class AppleDailyRealtimeNewsIE(NextMediaIE):
'ext': 'mp4',
'title': '周亭羽走過摩鐵陰霾2男陪吃 九把刀孤寒看醫生',
'thumbnail': 're:^https?://.*\.jpg$',
'description': 'md5:b23787119933404ce515c6356a8c355c',
'description': 'md5:2acd430e59956dc47cd7f67cb3c003f4',
'upload_date': '20150128',
}
}, {
@@ -110,26 +110,10 @@ class AppleDailyRealtimeNewsIE(NextMediaIE):
'ext': 'mp4',
'title': '不滿被踩腳 山東兩大媽一路打下車',
'thumbnail': 're:^https?://.*\.jpg$',
'description': 'md5:2648aaf6fc4f401f6de35a91d111aa1d',
'description': 'md5:175b4260c1d7c085993474217e4ab1b4',
'upload_date': '20150128',
}
}]
_URL_PATTERN = r'\{url: \'(.+)\'\}'
def _fetch_title(self, page):
return self._html_search_regex(r'<h1 id="h1">([^<>]+)</h1>', page, 'news title')
def _fetch_thumbnail(self, page):
return self._html_search_regex(r"setInitialImage\(\'([^']+)'\)", page, 'video thumbnail', fatal=False)
def _fetch_timestamp(self, page):
return None
class AppleDailyAnimationNewsIE(AppleDailyRealtimeNewsIE):
_VALID_URL = 'http://www.appledaily.com.tw/animation/[^/]+/[^/]+/(?P<date>\d+)/(?P<id>\d+)(/.*)?'
_TESTS = [{
}, {
'url': 'http://www.appledaily.com.tw/animation/realtimenews/new/20150128/5003671',
'md5': '03df296d95dedc2d5886debbb80cb43f',
'info_dict': {
@@ -154,10 +138,22 @@ class AppleDailyAnimationNewsIE(AppleDailyRealtimeNewsIE):
'expected_warnings': [
'video thumbnail',
]
}, {
'url': 'http://www.appledaily.com.tw/appledaily/article/supplement/20140417/35770334/',
'only_matching': True,
}]
_URL_PATTERN = r'\{url: \'(.+)\'\}'
def _fetch_title(self, page):
return self._html_search_meta('description', page, 'news title')
return (self._html_search_regex(r'<h1 id="h1">([^<>]+)</h1>', page, 'news title', default=None) or
self._html_search_meta('description', page, 'news title'))
def _fetch_thumbnail(self, page):
return self._html_search_regex(r"setInitialImage\(\'([^']+)'\)", page, 'video thumbnail', fatal=False)
def _fetch_timestamp(self, page):
return None
def _fetch_description(self, page):
return self._html_search_meta('description', page, 'news description')

View File

@@ -19,7 +19,7 @@ class NFLIE(InfoExtractor):
_VALID_URL = r'''(?x)https?://
(?P<host>(?:www\.)?(?:nfl\.com|.*?\.clubs\.nfl\.com))/
(?:.+?/)*
(?P<id>(?:\d[a-z]{2}\d{13}|\w{8}\-(?:\w{4}\-){3}\w{12}))'''
(?P<id>(?:[a-z0-9]{16}|\w{8}\-(?:\w{4}\-){3}\w{12}))'''
_TESTS = [
{
'url': 'http://www.nfl.com/videos/nfl-game-highlights/0ap3000000398478/Week-3-Redskins-vs-Eagles-highlights',
@@ -58,6 +58,10 @@ class NFLIE(InfoExtractor):
'upload_date': '20150202',
},
},
{
'url': 'http://www.nfl.com/videos/nfl-network-top-ten/09000d5d810a6bd4/Top-10-Gutsiest-Performances-Jack-Youngblood',
'only_matching': True,
}
]
@staticmethod

View File

@@ -21,6 +21,9 @@ class NHLBaseInfoExtractor(InfoExtractor):
return json_string.replace('\\\'', '\'')
def _real_extract_video(self, video_id):
vid_parts = video_id.split(',')
if len(vid_parts) == 3:
video_id = '%s0%s%s-X-h' % (vid_parts[0][:4], vid_parts[1], vid_parts[2].rjust(4, '0'))
json_url = 'http://video.nhl.com/videocenter/servlets/playlist?ids=%s&format=json' % video_id
data = self._download_json(
json_url, video_id, transform_source=self._fix_json)
@@ -47,7 +50,7 @@ class NHLBaseInfoExtractor(InfoExtractor):
video_url = initial_video_url
join = compat_urlparse.urljoin
return {
ret = {
'id': video_id,
'title': info['name'],
'url': video_url,
@@ -56,11 +59,20 @@ class NHLBaseInfoExtractor(InfoExtractor):
'thumbnail': join(join(video_url, '/u/'), info['bigImage']),
'upload_date': unified_strdate(info['releaseDate'].split('.')[0]),
}
if video_url.startswith('rtmp:'):
mobj = re.match(r'(?P<tc_url>rtmp://[^/]+/(?P<app>[a-z0-9/]+))/(?P<play_path>mp4:.*)', video_url)
ret.update({
'tc_url': mobj.group('tc_url'),
'play_path': mobj.group('play_path'),
'app': mobj.group('app'),
'no_resume': True,
})
return ret
class NHLIE(NHLBaseInfoExtractor):
IE_NAME = 'nhl.com'
_VALID_URL = r'https?://video(?P<team>\.[^.]*)?\.nhl\.com/videocenter/(?:console)?(?:\?(?:.*?[?&])?)id=(?P<id>[-0-9a-zA-Z]+)'
_VALID_URL = r'https?://video(?P<team>\.[^.]*)?\.nhl\.com/videocenter/(?:console)?(?:\?(?:.*?[?&])?)(?:id|hlg)=(?P<id>[-0-9a-zA-Z,]+)'
_TESTS = [{
'url': 'http://video.canucks.nhl.com/videocenter/console?catid=6?id=453614',
@@ -101,6 +113,29 @@ class NHLIE(NHLBaseInfoExtractor):
}, {
'url': 'http://video.nhl.com/videocenter/?id=736722',
'only_matching': True,
}, {
'url': 'http://video.nhl.com/videocenter/console?hlg=20142015,2,299&lang=en',
'md5': '076fcb88c255154aacbf0a7accc3f340',
'info_dict': {
'id': '2014020299-X-h',
'ext': 'mp4',
'title': 'Penguins at Islanders / Game Highlights',
'description': 'Home broadcast - Pittsburgh Penguins at New York Islanders - November 22, 2014',
'duration': 268,
'upload_date': '20141122',
}
}, {
'url': 'http://video.oilers.nhl.com/videocenter/console?id=691469&catid=4',
'info_dict': {
'id': '691469',
'ext': 'mp4',
'title': 'RAW | Craig MacTavish Full Press Conference',
'description': 'Oilers GM Craig MacTavish addresses the media at Rexall Place on Friday.',
'upload_date': '20141205',
},
'params': {
'skip_download': True, # Requires rtmpdump
}
}]
def _real_extract(self, url):

View File

@@ -3,6 +3,7 @@ from __future__ import unicode_literals
import re
import json
import datetime
from .common import InfoExtractor
from ..compat import (
@@ -14,7 +15,9 @@ from ..utils import (
ExtractorError,
int_or_none,
parse_duration,
unified_strdate,
parse_iso8601,
xpath_text,
determine_ext,
)
@@ -32,30 +35,50 @@ class NiconicoIE(InfoExtractor):
'uploader': 'takuya0301',
'uploader_id': '2698420',
'upload_date': '20131123',
'timestamp': 1385182762,
'description': '(c) copyright 2008, Blender Foundation / www.bigbuckbunny.org',
'duration': 33,
},
'params': {
'username': 'ydl.niconico@gmail.com',
'password': 'youtube-dl',
},
}, {
# File downloaded with and without credentials are different, so omit
# the md5 field
'url': 'http://www.nicovideo.jp/watch/nm14296458',
'md5': '8db08e0158457cf852a31519fceea5bc',
'info_dict': {
'id': 'nm14296458',
'ext': 'swf',
'title': '【鏡音リン】Dance on media【オリジナル】take2!',
'description': 'md5:',
'description': 'md5:689f066d74610b3b22e0f1739add0f58',
'uploader': 'りょうた',
'uploader_id': '18822557',
'upload_date': '20110429',
'timestamp': 1304065916,
'duration': 209,
},
'params': {
'username': 'ydl.niconico@gmail.com',
'password': 'youtube-dl',
}, {
# 'video exists but is marked as "deleted"
# md5 is unstable
'url': 'http://www.nicovideo.jp/watch/sm10000',
'info_dict': {
'id': 'sm10000',
'ext': 'unknown_video',
'description': 'deleted',
'title': 'ドラえもんエターナル第3話「決戦第3新東京市」前編',
'upload_date': '20071224',
'timestamp': 1198527840, # timestamp field has different value if logged in
'duration': 304,
},
}, {
'url': 'http://www.nicovideo.jp/watch/so22543406',
'info_dict': {
'id': '1388129933',
'ext': 'mp4',
'title': '【第1回】RADIOアニメロミックス ラブライブのぞえりRadio Garden',
'description': 'md5:b27d224bb0ff53d3c8269e9f8b561cf1',
'timestamp': 1388851200,
'upload_date': '20140104',
'uploader': 'アニメロチャンネル',
'uploader_id': '312',
}
}]
_VALID_URL = r'https?://(?:www\.|secure\.)?nicovideo\.jp/watch/(?P<id>(?:[a-z]{2})?[0-9]+)'
@@ -95,9 +118,13 @@ class NiconicoIE(InfoExtractor):
def _real_extract(self, url):
video_id = self._match_id(url)
# Get video webpage. We are not actually interested in it, but need
# the cookies in order to be able to download the info webpage
self._download_webpage('http://www.nicovideo.jp/watch/' + video_id, video_id)
# Get video webpage. We are not actually interested in it for normal
# cases, but need the cookies in order to be able to download the
# info webpage
webpage, handle = self._download_webpage_handle(
'http://www.nicovideo.jp/watch/' + video_id, video_id)
if video_id.startswith('so'):
video_id = self._match_id(handle.geturl())
video_info = self._download_xml(
'http://ext.nicovideo.jp/api/getthumbinfo/' + video_id, video_id,
@@ -127,22 +154,77 @@ class NiconicoIE(InfoExtractor):
flv_info_request, video_id,
note='Downloading flv info', errnote='Unable to download flv info')
if 'deleted=' in flv_info_webpage:
raise ExtractorError('The video has been deleted.',
expected=True)
video_real_url = compat_urlparse.parse_qs(flv_info_webpage)['url'][0]
flv_info = compat_urlparse.parse_qs(flv_info_webpage)
if 'url' not in flv_info:
if 'deleted' in flv_info:
raise ExtractorError('The video has been deleted.',
expected=True)
else:
raise ExtractorError('Unable to find video URL')
video_real_url = flv_info['url'][0]
# Start extracting information
title = video_info.find('.//title').text
extension = video_info.find('.//movie_type').text
video_format = extension.upper()
thumbnail = video_info.find('.//thumbnail_url').text
description = video_info.find('.//description').text
upload_date = unified_strdate(video_info.find('.//first_retrieve').text.split('+')[0])
view_count = int_or_none(video_info.find('.//view_counter').text)
comment_count = int_or_none(video_info.find('.//comment_num').text)
duration = parse_duration(video_info.find('.//length').text)
webpage_url = video_info.find('.//watch_url').text
title = xpath_text(video_info, './/title')
if not title:
title = self._og_search_title(webpage, default=None)
if not title:
title = self._html_search_regex(
r'<span[^>]+class="videoHeaderTitle"[^>]*>([^<]+)</span>',
webpage, 'video title')
watch_api_data_string = self._html_search_regex(
r'<div[^>]+id="watchAPIDataContainer"[^>]+>([^<]+)</div>',
webpage, 'watch api data', default=None)
watch_api_data = self._parse_json(watch_api_data_string, video_id) if watch_api_data_string else {}
video_detail = watch_api_data.get('videoDetail', {})
extension = xpath_text(video_info, './/movie_type')
if not extension:
extension = determine_ext(video_real_url)
thumbnail = (
xpath_text(video_info, './/thumbnail_url') or
self._html_search_meta('image', webpage, 'thumbnail', default=None) or
video_detail.get('thumbnail'))
description = xpath_text(video_info, './/description')
timestamp = parse_iso8601(xpath_text(video_info, './/first_retrieve'))
if not timestamp:
match = self._html_search_meta('datePublished', webpage, 'date published', default=None)
if match:
timestamp = parse_iso8601(match.replace('+', ':00+'))
if not timestamp and video_detail.get('postedAt'):
timestamp = parse_iso8601(
video_detail['postedAt'].replace('/', '-'),
delimiter=' ', timezone=datetime.timedelta(hours=9))
view_count = int_or_none(xpath_text(video_info, './/view_counter'))
if not view_count:
match = self._html_search_regex(
r'>Views: <strong[^>]*>([^<]+)</strong>',
webpage, 'view count', default=None)
if match:
view_count = int_or_none(match.replace(',', ''))
view_count = view_count or video_detail.get('viewCount')
comment_count = int_or_none(xpath_text(video_info, './/comment_num'))
if not comment_count:
match = self._html_search_regex(
r'>Comments: <strong[^>]*>([^<]+)</strong>',
webpage, 'comment count', default=None)
if match:
comment_count = int_or_none(match.replace(',', ''))
comment_count = comment_count or video_detail.get('commentCount')
duration = (parse_duration(
xpath_text(video_info, './/length') or
self._html_search_meta(
'video:duration', webpage, 'video duration', default=None)) or
video_detail.get('length'))
webpage_url = xpath_text(video_info, './/watch_url') or url
if video_info.find('.//ch_id') is not None:
uploader_id = video_info.find('.//ch_id').text
@@ -158,11 +240,11 @@ class NiconicoIE(InfoExtractor):
'url': video_real_url,
'title': title,
'ext': extension,
'format': video_format,
'format_id': 'economy' if video_real_url.endswith('low') else 'normal',
'thumbnail': thumbnail,
'description': description,
'uploader': uploader,
'upload_date': upload_date,
'timestamp': timestamp,
'uploader_id': uploader_id,
'view_count': view_count,
'comment_count': comment_count,

View File

@@ -14,7 +14,9 @@ from ..compat import (
from ..utils import (
clean_html,
ExtractorError,
unified_strdate,
int_or_none,
float_or_none,
parse_iso8601,
)
@@ -25,21 +27,38 @@ class NocoIE(InfoExtractor):
_SUB_LANG_TEMPLATE = '&sub_lang=%s'
_NETRC_MACHINE = 'noco'
_TEST = {
'url': 'http://noco.tv/emission/11538/nolife/ami-ami-idol-hello-france/',
'md5': '0a993f0058ddbcd902630b2047ef710e',
'info_dict': {
'id': '11538',
'ext': 'mp4',
'title': 'Ami Ami Idol - Hello! France',
'description': 'md5:4eaab46ab68fa4197a317a88a53d3b86',
'upload_date': '20140412',
'uploader': 'Nolife',
'uploader_id': 'NOL',
'duration': 2851.2,
_TESTS = [
{
'url': 'http://noco.tv/emission/11538/nolife/ami-ami-idol-hello-france/',
'md5': '0a993f0058ddbcd902630b2047ef710e',
'info_dict': {
'id': '11538',
'ext': 'mp4',
'title': 'Ami Ami Idol - Hello! France',
'description': 'md5:4eaab46ab68fa4197a317a88a53d3b86',
'upload_date': '20140412',
'uploader': 'Nolife',
'uploader_id': 'NOL',
'duration': 2851.2,
},
'skip': 'Requires noco account',
},
'skip': 'Requires noco account',
}
{
'url': 'http://noco.tv/emission/12610/lbl42/the-guild/s01e01-wake-up-call',
'md5': 'c190f1f48e313c55838f1f412225934d',
'info_dict': {
'id': '12610',
'ext': 'mp4',
'title': 'The Guild #1 - Wake-Up Call',
'timestamp': 1403863200,
'upload_date': '20140627',
'uploader': 'LBL42',
'uploader_id': 'LBL',
'duration': 233.023,
},
'skip': 'Requires noco account',
}
]
def _real_initialize(self):
self._login()
@@ -90,51 +109,70 @@ class NocoIE(InfoExtractor):
'shows/%s/medias' % video_id,
video_id, 'Downloading video JSON')
show = self._call_api(
'shows/by_id/%s' % video_id,
video_id, 'Downloading show JSON')[0]
options = self._call_api(
'users/init', video_id,
'Downloading user options JSON')['options']
audio_lang_pref = options.get('audio_language') or options.get('language', 'fr')
if audio_lang_pref == 'original':
audio_lang_pref = show['original_lang']
if len(medias) == 1:
audio_lang_pref = list(medias.keys())[0]
elif audio_lang_pref not in medias:
audio_lang_pref = 'fr'
qualities = self._call_api(
'qualities',
video_id, 'Downloading qualities JSON')
formats = []
for lang, lang_dict in medias['fr']['video_list'].items():
for format_id, fmt in lang_dict['quality_list'].items():
format_id_extended = '%s-%s' % (lang, format_id) if lang != 'none' else format_id
for audio_lang, audio_lang_dict in medias.items():
preference = 1 if audio_lang == audio_lang_pref else 0
for sub_lang, lang_dict in audio_lang_dict['video_list'].items():
for format_id, fmt in lang_dict['quality_list'].items():
format_id_extended = 'audio-%s_sub-%s_%s' % (audio_lang, sub_lang, format_id)
video = self._call_api(
'shows/%s/video/%s/fr' % (video_id, format_id.lower()),
video_id, 'Downloading %s video JSON' % format_id_extended,
lang if lang != 'none' else None)
video = self._call_api(
'shows/%s/video/%s/%s' % (video_id, format_id.lower(), audio_lang),
video_id, 'Downloading %s video JSON' % format_id_extended,
sub_lang if sub_lang != 'none' else None)
file_url = video['file']
if not file_url:
continue
file_url = video['file']
if not file_url:
continue
if file_url in ['forbidden', 'not found']:
popmessage = video['popmessage']
self._raise_error(popmessage['title'], popmessage['message'])
if file_url in ['forbidden', 'not found']:
popmessage = video['popmessage']
self._raise_error(popmessage['title'], popmessage['message'])
formats.append({
'url': file_url,
'format_id': format_id_extended,
'width': fmt['res_width'],
'height': fmt['res_lines'],
'abr': fmt['audiobitrate'],
'vbr': fmt['videobitrate'],
'filesize': fmt['filesize'],
'format_note': qualities[format_id]['quality_name'],
'preference': qualities[format_id]['priority'],
})
formats.append({
'url': file_url,
'format_id': format_id_extended,
'width': int_or_none(fmt.get('res_width')),
'height': int_or_none(fmt.get('res_lines')),
'abr': int_or_none(fmt.get('audiobitrate')),
'vbr': int_or_none(fmt.get('videobitrate')),
'filesize': int_or_none(fmt.get('filesize')),
'format_note': qualities[format_id].get('quality_name'),
'quality': qualities[format_id].get('priority'),
'preference': preference,
})
self._sort_formats(formats)
show = self._call_api(
'shows/by_id/%s' % video_id,
video_id, 'Downloading show JSON')[0]
timestamp = parse_iso8601(show.get('online_date_start_utc'), ' ')
upload_date = unified_strdate(show['online_date_start_utc'])
uploader = show['partner_name']
uploader_id = show['partner_key']
duration = show['duration_ms'] / 1000.0
if timestamp is not None and timestamp < 0:
timestamp = None
uploader = show.get('partner_name')
uploader_id = show.get('partner_key')
duration = float_or_none(show.get('duration_ms'), 1000)
thumbnails = []
for thumbnail_key, thumbnail_url in show.items():
@@ -157,7 +195,7 @@ class NocoIE(InfoExtractor):
if episode_number:
title += ' #' + compat_str(episode_number)
if episode:
title += ' - ' + episode
title += ' - ' + compat_str(episode)
description = show.get('show_resume') or show.get('family_resume')
@@ -166,7 +204,7 @@ class NocoIE(InfoExtractor):
'title': title,
'description': description,
'thumbnails': thumbnails,
'upload_date': upload_date,
'timestamp': timestamp,
'uploader': uploader,
'uploader_id': uploader_id,
'duration': duration,

View File

@@ -0,0 +1,179 @@
# encoding: utf-8
from __future__ import unicode_literals
import re
from .common import InfoExtractor
from ..utils import (
clean_html,
unified_strdate,
)
class NovaIE(InfoExtractor):
IE_DESC = 'TN.cz, Prásk.tv, Nova.cz, Novaplus.cz, FANDA.tv, Krásná.cz and Doma.cz'
_VALID_URL = 'http://(?:[^.]+\.)?(?P<site>tv(?:noviny)?|tn|novaplus|vymena|fanda|krasna|doma|prask)\.nova\.cz/(?:[^/]+/)+(?P<id>[^/]+?)(?:\.html|/|$)'
_TESTS = [{
'url': 'http://tvnoviny.nova.cz/clanek/novinky/co-na-sebe-sportaci-praskli-vime-jestli-pujde-hrdlicka-na-materskou.html?utm_source=tvnoviny&utm_medium=cpfooter&utm_campaign=novaplus',
'info_dict': {
'id': '1608920',
'display_id': 'co-na-sebe-sportaci-praskli-vime-jestli-pujde-hrdlicka-na-materskou',
'ext': 'flv',
'title': 'Duel: Michal Hrdlička a Petr Suchoň',
'description': 'md5:d0cc509858eee1b1374111c588c6f5d5',
'thumbnail': 're:^https?://.*\.(?:jpg)',
},
'params': {
# rtmp download
'skip_download': True,
}
}, {
'url': 'http://tn.nova.cz/clanek/tajemstvi-ukryte-v-podzemi-specialni-nemocnice-v-prazske-krci.html#player_13260',
'md5': '1dd7b9d5ea27bc361f110cd855a19bd3',
'info_dict': {
'id': '1757139',
'display_id': 'tajemstvi-ukryte-v-podzemi-specialni-nemocnice-v-prazske-krci',
'ext': 'mp4',
'title': 'Podzemní nemocnice v pražské Krči',
'description': 'md5:f0a42dd239c26f61c28f19e62d20ef53',
'thumbnail': 're:^https?://.*\.(?:jpg)',
}
}, {
'url': 'http://novaplus.nova.cz/porad/policie-modrava/video/5591-policie-modrava-15-dil-blondynka-na-hrbitove',
'info_dict': {
'id': '1756825',
'display_id': '5591-policie-modrava-15-dil-blondynka-na-hrbitove',
'ext': 'flv',
'title': 'Policie Modrava - 15. díl - Blondýnka na hřbitově',
'description': 'md5:dc24e50be5908df83348e50d1431295e', # Make sure this description is clean of html tags
'thumbnail': 're:^https?://.*\.(?:jpg)',
},
'params': {
# rtmp download
'skip_download': True,
}
}, {
'url': 'http://novaplus.nova.cz/porad/televizni-noviny/video/5585-televizni-noviny-30-5-2015/',
'info_dict': {
'id': '1756858',
'ext': 'flv',
'title': 'Televizní noviny - 30. 5. 2015',
'thumbnail': 're:^https?://.*\.(?:jpg)',
'upload_date': '20150530',
},
'params': {
# rtmp download
'skip_download': True,
}
}, {
'url': 'http://fanda.nova.cz/clanek/fun-and-games/krvavy-epos-zaklinac-3-divoky-hon-vychazi-vyhrajte-ho-pro-sebe.html',
'info_dict': {
'id': '1753621',
'ext': 'mp4',
'title': 'Zaklínač 3: Divoký hon',
'description': 're:.*Pokud se stejně jako my nemůžete.*',
'thumbnail': 're:https?://.*\.jpg(\?.*)?',
'upload_date': '20150521',
},
'params': {
# rtmp download
'skip_download': True,
}
}, {
'url': 'http://sport.tn.nova.cz/clanek/sport/hokej/nhl/zivot-jde-dal-hodnotil-po-vyrazeni-z-playoff-jiri-sekac.html',
'only_matching': True,
}, {
'url': 'http://fanda.nova.cz/clanek/fun-and-games/krvavy-epos-zaklinac-3-divoky-hon-vychazi-vyhrajte-ho-pro-sebe.html',
'only_matching': True,
}, {
'url': 'http://doma.nova.cz/clanek/zdravi/prijdte-se-zapsat-do-registru-kostni-drene-jiz-ve-stredu-3-cervna.html',
'only_matching': True,
}, {
'url': 'http://prask.nova.cz/clanek/novinky/co-si-na-sobe-nase-hvezdy-nechaly-pojistit.html',
'only_matching': True,
}, {
'url': 'http://tv.nova.cz/clanek/novinky/zivot-je-zivot-bondovsky-trailer.html',
'only_matching': True,
}]
def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)
display_id = mobj.group('id')
site = mobj.group('site')
webpage = self._download_webpage(url, display_id)
video_id = self._search_regex(
[r"(?:media|video_id)\s*:\s*'(\d+)'",
r'media=(\d+)',
r'id="article_video_(\d+)"',
r'id="player_(\d+)"'],
webpage, 'video id')
config_url = self._search_regex(
r'src="(http://tn\.nova\.cz/bin/player/videojs/config\.php\?[^"]+)"',
webpage, 'config url', default=None)
if not config_url:
DEFAULT_SITE_ID = '23000'
SITES = {
'tvnoviny': DEFAULT_SITE_ID,
'novaplus': DEFAULT_SITE_ID,
'vymena': DEFAULT_SITE_ID,
'krasna': DEFAULT_SITE_ID,
'fanda': '30',
'tn': '30',
'doma': '30',
}
site_id = self._search_regex(
r'site=(\d+)', webpage, 'site id', default=None) or SITES.get(site, DEFAULT_SITE_ID)
config_url = ('http://tn.nova.cz/bin/player/videojs/config.php?site=%s&media=%s&jsVar=vjsconfig'
% (site_id, video_id))
config = self._download_json(
config_url, display_id,
'Downloading config JSON',
transform_source=lambda s: s[s.index('{'):s.rindex('}') + 1])
mediafile = config['mediafile']
video_url = mediafile['src']
m = re.search(r'^(?P<url>rtmpe?://[^/]+/(?P<app>[^/]+?))/&*(?P<playpath>.+)$', video_url)
if m:
formats = [{
'url': m.group('url'),
'app': m.group('app'),
'play_path': m.group('playpath'),
'player_path': 'http://tvnoviny.nova.cz/static/shared/app/videojs/video-js.swf',
'ext': 'flv',
}]
else:
formats = [{
'url': video_url,
}]
self._sort_formats(formats)
title = mediafile.get('meta', {}).get('title') or self._og_search_title(webpage)
description = clean_html(self._og_search_description(webpage, default=None))
thumbnail = config.get('poster')
if site == 'novaplus':
upload_date = unified_strdate(self._search_regex(
r'(\d{1,2}-\d{1,2}-\d{4})$', display_id, 'upload date', default=None))
elif site == 'fanda':
upload_date = unified_strdate(self._search_regex(
r'<span class="date_time">(\d{1,2}\.\d{1,2}\.\d{4})', webpage, 'upload date', default=None))
else:
upload_date = None
return {
'id': video_id,
'display_id': display_id,
'title': title,
'description': description,
'upload_date': upload_date,
'thumbnail': thumbnail,
'formats': formats,
}

View File

@@ -0,0 +1,192 @@
# coding: utf-8
from __future__ import unicode_literals
import re
from .common import InfoExtractor
from ..compat import compat_str
from ..utils import (
ExtractorError,
int_or_none,
parse_iso8601,
parse_duration,
remove_start,
)
class NowTVIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?nowtv\.de/(?P<station>rtl|rtl2|rtlnitro|superrtl|ntv|vox)/(?P<id>.+?)/player'
_TESTS = [{
# rtl
'url': 'http://www.nowtv.de/rtl/bauer-sucht-frau/die-neuen-bauern-und-eine-hochzeit/player',
'info_dict': {
'id': '203519',
'display_id': 'bauer-sucht-frau/die-neuen-bauern-und-eine-hochzeit',
'ext': 'mp4',
'title': 'Die neuen Bauern und eine Hochzeit',
'description': 'md5:e234e1ed6d63cf06be5c070442612e7e',
'thumbnail': 're:^https?://.*\.jpg$',
'timestamp': 1432580700,
'upload_date': '20150525',
'duration': 2786,
},
'params': {
# m3u8 download
'skip_download': True,
},
}, {
# rtl2
'url': 'http://www.nowtv.de/rtl2/berlin-tag-nacht/berlin-tag-nacht-folge-934/player',
'info_dict': {
'id': '203481',
'display_id': 'berlin-tag-nacht/berlin-tag-nacht-folge-934',
'ext': 'mp4',
'title': 'Berlin - Tag & Nacht (Folge 934)',
'description': 'md5:c85e88c2e36c552dfe63433bc9506dd0',
'thumbnail': 're:^https?://.*\.jpg$',
'timestamp': 1432666800,
'upload_date': '20150526',
'duration': 2641,
},
'params': {
# m3u8 download
'skip_download': True,
},
}, {
# rtlnitro
'url': 'http://www.nowtv.de/rtlnitro/alarm-fuer-cobra-11-die-autobahnpolizei/hals-und-beinbruch-2014-08-23-21-10-00/player',
'info_dict': {
'id': '165780',
'display_id': 'alarm-fuer-cobra-11-die-autobahnpolizei/hals-und-beinbruch-2014-08-23-21-10-00',
'ext': 'mp4',
'title': 'Hals- und Beinbruch',
'description': 'md5:b50d248efffe244e6f56737f0911ca57',
'thumbnail': 're:^https?://.*\.jpg$',
'timestamp': 1432415400,
'upload_date': '20150523',
'duration': 2742,
},
'params': {
# m3u8 download
'skip_download': True,
},
}, {
# superrtl
'url': 'http://www.nowtv.de/superrtl/medicopter-117/angst/player',
'info_dict': {
'id': '99205',
'display_id': 'medicopter-117/angst',
'ext': 'mp4',
'title': 'Angst!',
'description': 'md5:30cbc4c0b73ec98bcd73c9f2a8c17c4e',
'thumbnail': 're:^https?://.*\.jpg$',
'timestamp': 1222632900,
'upload_date': '20080928',
'duration': 3025,
},
'params': {
# m3u8 download
'skip_download': True,
},
}, {
# ntv
'url': 'http://www.nowtv.de/ntv/ratgeber-geld/thema-ua-der-erste-blick-die-apple-watch/player',
'info_dict': {
'id': '203521',
'display_id': 'ratgeber-geld/thema-ua-der-erste-blick-die-apple-watch',
'ext': 'mp4',
'title': 'Thema u.a.: Der erste Blick: Die Apple Watch',
'description': 'md5:4312b6c9d839ffe7d8caf03865a531af',
'thumbnail': 're:^https?://.*\.jpg$',
'timestamp': 1432751700,
'upload_date': '20150527',
'duration': 1083,
},
'params': {
# m3u8 download
'skip_download': True,
},
}, {
# vox
'url': 'http://www.nowtv.de/vox/der-hundeprofi/buero-fall-chihuahua-joel/player',
'info_dict': {
'id': '128953',
'display_id': 'der-hundeprofi/buero-fall-chihuahua-joel',
'ext': 'mp4',
'title': "Büro-Fall / Chihuahua 'Joel'",
'description': 'md5:e62cb6bf7c3cc669179d4f1eb279ad8d',
'thumbnail': 're:^https?://.*\.jpg$',
'timestamp': 1432408200,
'upload_date': '20150523',
'duration': 3092,
},
'params': {
# m3u8 download
'skip_download': True,
},
}]
def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)
display_id = mobj.group('id')
station = mobj.group('station')
info = self._download_json(
'https://api.nowtv.de/v3/movies/%s?fields=*,format,files' % display_id,
display_id)
video_id = compat_str(info['id'])
files = info['files']
if not files:
if info.get('geoblocked', False):
raise ExtractorError(
'Video %s is not available from your location due to geo restriction' % video_id,
expected=True)
if not info.get('free', True):
raise ExtractorError(
'Video %s is not available for free' % video_id, expected=True)
f = info.get('format', {})
station = f.get('station') or station
STATIONS = {
'rtl': 'rtlnow',
'rtl2': 'rtl2now',
'vox': 'voxnow',
'nitro': 'rtlnitronow',
'ntv': 'n-tvnow',
'superrtl': 'superrtlnow'
}
formats = []
for item in files['items']:
item_path = remove_start(item['path'], '/')
tbr = int_or_none(item['bitrate'])
m3u8_url = 'http://hls.fra.%s.de/hls-vod-enc/%s.m3u8' % (STATIONS[station], item_path)
m3u8_url = m3u8_url.replace('now/', 'now/videos/')
formats.append({
'url': m3u8_url,
'format_id': '%s-%sk' % (item['id'], tbr),
'ext': 'mp4',
'tbr': tbr,
})
self._sort_formats(formats)
title = info['title']
description = info.get('articleLong') or info.get('articleShort')
timestamp = parse_iso8601(info.get('broadcastStartDate'), ' ')
duration = parse_duration(info.get('duration'))
thumbnail = f.get('defaultImage169Format') or f.get('defaultImage169Logo')
return {
'id': video_id,
'display_id': display_id,
'title': title,
'description': description,
'thumbnail': thumbnail,
'timestamp': timestamp,
'duration': duration,
'formats': formats,
}

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