mirror of
https://codeberg.org/polarisfm/youtube-dl
synced 2024-12-25 15:57:55 +01:00
Merge remote-tracking branch 'upstream/master' into porntrex
This commit is contained in:
commit
d02cc2bf50
6
.github/ISSUE_TEMPLATE/1_broken_site.md
vendored
6
.github/ISSUE_TEMPLATE/1_broken_site.md
vendored
@ -18,7 +18,7 @@ title: ''
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
||||||
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2019.05.20. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2019.06.21. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
||||||
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
||||||
- Make sure that all URLs and arguments with special characters are properly quoted or escaped as explained in http://yt-dl.org/escape.
|
- Make sure that all URLs and arguments with special characters are properly quoted or escaped as explained in http://yt-dl.org/escape.
|
||||||
- Search the bugtracker for similar issues: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
- Search the bugtracker for similar issues: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
||||||
@ -26,7 +26,7 @@ Carefully read and work through this check list in order to prevent the most com
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
- [ ] I'm reporting a broken site support
|
- [ ] I'm reporting a broken site support
|
||||||
- [ ] I've verified that I'm running youtube-dl version **2019.05.20**
|
- [ ] I've verified that I'm running youtube-dl version **2019.06.21**
|
||||||
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
||||||
- [ ] I've checked that all URLs and arguments with special characters are properly quoted or escaped
|
- [ ] I've checked that all URLs and arguments with special characters are properly quoted or escaped
|
||||||
- [ ] I've searched the bugtracker for similar issues including closed ones
|
- [ ] I've searched the bugtracker for similar issues including closed ones
|
||||||
@ -41,7 +41,7 @@ Add the `-v` flag to your command line you run youtube-dl with (`youtube-dl -v <
|
|||||||
[debug] User config: []
|
[debug] User config: []
|
||||||
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
|
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
|
||||||
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
|
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
|
||||||
[debug] youtube-dl version 2019.05.20
|
[debug] youtube-dl version 2019.06.21
|
||||||
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
|
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
|
||||||
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
|
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
|
||||||
[debug] Proxy map: {}
|
[debug] Proxy map: {}
|
||||||
|
@ -19,7 +19,7 @@ labels: 'site-support-request'
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
||||||
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2019.05.20. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2019.06.21. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
||||||
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
||||||
- Make sure that site you are requesting is not dedicated to copyright infringement, see https://yt-dl.org/copyright-infringement. youtube-dl does not support such sites. In order for site support request to be accepted all provided example URLs should not violate any copyrights.
|
- Make sure that site you are requesting is not dedicated to copyright infringement, see https://yt-dl.org/copyright-infringement. youtube-dl does not support such sites. In order for site support request to be accepted all provided example URLs should not violate any copyrights.
|
||||||
- Search the bugtracker for similar site support requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
- Search the bugtracker for similar site support requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
||||||
@ -27,7 +27,7 @@ Carefully read and work through this check list in order to prevent the most com
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
- [ ] I'm reporting a new site support request
|
- [ ] I'm reporting a new site support request
|
||||||
- [ ] I've verified that I'm running youtube-dl version **2019.05.20**
|
- [ ] I've verified that I'm running youtube-dl version **2019.06.21**
|
||||||
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
||||||
- [ ] I've checked that none of provided URLs violate any copyrights
|
- [ ] I've checked that none of provided URLs violate any copyrights
|
||||||
- [ ] I've searched the bugtracker for similar site support requests including closed ones
|
- [ ] I've searched the bugtracker for similar site support requests including closed ones
|
||||||
|
@ -18,13 +18,13 @@ title: ''
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
||||||
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2019.05.20. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2019.06.21. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
||||||
- Search the bugtracker for similar site feature requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
- Search the bugtracker for similar site feature requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
||||||
- Finally, put x into all relevant boxes (like this [x])
|
- Finally, put x into all relevant boxes (like this [x])
|
||||||
-->
|
-->
|
||||||
|
|
||||||
- [ ] I'm reporting a site feature request
|
- [ ] I'm reporting a site feature request
|
||||||
- [ ] I've verified that I'm running youtube-dl version **2019.05.20**
|
- [ ] I've verified that I'm running youtube-dl version **2019.06.21**
|
||||||
- [ ] I've searched the bugtracker for similar site feature requests including closed ones
|
- [ ] I've searched the bugtracker for similar site feature requests including closed ones
|
||||||
|
|
||||||
|
|
||||||
|
6
.github/ISSUE_TEMPLATE/4_bug_report.md
vendored
6
.github/ISSUE_TEMPLATE/4_bug_report.md
vendored
@ -18,7 +18,7 @@ title: ''
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
||||||
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2019.05.20. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2019.06.21. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
||||||
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
||||||
- Make sure that all URLs and arguments with special characters are properly quoted or escaped as explained in http://yt-dl.org/escape.
|
- Make sure that all URLs and arguments with special characters are properly quoted or escaped as explained in http://yt-dl.org/escape.
|
||||||
- Search the bugtracker for similar issues: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
- Search the bugtracker for similar issues: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
||||||
@ -27,7 +27,7 @@ Carefully read and work through this check list in order to prevent the most com
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
- [ ] I'm reporting a broken site support issue
|
- [ ] I'm reporting a broken site support issue
|
||||||
- [ ] I've verified that I'm running youtube-dl version **2019.05.20**
|
- [ ] I've verified that I'm running youtube-dl version **2019.06.21**
|
||||||
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
||||||
- [ ] I've checked that all URLs and arguments with special characters are properly quoted or escaped
|
- [ ] I've checked that all URLs and arguments with special characters are properly quoted or escaped
|
||||||
- [ ] I've searched the bugtracker for similar bug reports including closed ones
|
- [ ] I've searched the bugtracker for similar bug reports including closed ones
|
||||||
@ -43,7 +43,7 @@ Add the `-v` flag to your command line you run youtube-dl with (`youtube-dl -v <
|
|||||||
[debug] User config: []
|
[debug] User config: []
|
||||||
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
|
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
|
||||||
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
|
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
|
||||||
[debug] youtube-dl version 2019.05.20
|
[debug] youtube-dl version 2019.06.21
|
||||||
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
|
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
|
||||||
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
|
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
|
||||||
[debug] Proxy map: {}
|
[debug] Proxy map: {}
|
||||||
|
4
.github/ISSUE_TEMPLATE/5_feature_request.md
vendored
4
.github/ISSUE_TEMPLATE/5_feature_request.md
vendored
@ -19,13 +19,13 @@ labels: 'request'
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
||||||
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2019.05.20. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2019.06.21. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
||||||
- Search the bugtracker for similar feature requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
- Search the bugtracker for similar feature requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
||||||
- Finally, put x into all relevant boxes (like this [x])
|
- Finally, put x into all relevant boxes (like this [x])
|
||||||
-->
|
-->
|
||||||
|
|
||||||
- [ ] I'm reporting a feature request
|
- [ ] I'm reporting a feature request
|
||||||
- [ ] I've verified that I'm running youtube-dl version **2019.05.20**
|
- [ ] I've verified that I'm running youtube-dl version **2019.06.21**
|
||||||
- [ ] I've searched the bugtracker for similar feature requests including closed ones
|
- [ ] I've searched the bugtracker for similar feature requests including closed ones
|
||||||
|
|
||||||
|
|
||||||
|
53
ChangeLog
53
ChangeLog
@ -1,3 +1,56 @@
|
|||||||
|
version 2019.06.21
|
||||||
|
|
||||||
|
Core
|
||||||
|
* [utils] Restrict parse_codecs and add theora as known vcodec (#21381)
|
||||||
|
|
||||||
|
Extractors
|
||||||
|
* [youtube] Update signature function patterns (#21469, #21476)
|
||||||
|
* [youtube] Make --write-annotations non fatal (#21452)
|
||||||
|
+ [sixplay] Add support for rtlmost.hu (#21405)
|
||||||
|
* [youtube] Hardcode codec metadata for av01 video only formats (#21381)
|
||||||
|
* [toutv] Update client key (#21370)
|
||||||
|
+ [biqle] Add support for new embed domain
|
||||||
|
* [cbs] Improve DRM protected videos detection (#21339)
|
||||||
|
|
||||||
|
|
||||||
|
version 2019.06.08
|
||||||
|
|
||||||
|
Core
|
||||||
|
* [downloader/common] Improve rate limit (#21301)
|
||||||
|
* [utils] Improve strip_or_none
|
||||||
|
* [extractor/common] Strip src attribute for HTML5 entries code (#18485,
|
||||||
|
#21169)
|
||||||
|
|
||||||
|
Extractors
|
||||||
|
* [ted] Fix playlist extraction (#20844, #21032)
|
||||||
|
* [vlive:playlist] Fix video extraction when no playlist is found (#20590)
|
||||||
|
+ [vlive] Add CH+ support (#16887, #21209)
|
||||||
|
+ [openload] Add support for oload.website (#21329)
|
||||||
|
+ [tvnow] Extract HD formats (#21201)
|
||||||
|
+ [redbulltv] Add support for rrn:content URLs (#21297)
|
||||||
|
* [youtube] Fix average rating extraction (#21304)
|
||||||
|
+ [bitchute] Extract HTML5 formats (#21306)
|
||||||
|
* [cbsnews] Fix extraction (#9659, #15397)
|
||||||
|
* [vvvvid] Relax URL regular expression (#21299)
|
||||||
|
+ [prosiebensat1] Add support for new API (#21272)
|
||||||
|
+ [vrv] Extract adaptive_hls formats (#21243)
|
||||||
|
* [viki] Switch to HTTPS (#21001)
|
||||||
|
* [LiveLeak] Check if the original videos exist (#21206, #21208)
|
||||||
|
* [rtp] Fix extraction (#15099)
|
||||||
|
* [youtube] Improve DRM protected videos detection (#1774)
|
||||||
|
+ [srgssrplay] Add support for popupvideoplayer URLs (#21155)
|
||||||
|
+ [24video] Add support for porno.24video.net (#21194)
|
||||||
|
+ [24video] Add support for 24video.site (#21193)
|
||||||
|
- [pornflip] Remove extractor
|
||||||
|
- [criterion] Remove extractor (#21195)
|
||||||
|
* [pornhub] Use HTTPS (#21061)
|
||||||
|
* [bitchute] Fix uploader extraction (#21076)
|
||||||
|
* [streamcloud] Reduce waiting time to 6 seconds (#21092)
|
||||||
|
- [novamov] Remove extractors (#21077)
|
||||||
|
+ [openload] Add support for oload.press (#21135)
|
||||||
|
* [vivo] Fix extraction (#18906, #19217)
|
||||||
|
|
||||||
|
|
||||||
version 2019.05.20
|
version 2019.05.20
|
||||||
|
|
||||||
Core
|
Core
|
||||||
|
@ -78,7 +78,6 @@
|
|||||||
- **AudioBoom**
|
- **AudioBoom**
|
||||||
- **audiomack**
|
- **audiomack**
|
||||||
- **audiomack:album**
|
- **audiomack:album**
|
||||||
- **auroravid**: AuroraVid
|
|
||||||
- **AWAAN**
|
- **AWAAN**
|
||||||
- **awaan:live**
|
- **awaan:live**
|
||||||
- **awaan:season**
|
- **awaan:season**
|
||||||
@ -150,6 +149,7 @@
|
|||||||
- **CBSInteractive**
|
- **CBSInteractive**
|
||||||
- **CBSLocal**
|
- **CBSLocal**
|
||||||
- **cbsnews**: CBS News
|
- **cbsnews**: CBS News
|
||||||
|
- **cbsnews:embed**
|
||||||
- **cbsnews:livevideo**: CBS News Live Videos
|
- **cbsnews:livevideo**: CBS News Live Videos
|
||||||
- **CBSSports**
|
- **CBSSports**
|
||||||
- **CCMA**
|
- **CCMA**
|
||||||
@ -174,7 +174,6 @@
|
|||||||
- **Clipsyndicate**
|
- **Clipsyndicate**
|
||||||
- **CloserToTruth**
|
- **CloserToTruth**
|
||||||
- **CloudflareStream**
|
- **CloudflareStream**
|
||||||
- **cloudtime**: CloudTime
|
|
||||||
- **Cloudy**
|
- **Cloudy**
|
||||||
- **Clubic**
|
- **Clubic**
|
||||||
- **Clyp**
|
- **Clyp**
|
||||||
@ -194,7 +193,6 @@
|
|||||||
- **Coub**
|
- **Coub**
|
||||||
- **Cracked**
|
- **Cracked**
|
||||||
- **Crackle**
|
- **Crackle**
|
||||||
- **Criterion**
|
|
||||||
- **CrooksAndLiars**
|
- **CrooksAndLiars**
|
||||||
- **crunchyroll**
|
- **crunchyroll**
|
||||||
- **crunchyroll:playlist**
|
- **crunchyroll:playlist**
|
||||||
@ -609,7 +607,6 @@
|
|||||||
- **nowness**
|
- **nowness**
|
||||||
- **nowness:playlist**
|
- **nowness:playlist**
|
||||||
- **nowness:series**
|
- **nowness:series**
|
||||||
- **nowvideo**: NowVideo
|
|
||||||
- **Noz**
|
- **Noz**
|
||||||
- **npo**: npo.nl, ntr.nl, omroepwnl.nl, zapp.nl and npo3.nl
|
- **npo**: npo.nl, ntr.nl, omroepwnl.nl, zapp.nl and npo3.nl
|
||||||
- **npo.nl:live**
|
- **npo.nl:live**
|
||||||
@ -693,7 +690,6 @@
|
|||||||
- **PopcornTV**
|
- **PopcornTV**
|
||||||
- **PornCom**
|
- **PornCom**
|
||||||
- **PornerBros**
|
- **PornerBros**
|
||||||
- **PornFlip**
|
|
||||||
- **PornHd**
|
- **PornHd**
|
||||||
- **PornHub**: PornHub and Thumbzilla
|
- **PornHub**: PornHub and Thumbzilla
|
||||||
- **PornHubPlaylist**
|
- **PornHubPlaylist**
|
||||||
@ -734,6 +730,7 @@
|
|||||||
- **RBMARadio**
|
- **RBMARadio**
|
||||||
- **RDS**: RDS.ca
|
- **RDS**: RDS.ca
|
||||||
- **RedBullTV**
|
- **RedBullTV**
|
||||||
|
- **RedBullTVRrnContent**
|
||||||
- **Reddit**
|
- **Reddit**
|
||||||
- **RedditR**
|
- **RedditR**
|
||||||
- **RedTube**
|
- **RedTube**
|
||||||
@ -1024,7 +1021,6 @@
|
|||||||
- **videomore:video**
|
- **videomore:video**
|
||||||
- **VideoPremium**
|
- **VideoPremium**
|
||||||
- **VideoPress**
|
- **VideoPress**
|
||||||
- **videoweed**: VideoWeed
|
|
||||||
- **Vidio**
|
- **Vidio**
|
||||||
- **VidLii**
|
- **VidLii**
|
||||||
- **vidme**
|
- **vidme**
|
||||||
@ -1101,7 +1097,6 @@
|
|||||||
- **Weibo**
|
- **Weibo**
|
||||||
- **WeiboMobile**
|
- **WeiboMobile**
|
||||||
- **WeiqiTV**: WQTV
|
- **WeiqiTV**: WQTV
|
||||||
- **wholecloud**: WholeCloud
|
|
||||||
- **Wimp**
|
- **Wimp**
|
||||||
- **Wistia**
|
- **Wistia**
|
||||||
- **wnl**: npo.nl, ntr.nl, omroepwnl.nl, zapp.nl and npo3.nl
|
- **wnl**: npo.nl, ntr.nl, omroepwnl.nl, zapp.nl and npo3.nl
|
||||||
|
@ -822,6 +822,15 @@ class TestUtil(unittest.TestCase):
|
|||||||
'vcodec': 'av01.0.05M.08',
|
'vcodec': 'av01.0.05M.08',
|
||||||
'acodec': 'none',
|
'acodec': 'none',
|
||||||
})
|
})
|
||||||
|
self.assertEqual(parse_codecs('theora, vorbis'), {
|
||||||
|
'vcodec': 'theora',
|
||||||
|
'acodec': 'vorbis',
|
||||||
|
})
|
||||||
|
self.assertEqual(parse_codecs('unknownvcodec, unknownacodec'), {
|
||||||
|
'vcodec': 'unknownvcodec',
|
||||||
|
'acodec': 'unknownacodec',
|
||||||
|
})
|
||||||
|
self.assertEqual(parse_codecs('unknown'), {})
|
||||||
|
|
||||||
def test_escape_rfc3986(self):
|
def test_escape_rfc3986(self):
|
||||||
reserved = "!*'();:@&=+$,/?#[]"
|
reserved = "!*'();:@&=+$,/?#[]"
|
||||||
|
@ -176,7 +176,9 @@ class FileDownloader(object):
|
|||||||
return
|
return
|
||||||
speed = float(byte_counter) / elapsed
|
speed = float(byte_counter) / elapsed
|
||||||
if speed > rate_limit:
|
if speed > rate_limit:
|
||||||
time.sleep(max((byte_counter // rate_limit) - elapsed, 0))
|
sleep_time = float(byte_counter) / rate_limit - elapsed
|
||||||
|
if sleep_time > 0:
|
||||||
|
time.sleep(sleep_time)
|
||||||
|
|
||||||
def temp_name(self, filename):
|
def temp_name(self, filename):
|
||||||
"""Returns a temporary filename for the given filename."""
|
"""Returns a temporary filename for the given filename."""
|
||||||
|
@ -42,7 +42,7 @@ class BIQLEIE(InfoExtractor):
|
|||||||
video_id = self._match_id(url)
|
video_id = self._match_id(url)
|
||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, video_id)
|
||||||
embed_url = self._proto_relative_url(self._search_regex(
|
embed_url = self._proto_relative_url(self._search_regex(
|
||||||
r'<iframe.+?src="((?:https?:)?//daxab\.com/[^"]+)".*?></iframe>',
|
r'<iframe.+?src="((?:https?:)?//(?:daxab\.com|dxb\.to|[^/]+/player)/[^"]+)".*?></iframe>',
|
||||||
webpage, 'embed url'))
|
webpage, 'embed url'))
|
||||||
if VKIE.suitable(embed_url):
|
if VKIE.suitable(embed_url):
|
||||||
return self.url_result(embed_url, VKIE.ie_key(), video_id)
|
return self.url_result(embed_url, VKIE.ie_key(), video_id)
|
||||||
|
@ -55,6 +55,11 @@ class BitChuteIE(InfoExtractor):
|
|||||||
formats = [
|
formats = [
|
||||||
{'url': format_url}
|
{'url': format_url}
|
||||||
for format_url in orderedSet(format_urls)]
|
for format_url in orderedSet(format_urls)]
|
||||||
|
|
||||||
|
if not formats:
|
||||||
|
formats = self._parse_html5_media_entries(
|
||||||
|
url, webpage, video_id)[0]['formats']
|
||||||
|
|
||||||
self._check_formats(formats, video_id)
|
self._check_formats(formats, video_id)
|
||||||
self._sort_formats(formats)
|
self._sort_formats(formats)
|
||||||
|
|
||||||
|
@ -483,7 +483,7 @@ class BrightcoveLegacyIE(InfoExtractor):
|
|||||||
|
|
||||||
class BrightcoveNewIE(AdobePassIE):
|
class BrightcoveNewIE(AdobePassIE):
|
||||||
IE_NAME = 'brightcove:new'
|
IE_NAME = 'brightcove:new'
|
||||||
_VALID_URL = r'https?://players\.brightcove\.net/(?P<account_id>\d+)/(?P<player_id>[^/]+)_(?P<embed>[^/]+)/index\.html\?.*videoId=(?P<video_id>\d+|ref:[^&]+)'
|
_VALID_URL = r'https?://players\.brightcove\.net/(?P<account_id>\d+)/(?P<player_id>[^/]+)_(?P<embed>[^/]+)/index\.html\?.*(?P<content_type>video|playlist)Id=(?P<video_id>\d+|ref:[^&]+)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
'url': 'http://players.brightcove.net/929656772001/e41d32dc-ec74-459e-a845-6c69f7b724ea_default/index.html?videoId=4463358922001',
|
'url': 'http://players.brightcove.net/929656772001/e41d32dc-ec74-459e-a845-6c69f7b724ea_default/index.html?videoId=4463358922001',
|
||||||
'md5': 'c8100925723840d4b0d243f7025703be',
|
'md5': 'c8100925723840d4b0d243f7025703be',
|
||||||
@ -516,6 +516,21 @@ class BrightcoveNewIE(AdobePassIE):
|
|||||||
# m3u8 download
|
# m3u8 download
|
||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
# playlist stream
|
||||||
|
'url': 'https://players.brightcove.net/1752604059001/S13cJdUBz_default/index.html?playlistId=5718313430001',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '5718313430001',
|
||||||
|
'title': 'No Audio Playlist',
|
||||||
|
},
|
||||||
|
'playlist_count': 7,
|
||||||
|
'params': {
|
||||||
|
# m3u8 download
|
||||||
|
'skip_download': True,
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
'url': 'http://players.brightcove.net/5690807595001/HyZNerRl7_default/index.html?playlistId=5743160747001',
|
||||||
|
'only_matching': True,
|
||||||
}, {
|
}, {
|
||||||
# ref: prefixed video id
|
# ref: prefixed video id
|
||||||
'url': 'http://players.brightcove.net/3910869709001/21519b5c-4b3b-4363-accb-bdc8f358f823_default/index.html?videoId=ref:7069442',
|
'url': 'http://players.brightcove.net/3910869709001/21519b5c-4b3b-4363-accb-bdc8f358f823_default/index.html?videoId=ref:7069442',
|
||||||
@ -715,7 +730,7 @@ class BrightcoveNewIE(AdobePassIE):
|
|||||||
'ip_blocks': smuggled_data.get('geo_ip_blocks'),
|
'ip_blocks': smuggled_data.get('geo_ip_blocks'),
|
||||||
})
|
})
|
||||||
|
|
||||||
account_id, player_id, embed, video_id = re.match(self._VALID_URL, url).groups()
|
account_id, player_id, embed, content_type, video_id = re.match(self._VALID_URL, url).groups()
|
||||||
|
|
||||||
webpage = self._download_webpage(
|
webpage = self._download_webpage(
|
||||||
'http://players.brightcove.net/%s/%s_%s/index.min.js'
|
'http://players.brightcove.net/%s/%s_%s/index.min.js'
|
||||||
@ -736,7 +751,7 @@ class BrightcoveNewIE(AdobePassIE):
|
|||||||
r'policyKey\s*:\s*(["\'])(?P<pk>.+?)\1',
|
r'policyKey\s*:\s*(["\'])(?P<pk>.+?)\1',
|
||||||
webpage, 'policy key', group='pk')
|
webpage, 'policy key', group='pk')
|
||||||
|
|
||||||
api_url = 'https://edge.api.brightcove.com/playback/v1/accounts/%s/videos/%s' % (account_id, video_id)
|
api_url = 'https://edge.api.brightcove.com/playback/v1/accounts/%s/%ss/%s' % (account_id, content_type, video_id)
|
||||||
headers = {
|
headers = {
|
||||||
'Accept': 'application/json;pk=%s' % policy_key,
|
'Accept': 'application/json;pk=%s' % policy_key,
|
||||||
}
|
}
|
||||||
@ -771,5 +786,12 @@ class BrightcoveNewIE(AdobePassIE):
|
|||||||
'tveToken': tve_token,
|
'tveToken': tve_token,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if content_type == 'playlist':
|
||||||
|
return self.playlist_result(
|
||||||
|
[self._parse_brightcove_metadata(vid, vid.get('id'), headers)
|
||||||
|
for vid in json_data.get('videos', []) if vid.get('id')],
|
||||||
|
json_data.get('id'), json_data.get('name'),
|
||||||
|
json_data.get('description'))
|
||||||
|
|
||||||
return self._parse_brightcove_metadata(
|
return self._parse_brightcove_metadata(
|
||||||
json_data, video_id, headers=headers)
|
json_data, video_id, headers=headers)
|
||||||
|
@ -69,7 +69,7 @@ class CBSIE(CBSBaseIE):
|
|||||||
last_e = None
|
last_e = None
|
||||||
for item in items_data.findall('.//item'):
|
for item in items_data.findall('.//item'):
|
||||||
asset_type = xpath_text(item, 'assetType')
|
asset_type = xpath_text(item, 'assetType')
|
||||||
if not asset_type or asset_type in asset_types or asset_type in ('HLS_FPS', 'DASH_CENC'):
|
if not asset_type or asset_type in asset_types or 'HLS_FPS' in asset_type or 'DASH_CENC' in asset_type:
|
||||||
continue
|
continue
|
||||||
asset_types.append(asset_type)
|
asset_types.append(asset_type)
|
||||||
query = {
|
query = {
|
||||||
|
@ -1,40 +1,62 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import re
|
||||||
|
import zlib
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from .cbs import CBSIE
|
from .cbs import CBSIE
|
||||||
|
from ..compat import (
|
||||||
|
compat_b64decode,
|
||||||
|
compat_urllib_parse_unquote,
|
||||||
|
)
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
parse_duration,
|
parse_duration,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CBSNewsEmbedIE(CBSIE):
|
||||||
|
IE_NAME = 'cbsnews:embed'
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?cbsnews\.com/embed/video[^#]*#(?P<id>.+)'
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://www.cbsnews.com/embed/video/?v=1.c9b5b61492913d6660db0b2f03579ef25e86307a#1Vb7b9s2EP5XBAHbT6Gt98PAMKTJ0se6LVjWYWtdGBR1stlIpEBSTtwi%2F%2FvuJNkNhmHdGxgM2NL57vjd6zt%2B8PngdN%2Fyg79qeGvhzN%2FLGrS%2F%2BuBLB531V28%2B%2BO7Qg7%2Fy97r2z3xZ42NW8yLhDbA0S0KWlHnIijwKWJBHZZnHBa8Cgbpdf%2F89NM9Hi9fXifhpr8sr%2FlP848tn%2BTdXycX25zh4cdX%2FvHl6PmmPqnWQv9w8Ed%2B9GjYRim07bFEqdG%2BZVHuwTm65A7bVRrYtR5lAyMox7pigF6W4k%2By91mjspGsJ%2BwVae4%2BsvdnaO1p73HkXs%2FVisUDTGm7R8IcdnOROeq%2B19qT1amhA1VJtPenoTUgrtfKc9m7Rq8dP7nnjwOB7wg7ADdNt7VX64DWAWlKhPtmDEq22g4GF99x6Dk9E8OSsankHXqPNKDxC%2FdK7MLKTircTDgsI3mmj4OBdSq64dy7fd1x577RU1rt4cvMtOaulFYOd%2FLewRWvDO9lIgXFpZSnkZmjbv5SxKTPoQXClFbpsf%2Fhbbpzs0IB3vb8KkyzJQ%2BywOAgCrMpgRrz%2BKk4fvb7kFbR4XJCu0gAdtNO7woCwZTu%2BBUs9bam%2Fds71drVerpeisgrubLjAB4nnOSkWQnfr5W6o1ku5Xpr1MgrCbL0M0vUyDtfLLK15WiYp47xKWSLyjFVpwVmVJSLIoCjSOFkv3W7oKsVliwZJcB9nwXpZ5GEQQwY8jNKqKCBrgjTLeFxgdCIpazojDgnRtn43J6kG7nZ6cAbxh0EeFFk4%2B1u867cY5u4344n%2FxXjCqAjucdTHgLKojNKmSfO8KRsOFY%2FzKEYCKEJBzv90QA9nfm9gL%2BHulaFqUkz9ULUYxl62B3U%2FRVNLA8IhggaPycOoBuwOCESciDQVSSUgiOMsROB%2FhKfwCKOzEk%2B4k6rWd4uuT%2FwTDz7K7t3d3WLO8ISD95jSPQbayBacthbz86XVgxHwhex5zawzgDOmtp%2F3GPcXn0VXHdSS029%2Fj99UC%2FwJUvyKQ%2FzKyixIEVlYJOn4RxxuaH43Ty9fbJ5OObykHH435XAzJTHeOF4hhEUXD8URe%2FQ%2FBT%2BMpf8d5GN02Ox%2FfiGsl7TA7POu1xZ5%2BbTzcAVKMe48mqcC21hkacVEVScM26liVVBnrKkC4CLKyzAvHu0lhEaTKMFwI3a4SN9MsrfYzdBLq2vkwRD1gVviLT8kY9h2CHH6Y%2Bix6609weFtey4ESp60WtyeWMy%2BsmBuhsoKIyuoT%2Bq2R%2FrW5qi3g%2FvzS2j40DoixDP8%2BKP0yUdpXJ4l6Vla%2Bg9vce%2BC4yM5YlUcbA%2F0jLKdpmTwvsdN5z88nAIe08%2F0HgxeG1iv%2B6Hlhjh7uiW0SDzYNI92L401uha3JKYk268UVRzdOzNQvAaJqoXzAc80dAV440NZ1WVVAAMRYQ2KrGJFmDUsq8saWSnjvIj8t78y%2FRa3JRnbHVfyFpfwoDiGpPgjzekyUiKNlU3OMlwuLMmzgvEojllYVE2Z1HhImvsnk%2BuhusTEoB21PAtSFodeFK3iYhXEH9WOG2%2FkOE833sfeG%2Ff5cfHtEFNXgYes0%2FXj7aGivUgJ9XpusCtoNcNYVVnJVrrDo0OmJAutHCpuZul4W9lLcfy7BnuLPT02%2ByXsCTk%2B9zhzswIN04YueNSK%2BPtM0jS88QdLqSLJDTLsuGZJNolm2yO0PXh3UPnz9Ix5bfIAqxPjvETQsDCEiPG4QbqNyhBZISxybLnZYCrW5H3Axp690%2F0BJdXtDZ5ITuM4xj3f4oUHGzc5JeJmZKpp%2FjwKh4wMV%2FV1yx3emLoR0MwbG4K%2F%2BZgVep3PnzXGDHZ6a3i%2Fk%2BJrONDN13%2Bnq6tBTYk4o7cLGhBtqCC4KwacGHpEVuoH5JNro%2FE6JfE6d5RydbiR76k%2BW5wioDHBIjw1euhHjUGRB0y5A97KoaPx6MlL%2BwgboUVtUFRI%2FLemgTpdtF59ii7pab08kuPcfWzs0l%2FRI5takWnFpka0zOgWRtYcuf9aIxZMxlwr6IiGpsb6j2DQUXPl%2FimXI599Ev7fWjoPD78A',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
item = self._parse_json(zlib.decompress(compat_b64decode(
|
||||||
|
compat_urllib_parse_unquote(self._match_id(url))),
|
||||||
|
-zlib.MAX_WBITS), None)['video']['items'][0]
|
||||||
|
return self._extract_video_info(item['mpxRefId'], 'cbsnews')
|
||||||
|
|
||||||
|
|
||||||
class CBSNewsIE(CBSIE):
|
class CBSNewsIE(CBSIE):
|
||||||
IE_NAME = 'cbsnews'
|
IE_NAME = 'cbsnews'
|
||||||
IE_DESC = 'CBS News'
|
IE_DESC = 'CBS News'
|
||||||
_VALID_URL = r'https?://(?:www\.)?cbsnews\.com/(?:news|videos)/(?P<id>[\da-z_-]+)'
|
_VALID_URL = r'https?://(?:www\.)?cbsnews\.com/(?:news|video)/(?P<id>[\da-z_-]+)'
|
||||||
|
|
||||||
_TESTS = [
|
_TESTS = [
|
||||||
{
|
{
|
||||||
# 60 minutes
|
# 60 minutes
|
||||||
'url': 'http://www.cbsnews.com/news/artificial-intelligence-positioned-to-be-a-game-changer/',
|
'url': 'http://www.cbsnews.com/news/artificial-intelligence-positioned-to-be-a-game-changer/',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '_B6Ga3VJrI4iQNKsir_cdFo9Re_YJHE_',
|
'id': 'Y_nf_aEg6WwO9OLAq0MpKaPgfnBUxfW4',
|
||||||
'ext': 'mp4',
|
'ext': 'flv',
|
||||||
'title': 'Artificial Intelligence',
|
'title': 'Artificial Intelligence, real-life applications',
|
||||||
'description': 'md5:8818145f9974431e0fb58a1b8d69613c',
|
'description': 'md5:a7aaf27f1b4777244de8b0b442289304',
|
||||||
'thumbnail': r're:^https?://.*\.jpg$',
|
'thumbnail': r're:^https?://.*\.jpg$',
|
||||||
'duration': 1606,
|
'duration': 317,
|
||||||
'uploader': 'CBSI-NEW',
|
'uploader': 'CBSI-NEW',
|
||||||
'timestamp': 1498431900,
|
'timestamp': 1476046464,
|
||||||
'upload_date': '20170625',
|
'upload_date': '20161009',
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {
|
||||||
# m3u8 download
|
# rtmp download
|
||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'url': 'http://www.cbsnews.com/videos/fort-hood-shooting-army-downplays-mental-illness-as-cause-of-attack/',
|
'url': 'https://www.cbsnews.com/video/fort-hood-shooting-army-downplays-mental-illness-as-cause-of-attack/',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'SNJBOYzXiWBOvaLsdzwH8fmtP1SCd91Y',
|
'id': 'SNJBOYzXiWBOvaLsdzwH8fmtP1SCd91Y',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
@ -60,37 +82,29 @@ class CBSNewsIE(CBSIE):
|
|||||||
# 48 hours
|
# 48 hours
|
||||||
'url': 'http://www.cbsnews.com/news/maria-ridulph-murder-will-the-nations-oldest-cold-case-to-go-to-trial-ever-get-solved/',
|
'url': 'http://www.cbsnews.com/news/maria-ridulph-murder-will-the-nations-oldest-cold-case-to-go-to-trial-ever-get-solved/',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'QpM5BJjBVEAUFi7ydR9LusS69DPLqPJ1',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'title': 'Cold as Ice',
|
'title': 'Cold as Ice',
|
||||||
'description': 'Can a childhood memory of a friend\'s murder solve a 1957 cold case? "48 Hours" correspondent Erin Moriarty has the latest.',
|
'description': 'Can a childhood memory solve the 1957 murder of 7-year-old Maria Ridulph?',
|
||||||
'upload_date': '20170604',
|
|
||||||
'timestamp': 1496538000,
|
|
||||||
'uploader': 'CBSI-NEW',
|
|
||||||
},
|
|
||||||
'params': {
|
|
||||||
'skip_download': True,
|
|
||||||
},
|
},
|
||||||
|
'playlist_mincount': 7,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
video_id = self._match_id(url)
|
display_id = self._match_id(url)
|
||||||
|
|
||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, display_id)
|
||||||
|
|
||||||
video_info = self._parse_json(self._html_search_regex(
|
entries = []
|
||||||
r'(?:<ul class="media-list items" id="media-related-items"[^>]*><li data-video-info|<div id="cbsNewsVideoPlayer" data-video-player-options)=\'({.+?})\'',
|
for embed_url in re.findall(r'<iframe[^>]+data-src="(https?://(?:www\.)?cbsnews\.com/embed/video/[^#]*#[^"]+)"', webpage):
|
||||||
webpage, 'video JSON info', default='{}'), video_id, fatal=False)
|
entries.append(self.url_result(embed_url, CBSNewsEmbedIE.ie_key()))
|
||||||
|
if entries:
|
||||||
if video_info:
|
return self.playlist_result(
|
||||||
item = video_info['item'] if 'item' in video_info else video_info
|
entries, playlist_title=self._html_search_meta(['og:title', 'twitter:title'], webpage),
|
||||||
else:
|
playlist_description=self._html_search_meta(['og:description', 'twitter:description', 'description'], webpage))
|
||||||
state = self._parse_json(self._search_regex(
|
|
||||||
r'data-cbsvideoui-options=(["\'])(?P<json>{.+?})\1', webpage,
|
|
||||||
'playlist JSON info', group='json'), video_id)['state']
|
|
||||||
item = state['playlist'][state['pid']]
|
|
||||||
|
|
||||||
|
item = self._parse_json(self._html_search_regex(
|
||||||
|
r'CBSNEWS\.defaultPayload\s*=\s*({.+})',
|
||||||
|
webpage, 'video JSON info'), display_id)['items'][0]
|
||||||
return self._extract_video_info(item['mpxRefId'], 'cbsnews')
|
return self._extract_video_info(item['mpxRefId'], 'cbsnews')
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,19 +103,6 @@ class CrunchyrollBaseIE(InfoExtractor):
|
|||||||
def _real_initialize(self):
|
def _real_initialize(self):
|
||||||
self._login()
|
self._login()
|
||||||
|
|
||||||
def _download_webpage(self, url_or_request, *args, **kwargs):
|
|
||||||
request = (url_or_request if isinstance(url_or_request, compat_urllib_request.Request)
|
|
||||||
else sanitized_Request(url_or_request))
|
|
||||||
# Accept-Language must be set explicitly to accept any language to avoid issues
|
|
||||||
# similar to https://github.com/ytdl-org/youtube-dl/issues/6797.
|
|
||||||
# Along with IP address Crunchyroll uses Accept-Language to guess whether georestriction
|
|
||||||
# should be imposed or not (from what I can see it just takes the first language
|
|
||||||
# ignoring the priority and requires it to correspond the IP). By the way this causes
|
|
||||||
# Crunchyroll to not work in georestriction cases in some browsers that don't place
|
|
||||||
# the locale lang first in header. However allowing any language seems to workaround the issue.
|
|
||||||
request.add_header('Accept-Language', '*')
|
|
||||||
return super(CrunchyrollBaseIE, self)._download_webpage(request, *args, **kwargs)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _add_skip_wall(url):
|
def _add_skip_wall(url):
|
||||||
parsed_url = compat_urlparse.urlparse(url)
|
parsed_url = compat_urlparse.urlparse(url)
|
||||||
@ -269,6 +256,19 @@ class CrunchyrollIE(CrunchyrollBaseIE, VRVIE):
|
|||||||
'1080': ('80', '108'),
|
'1080': ('80', '108'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _download_webpage(self, url_or_request, *args, **kwargs):
|
||||||
|
request = (url_or_request if isinstance(url_or_request, compat_urllib_request.Request)
|
||||||
|
else sanitized_Request(url_or_request))
|
||||||
|
# Accept-Language must be set explicitly to accept any language to avoid issues
|
||||||
|
# similar to https://github.com/ytdl-org/youtube-dl/issues/6797.
|
||||||
|
# Along with IP address Crunchyroll uses Accept-Language to guess whether georestriction
|
||||||
|
# should be imposed or not (from what I can see it just takes the first language
|
||||||
|
# ignoring the priority and requires it to correspond the IP). By the way this causes
|
||||||
|
# Crunchyroll to not work in georestriction cases in some browsers that don't place
|
||||||
|
# the locale lang first in header. However allowing any language seems to workaround the issue.
|
||||||
|
request.add_header('Accept-Language', '*')
|
||||||
|
return super(CrunchyrollBaseIE, self)._download_webpage(request, *args, **kwargs)
|
||||||
|
|
||||||
def _decrypt_subtitles(self, data, iv, id):
|
def _decrypt_subtitles(self, data, iv, id):
|
||||||
data = bytes_to_intlist(compat_b64decode(data))
|
data = bytes_to_intlist(compat_b64decode(data))
|
||||||
iv = bytes_to_intlist(compat_b64decode(iv))
|
iv = bytes_to_intlist(compat_b64decode(iv))
|
||||||
@ -661,9 +661,8 @@ class CrunchyrollShowPlaylistIE(CrunchyrollBaseIE):
|
|||||||
webpage = self._download_webpage(
|
webpage = self._download_webpage(
|
||||||
self._add_skip_wall(url), show_id,
|
self._add_skip_wall(url), show_id,
|
||||||
headers=self.geo_verification_headers())
|
headers=self.geo_verification_headers())
|
||||||
title = self._html_search_regex(
|
title = self._html_search_meta('name', webpage, default=None)
|
||||||
r'(?s)<h1[^>]*>\s*<span itemprop="name">(.*?)</span>',
|
|
||||||
webpage, 'title')
|
|
||||||
episode_paths = re.findall(
|
episode_paths = re.findall(
|
||||||
r'(?s)<li id="showview_videos_media_(\d+)"[^>]+>.*?<a href="([^"]+)"',
|
r'(?s)<li id="showview_videos_media_(\d+)"[^>]+>.*?<a href="([^"]+)"',
|
||||||
webpage)
|
webpage)
|
||||||
|
@ -173,6 +173,7 @@ from .cbs import CBSIE
|
|||||||
from .cbslocal import CBSLocalIE
|
from .cbslocal import CBSLocalIE
|
||||||
from .cbsinteractive import CBSInteractiveIE
|
from .cbsinteractive import CBSInteractiveIE
|
||||||
from .cbsnews import (
|
from .cbsnews import (
|
||||||
|
CBSNewsEmbedIE,
|
||||||
CBSNewsIE,
|
CBSNewsIE,
|
||||||
CBSNewsLiveVideoIE,
|
CBSNewsLiveVideoIE,
|
||||||
)
|
)
|
||||||
@ -891,8 +892,9 @@ from .porncom import PornComIE
|
|||||||
from .pornhd import PornHdIE
|
from .pornhd import PornHdIE
|
||||||
from .pornhub import (
|
from .pornhub import (
|
||||||
PornHubIE,
|
PornHubIE,
|
||||||
PornHubPlaylistIE,
|
PornHubUserIE,
|
||||||
PornHubUserVideosIE,
|
PornHubPagedVideoListIE,
|
||||||
|
PornHubUserVideosUploadIE,
|
||||||
)
|
)
|
||||||
from .pornotube import PornotubeIE
|
from .pornotube import PornotubeIE
|
||||||
from .pornovoisines import PornoVoisinesIE
|
from .pornovoisines import PornoVoisinesIE
|
||||||
@ -941,7 +943,10 @@ from .raywenderlich import (
|
|||||||
)
|
)
|
||||||
from .rbmaradio import RBMARadioIE
|
from .rbmaradio import RBMARadioIE
|
||||||
from .rds import RDSIE
|
from .rds import RDSIE
|
||||||
from .redbulltv import RedBullTVIE
|
from .redbulltv import (
|
||||||
|
RedBullTVIE,
|
||||||
|
RedBullTVRrnContentIE,
|
||||||
|
)
|
||||||
from .reddit import (
|
from .reddit import (
|
||||||
RedditIE,
|
RedditIE,
|
||||||
RedditRIE,
|
RedditRIE,
|
||||||
|
@ -244,7 +244,7 @@ class PhantomJSwrapper(object):
|
|||||||
|
|
||||||
|
|
||||||
class OpenloadIE(InfoExtractor):
|
class OpenloadIE(InfoExtractor):
|
||||||
_DOMAINS = r'(?:openload\.(?:co|io|link|pw)|oload\.(?:tv|stream|site|xyz|win|download|cloud|cc|icu|fun|club|info|press|pw|live|space|services)|oladblock\.(?:services|xyz|me)|openloed\.co)'
|
_DOMAINS = r'(?:openload\.(?:co|io|link|pw)|oload\.(?:tv|stream|site|xyz|win|download|cloud|cc|icu|fun|club|info|press|pw|life|live|space|services|website)|oladblock\.(?:services|xyz|me)|openloed\.co)'
|
||||||
_VALID_URL = r'''(?x)
|
_VALID_URL = r'''(?x)
|
||||||
https?://
|
https?://
|
||||||
(?P<host>
|
(?P<host>
|
||||||
@ -360,6 +360,12 @@ class OpenloadIE(InfoExtractor):
|
|||||||
}, {
|
}, {
|
||||||
'url': 'https://oload.press/embed/drTBl1aOTvk/',
|
'url': 'https://oload.press/embed/drTBl1aOTvk/',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://oload.website/embed/drTBl1aOTvk/',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://oload.life/embed/oOzZjNPw9Dc/',
|
||||||
|
'only_matching': True,
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://oladblock.services/f/b8NWEgkqNLI/',
|
'url': 'https://oladblock.services/f/b8NWEgkqNLI/',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
|
@ -372,37 +372,92 @@ class PornHubPlaylistBaseIE(PornHubBaseIE):
|
|||||||
entries, playlist_id, title, playlist.get('description'))
|
entries, playlist_id, title, playlist.get('description'))
|
||||||
|
|
||||||
|
|
||||||
class PornHubPlaylistIE(PornHubPlaylistBaseIE):
|
class PornHubUserIE(PornHubPlaylistBaseIE):
|
||||||
_VALID_URL = r'https?://(?:[^/]+\.)?(?P<host>pornhub\.(?:com|net))/playlist/(?P<id>\d+)'
|
_VALID_URL = r'(?P<url>https?://(?:[^/]+\.)?pornhub\.(?:com|net)/(?:(?:user|channel)s|model|pornstar)/(?P<id>[^/?#&]+))(?:[?#&]|/(?!videos)|$)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
'url': 'http://www.pornhub.com/playlist/4667351',
|
'url': 'https://www.pornhub.com/model/zoe_ph',
|
||||||
'info_dict': {
|
'playlist_mincount': 118,
|
||||||
'id': '4667351',
|
|
||||||
'title': 'Nataly Hot',
|
|
||||||
},
|
|
||||||
'playlist_mincount': 2,
|
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://de.pornhub.com/playlist/4667351',
|
'url': 'https://www.pornhub.com/pornstar/liz-vicious',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'liz-vicious',
|
||||||
|
},
|
||||||
|
'playlist_mincount': 118,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/users/russianveet69',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/channels/povd',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/model/zoe_ph?abc=1',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
mobj = re.match(self._VALID_URL, url)
|
||||||
|
user_id = mobj.group('id')
|
||||||
|
return self.url_result(
|
||||||
|
'%s/videos' % mobj.group('url'), ie=PornHubPagedVideoListIE.ie_key(),
|
||||||
|
video_id=user_id)
|
||||||
|
|
||||||
class PornHubUserVideosIE(PornHubPlaylistBaseIE):
|
|
||||||
_VALID_URL = r'https?://(?:[^/]+\.)?(?P<host>pornhub\.(?:com|net))/(?:(?:user|channel)s|model|pornstar)/(?P<id>[^/]+)/videos'
|
class PornHubPagedPlaylistBaseIE(PornHubPlaylistBaseIE):
|
||||||
|
def _real_extract(self, url):
|
||||||
|
mobj = re.match(self._VALID_URL, url)
|
||||||
|
host = mobj.group('host')
|
||||||
|
item_id = mobj.group('id')
|
||||||
|
|
||||||
|
page = int_or_none(self._search_regex(
|
||||||
|
r'\bpage=(\d+)', url, 'page', default=None))
|
||||||
|
|
||||||
|
page_url = self._make_page_url(url)
|
||||||
|
|
||||||
|
entries = []
|
||||||
|
for page_num in (page, ) if page is not None else itertools.count(1):
|
||||||
|
try:
|
||||||
|
webpage = self._download_webpage(
|
||||||
|
page_url, item_id, 'Downloading page %d' % page_num,
|
||||||
|
query={'page': page_num})
|
||||||
|
except ExtractorError as e:
|
||||||
|
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 404:
|
||||||
|
break
|
||||||
|
raise
|
||||||
|
page_entries = self._extract_entries(webpage, host)
|
||||||
|
if not page_entries:
|
||||||
|
break
|
||||||
|
entries.extend(page_entries)
|
||||||
|
if not self._has_more(webpage):
|
||||||
|
break
|
||||||
|
|
||||||
|
return self.playlist_result(orderedSet(entries), item_id)
|
||||||
|
|
||||||
|
|
||||||
|
class PornHubPagedVideoListIE(PornHubPagedPlaylistBaseIE):
|
||||||
|
_VALID_URL = r'https?://(?:[^/]+\.)?(?P<host>pornhub\.(?:com|net))/(?P<id>(?:[^/]+/)*[^/?#&]+)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
'url': 'http://www.pornhub.com/users/zoe_ph/videos/public',
|
'url': 'https://www.pornhub.com/model/zoe_ph/videos',
|
||||||
'info_dict': {
|
'only_matching': True,
|
||||||
'id': 'zoe_ph',
|
|
||||||
},
|
|
||||||
'playlist_mincount': 171,
|
|
||||||
}, {
|
}, {
|
||||||
'url': 'http://www.pornhub.com/users/rushandlia/videos',
|
'url': 'http://www.pornhub.com/users/rushandlia/videos',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/pornstar/jenny-blighe/videos',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'pornstar/jenny-blighe/videos',
|
||||||
|
},
|
||||||
|
'playlist_mincount': 149,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/pornstar/jenny-blighe/videos?page=3',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'pornstar/jenny-blighe/videos',
|
||||||
|
},
|
||||||
|
'playlist_mincount': 40,
|
||||||
}, {
|
}, {
|
||||||
# default sorting as Top Rated Videos
|
# default sorting as Top Rated Videos
|
||||||
'url': 'https://www.pornhub.com/channels/povd/videos',
|
'url': 'https://www.pornhub.com/channels/povd/videos',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'povd',
|
'id': 'channels/povd/videos',
|
||||||
},
|
},
|
||||||
'playlist_mincount': 293,
|
'playlist_mincount': 293,
|
||||||
}, {
|
}, {
|
||||||
@ -421,31 +476,107 @@ class PornHubUserVideosIE(PornHubPlaylistBaseIE):
|
|||||||
'url': 'http://www.pornhub.com/users/zoe_ph/videos/public',
|
'url': 'http://www.pornhub.com/users/zoe_ph/videos/public',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://www.pornhub.com/model/jayndrea/videos/upload',
|
# Most Viewed Videos
|
||||||
|
'url': 'https://www.pornhub.com/pornstar/liz-vicious/videos?o=mv',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://www.pornhub.com/pornstar/jenny-blighe/videos/upload',
|
# Top Rated Videos
|
||||||
|
'url': 'https://www.pornhub.com/pornstar/liz-vicious/videos?o=tr',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
# Longest Videos
|
||||||
|
'url': 'https://www.pornhub.com/pornstar/liz-vicious/videos?o=lg',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
# Newest Videos
|
||||||
|
'url': 'https://www.pornhub.com/pornstar/liz-vicious/videos?o=cm',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/pornstar/liz-vicious/videos/paid',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/pornstar/liz-vicious/videos/fanonly',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/video',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/video?page=3',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/video/search?search=123',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/categories/teen',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/categories/teen?page=3',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/hd',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/hd?page=3',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/described-video',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/described-video?page=2',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/video/incategories/60fps-1/hd-porn',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/playlist/44121572',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'playlist/44121572',
|
||||||
|
},
|
||||||
|
'playlist_mincount': 132,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/playlist/4667351',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://de.pornhub.com/playlist/4667351',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def _real_extract(self, url):
|
@classmethod
|
||||||
|
def suitable(cls, url):
|
||||||
|
return (False
|
||||||
|
if PornHubIE.suitable(url) or PornHubUserIE.suitable(url) or PornHubUserVideosUploadIE.suitable(url)
|
||||||
|
else super(PornHubPagedVideoListIE, cls).suitable(url))
|
||||||
|
|
||||||
|
def _make_page_url(self, url):
|
||||||
|
return url
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _has_more(webpage):
|
||||||
|
return re.search(
|
||||||
|
r'''(?x)
|
||||||
|
<li[^>]+\bclass=["\']page_next|
|
||||||
|
<link[^>]+\brel=["\']next|
|
||||||
|
<button[^>]+\bid=["\']moreDataBtn
|
||||||
|
''', webpage) is not None
|
||||||
|
|
||||||
|
|
||||||
|
class PornHubUserVideosUploadIE(PornHubPagedPlaylistBaseIE):
|
||||||
|
_VALID_URL = r'(?P<url>https?://(?:[^/]+\.)?(?P<host>pornhub\.(?:com|net))/(?:(?:user|channel)s|model|pornstar)/(?P<id>[^/]+)/videos/upload)'
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://www.pornhub.com/pornstar/jenny-blighe/videos/upload',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'jenny-blighe',
|
||||||
|
},
|
||||||
|
'playlist_mincount': 129,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.pornhub.com/model/zoe_ph/videos/upload',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _make_page_url(self, url):
|
||||||
mobj = re.match(self._VALID_URL, url)
|
mobj = re.match(self._VALID_URL, url)
|
||||||
host = mobj.group('host')
|
return '%s/ajax' % mobj.group('url')
|
||||||
user_id = mobj.group('id')
|
|
||||||
|
|
||||||
entries = []
|
@staticmethod
|
||||||
for page_num in itertools.count(1):
|
def _has_more(webpage):
|
||||||
try:
|
return True
|
||||||
webpage = self._download_webpage(
|
|
||||||
url, user_id, 'Downloading page %d' % page_num,
|
|
||||||
query={'page': page_num})
|
|
||||||
except ExtractorError as e:
|
|
||||||
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 404:
|
|
||||||
break
|
|
||||||
raise
|
|
||||||
page_entries = self._extract_entries(webpage, host)
|
|
||||||
if not page_entries:
|
|
||||||
break
|
|
||||||
entries.extend(page_entries)
|
|
||||||
|
|
||||||
return self.playlist_result(entries, user_id)
|
|
||||||
|
@ -104,3 +104,25 @@ class RedBullTVIE(InfoExtractor):
|
|||||||
'formats': formats,
|
'formats': formats,
|
||||||
'subtitles': subtitles,
|
'subtitles': subtitles,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class RedBullTVRrnContentIE(InfoExtractor):
|
||||||
|
_VALID_URL = r'https?://(?:www\.)?redbull(?:\.tv|\.com(?:/[^/]+)?(?:/tv)?)/(?:video|live)/rrn:content:[^:]+:(?P<id>[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12})'
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://www.redbull.com/int-en/tv/video/rrn:content:live-videos:e3e6feb4-e95f-50b7-962a-c70f8fd13c73/mens-dh-finals-fort-william',
|
||||||
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.redbull.com/int-en/tv/video/rrn:content:videos:a36a0f36-ff1b-5db8-a69d-ee11a14bf48b/tn-ts-style?playlist=rrn:content:event-profiles:83f05926-5de8-5389-b5e4-9bb312d715e8:extras',
|
||||||
|
'only_matching': True,
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
display_id = self._match_id(url)
|
||||||
|
|
||||||
|
webpage = self._download_webpage(url, display_id)
|
||||||
|
|
||||||
|
video_url = self._og_search_url(webpage)
|
||||||
|
|
||||||
|
return self.url_result(
|
||||||
|
video_url, ie=RedBullTVIE.ie_key(),
|
||||||
|
video_id=RedBullTVIE._match_id(video_url))
|
||||||
|
@ -19,7 +19,7 @@ from ..utils import (
|
|||||||
|
|
||||||
class SixPlayIE(InfoExtractor):
|
class SixPlayIE(InfoExtractor):
|
||||||
IE_NAME = '6play'
|
IE_NAME = '6play'
|
||||||
_VALID_URL = r'(?:6play:|https?://(?:www\.)?(?P<domain>6play\.fr|rtlplay\.be|play\.rtl\.hr)/.+?-c_)(?P<id>[0-9]+)'
|
_VALID_URL = r'(?:6play:|https?://(?:www\.)?(?P<domain>6play\.fr|rtlplay\.be|play\.rtl\.hr|rtlmost\.hu)/.+?-c_)(?P<id>[0-9]+)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
'url': 'https://www.6play.fr/minute-par-minute-p_9533/le-but-qui-a-marque-lhistoire-du-football-francais-c_12041051',
|
'url': 'https://www.6play.fr/minute-par-minute-p_9533/le-but-qui-a-marque-lhistoire-du-football-francais-c_12041051',
|
||||||
'md5': '31fcd112637baa0c2ab92c4fcd8baf27',
|
'md5': '31fcd112637baa0c2ab92c4fcd8baf27',
|
||||||
@ -35,6 +35,9 @@ class SixPlayIE(InfoExtractor):
|
|||||||
}, {
|
}, {
|
||||||
'url': 'https://play.rtl.hr/pj-masks-p_9455/epizoda-34-sezona-1-catboyevo-cudo-na-dva-kotaca-c_11984989',
|
'url': 'https://play.rtl.hr/pj-masks-p_9455/epizoda-34-sezona-1-catboyevo-cudo-na-dva-kotaca-c_11984989',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.rtlmost.hu/megtorve-p_14167/megtorve-6-resz-c_12397787',
|
||||||
|
'only_matching': True,
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
@ -43,6 +46,7 @@ class SixPlayIE(InfoExtractor):
|
|||||||
'6play.fr': ('6play', 'm6web'),
|
'6play.fr': ('6play', 'm6web'),
|
||||||
'rtlplay.be': ('rtlbe_rtl_play', 'rtlbe'),
|
'rtlplay.be': ('rtlbe_rtl_play', 'rtlbe'),
|
||||||
'play.rtl.hr': ('rtlhr_rtl_play', 'rtlhr'),
|
'play.rtl.hr': ('rtlhr_rtl_play', 'rtlhr'),
|
||||||
|
'rtlmost.hu': ('rtlhu_rtl_most', 'rtlhu'),
|
||||||
}.get(domain, ('6play', 'm6web'))
|
}.get(domain, ('6play', 'm6web'))
|
||||||
|
|
||||||
data = self._download_json(
|
data = self._download_json(
|
||||||
|
@ -5,8 +5,12 @@ import re
|
|||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
|
|
||||||
from ..compat import compat_str
|
from ..compat import (
|
||||||
|
compat_str,
|
||||||
|
compat_urlparse
|
||||||
|
)
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
|
extract_attributes,
|
||||||
float_or_none,
|
float_or_none,
|
||||||
int_or_none,
|
int_or_none,
|
||||||
try_get,
|
try_get,
|
||||||
@ -20,7 +24,7 @@ class TEDIE(InfoExtractor):
|
|||||||
(?P<proto>https?://)
|
(?P<proto>https?://)
|
||||||
(?P<type>www|embed(?:-ssl)?)(?P<urlmain>\.ted\.com/
|
(?P<type>www|embed(?:-ssl)?)(?P<urlmain>\.ted\.com/
|
||||||
(
|
(
|
||||||
(?P<type_playlist>playlists(?:/\d+)?) # We have a playlist
|
(?P<type_playlist>playlists(?:/(?P<playlist_id>\d+))?) # We have a playlist
|
||||||
|
|
|
|
||||||
((?P<type_talk>talks)) # We have a simple talk
|
((?P<type_talk>talks)) # We have a simple talk
|
||||||
|
|
|
|
||||||
@ -84,6 +88,7 @@ class TEDIE(InfoExtractor):
|
|||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '10',
|
'id': '10',
|
||||||
'title': 'Who are the hackers?',
|
'title': 'Who are the hackers?',
|
||||||
|
'description': 'md5:49a0dbe8fb76d81a0e64b4a80af7f15a'
|
||||||
},
|
},
|
||||||
'playlist_mincount': 6,
|
'playlist_mincount': 6,
|
||||||
}, {
|
}, {
|
||||||
@ -150,22 +155,22 @@ class TEDIE(InfoExtractor):
|
|||||||
|
|
||||||
webpage = self._download_webpage(url, name,
|
webpage = self._download_webpage(url, name,
|
||||||
'Downloading playlist webpage')
|
'Downloading playlist webpage')
|
||||||
info = self._extract_info(webpage)
|
|
||||||
|
|
||||||
playlist_info = try_get(
|
playlist_entries = []
|
||||||
info, lambda x: x['__INITIAL_DATA__']['playlist'],
|
for entry in re.findall(r'(?s)<[^>]+data-ga-context=["\']playlist["\'][^>]*>', webpage):
|
||||||
dict) or info['playlist']
|
attrs = extract_attributes(entry)
|
||||||
|
entry_url = compat_urlparse.urljoin(url, attrs['href'])
|
||||||
|
playlist_entries.append(self.url_result(entry_url, self.ie_key()))
|
||||||
|
|
||||||
|
final_url = self._og_search_url(webpage, fatal=False)
|
||||||
|
playlist_id = (
|
||||||
|
re.match(self._VALID_URL, final_url).group('playlist_id')
|
||||||
|
if final_url else None)
|
||||||
|
|
||||||
playlist_entries = [
|
|
||||||
self.url_result('http://www.ted.com/talks/' + talk['slug'], self.ie_key())
|
|
||||||
for talk in try_get(
|
|
||||||
info, lambda x: x['__INITIAL_DATA__']['talks'],
|
|
||||||
dict) or info['talks']
|
|
||||||
]
|
|
||||||
return self.playlist_result(
|
return self.playlist_result(
|
||||||
playlist_entries,
|
playlist_entries, playlist_id=playlist_id,
|
||||||
playlist_id=compat_str(playlist_info['id']),
|
playlist_title=self._og_search_title(webpage, fatal=False),
|
||||||
playlist_title=playlist_info['title'])
|
playlist_description=self._og_search_description(webpage))
|
||||||
|
|
||||||
def _talk_info(self, url, video_name):
|
def _talk_info(self, url, video_name):
|
||||||
webpage = self._download_webpage(url, video_name)
|
webpage = self._download_webpage(url, video_name)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
|
from ..compat import compat_str
|
||||||
|
|
||||||
|
|
||||||
class TF1IE(InfoExtractor):
|
class TF1IE(InfoExtractor):
|
||||||
@ -43,12 +44,49 @@ class TF1IE(InfoExtractor):
|
|||||||
}, {
|
}, {
|
||||||
'url': 'http://www.tf1.fr/hd1/documentaire/videos/mylene-farmer-d-une-icone.html',
|
'url': 'http://www.tf1.fr/hd1/documentaire/videos/mylene-farmer-d-une-icone.html',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.tf1.fr/tmc/quotidien-avec-yann-barthes/videos/quotidien-premiere-partie-11-juin-2019.html',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '13641379',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'md5:f392bc52245dc5ad43771650c96fb620',
|
||||||
|
'description': 'md5:44bc54f0a21322f5b91d68e76a544eae',
|
||||||
|
'upload_date': '20190611',
|
||||||
|
},
|
||||||
|
'params': {
|
||||||
|
# Sometimes wat serves the whole file with the --test option
|
||||||
|
'skip_download': True,
|
||||||
|
},
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
video_id = self._match_id(url)
|
video_id = self._match_id(url)
|
||||||
|
|
||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, video_id)
|
||||||
wat_id = self._html_search_regex(
|
|
||||||
r'(["\'])(?:https?:)?//www\.wat\.tv/embedframe/.*?(?P<id>\d{8})\1',
|
wat_id = None
|
||||||
webpage, 'wat id', group='id')
|
|
||||||
|
data = self._parse_json(
|
||||||
|
self._search_regex(
|
||||||
|
r'__APOLLO_STATE__\s*=\s*({.+?})\s*(?:;|</script>)', webpage,
|
||||||
|
'data', default='{}'), video_id, fatal=False)
|
||||||
|
|
||||||
|
if data:
|
||||||
|
try:
|
||||||
|
wat_id = next(
|
||||||
|
video.get('streamId')
|
||||||
|
for key, video in data.items()
|
||||||
|
if isinstance(video, dict)
|
||||||
|
and video.get('slug') == video_id)
|
||||||
|
if not isinstance(wat_id, compat_str) or not wat_id.isdigit():
|
||||||
|
wat_id = None
|
||||||
|
except StopIteration:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not wat_id:
|
||||||
|
wat_id = self._html_search_regex(
|
||||||
|
(r'(["\'])(?:https?:)?//www\.wat\.tv/embedframe/.*?(?P<id>\d{8})\1',
|
||||||
|
r'(["\']?)streamId\1\s*:\s*(["\']?)(?P<id>\d+)\2'),
|
||||||
|
webpage, 'wat id', group='id')
|
||||||
|
|
||||||
return self.url_result('wat:%s' % wat_id, 'Wat')
|
return self.url_result('wat:%s' % wat_id, 'Wat')
|
||||||
|
@ -38,7 +38,7 @@ class TouTvIE(RadioCanadaIE):
|
|||||||
'url': 'https://ici.tou.tv/l-age-adulte/S01C501',
|
'url': 'https://ici.tou.tv/l-age-adulte/S01C501',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
}]
|
}]
|
||||||
_CLIENT_KEY = '4dd36440-09d5-4468-8923-b6d91174ad36'
|
_CLIENT_KEY = '90505c8d-9c34-4f34-8da1-3a85bdc6d4f4'
|
||||||
|
|
||||||
def _real_initialize(self):
|
def _real_initialize(self):
|
||||||
email, password = self._get_login_info()
|
email, password = self._get_login_info()
|
||||||
|
@ -47,15 +47,23 @@ class TVNowBaseIE(InfoExtractor):
|
|||||||
r'\.ism/(?:[^.]*\.(?:m3u8|mpd)|[Mm]anifest)',
|
r'\.ism/(?:[^.]*\.(?:m3u8|mpd)|[Mm]anifest)',
|
||||||
'.ism/' + suffix, manifest_url))
|
'.ism/' + suffix, manifest_url))
|
||||||
|
|
||||||
formats = self._extract_mpd_formats(
|
def make_urls(proto, suffix):
|
||||||
url_repl('dash', '.mpd'), video_id,
|
urls = [url_repl(proto, suffix)]
|
||||||
mpd_id='dash', fatal=False)
|
hd_url = urls[0].replace('/manifest/', '/ngvod/')
|
||||||
formats.extend(self._extract_ism_formats(
|
if hd_url != urls[0]:
|
||||||
url_repl('hss', 'Manifest'),
|
urls.append(hd_url)
|
||||||
video_id, ism_id='mss', fatal=False))
|
return urls
|
||||||
formats.extend(self._extract_m3u8_formats(
|
|
||||||
url_repl('hls', '.m3u8'), video_id, 'mp4',
|
for man_url in make_urls('dash', '.mpd'):
|
||||||
'm3u8_native', m3u8_id='hls', fatal=False))
|
formats = self._extract_mpd_formats(
|
||||||
|
man_url, video_id, mpd_id='dash', fatal=False)
|
||||||
|
for man_url in make_urls('hss', 'Manifest'):
|
||||||
|
formats.extend(self._extract_ism_formats(
|
||||||
|
man_url, video_id, ism_id='mss', fatal=False))
|
||||||
|
for man_url in make_urls('hls', '.m3u8'):
|
||||||
|
formats.extend(self._extract_m3u8_formats(
|
||||||
|
man_url, video_id, 'mp4', 'm3u8_native', m3u8_id='hls',
|
||||||
|
fatal=False))
|
||||||
if formats:
|
if formats:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
@ -16,7 +16,6 @@ from ..utils import (
|
|||||||
determine_ext,
|
determine_ext,
|
||||||
ExtractorError,
|
ExtractorError,
|
||||||
js_to_json,
|
js_to_json,
|
||||||
InAdvancePagedList,
|
|
||||||
int_or_none,
|
int_or_none,
|
||||||
merge_dicts,
|
merge_dicts,
|
||||||
NO_DEFAULT,
|
NO_DEFAULT,
|
||||||
@ -814,7 +813,8 @@ class VimeoChannelIE(VimeoBaseInfoExtractor):
|
|||||||
return '%s/videos/page:%d/' % (base_url, pagenum)
|
return '%s/videos/page:%d/' % (base_url, pagenum)
|
||||||
|
|
||||||
def _extract_list_title(self, webpage):
|
def _extract_list_title(self, webpage):
|
||||||
return self._TITLE or self._html_search_regex(self._TITLE_RE, webpage, 'list title')
|
return self._TITLE or self._html_search_regex(
|
||||||
|
self._TITLE_RE, webpage, 'list title', fatal=False)
|
||||||
|
|
||||||
def _login_list_password(self, page_url, list_id, webpage):
|
def _login_list_password(self, page_url, list_id, webpage):
|
||||||
login_form = self._search_regex(
|
login_form = self._search_regex(
|
||||||
@ -955,7 +955,7 @@ class VimeoGroupsIE(VimeoAlbumIE):
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
def _extract_list_title(self, webpage):
|
def _extract_list_title(self, webpage):
|
||||||
return self._og_search_title(webpage)
|
return self._og_search_title(webpage, fatal=False)
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
mobj = re.match(self._VALID_URL, url)
|
mobj = re.match(self._VALID_URL, url)
|
||||||
@ -1065,7 +1065,7 @@ class VimeoWatchLaterIE(VimeoChannelIE):
|
|||||||
return self._extract_videos('watchlater', 'https://vimeo.com/watchlater')
|
return self._extract_videos('watchlater', 'https://vimeo.com/watchlater')
|
||||||
|
|
||||||
|
|
||||||
class VimeoLikesIE(InfoExtractor):
|
class VimeoLikesIE(VimeoChannelIE):
|
||||||
_VALID_URL = r'https://(?:www\.)?vimeo\.com/(?P<id>[^/]+)/likes/?(?:$|[?#]|sort:)'
|
_VALID_URL = r'https://(?:www\.)?vimeo\.com/(?P<id>[^/]+)/likes/?(?:$|[?#]|sort:)'
|
||||||
IE_NAME = 'vimeo:likes'
|
IE_NAME = 'vimeo:likes'
|
||||||
IE_DESC = 'Vimeo user likes'
|
IE_DESC = 'Vimeo user likes'
|
||||||
@ -1073,55 +1073,20 @@ class VimeoLikesIE(InfoExtractor):
|
|||||||
'url': 'https://vimeo.com/user755559/likes/',
|
'url': 'https://vimeo.com/user755559/likes/',
|
||||||
'playlist_mincount': 293,
|
'playlist_mincount': 293,
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'user755559_likes',
|
'id': 'user755559',
|
||||||
'description': 'See all the videos urza likes',
|
'title': 'urza’s Likes',
|
||||||
'title': 'Videos urza likes',
|
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://vimeo.com/stormlapse/likes',
|
'url': 'https://vimeo.com/stormlapse/likes',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
def _page_url(self, base_url, pagenum):
|
||||||
|
return '%s/page:%d/' % (base_url, pagenum)
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
user_id = self._match_id(url)
|
user_id = self._match_id(url)
|
||||||
webpage = self._download_webpage(url, user_id)
|
return self._extract_videos(user_id, 'https://vimeo.com/%s/likes' % user_id)
|
||||||
page_count = self._int(
|
|
||||||
self._search_regex(
|
|
||||||
r'''(?x)<li><a\s+href="[^"]+"\s+data-page="([0-9]+)">
|
|
||||||
.*?</a></li>\s*<li\s+class="pagination_next">
|
|
||||||
''', webpage, 'page count', default=1),
|
|
||||||
'page count', fatal=True)
|
|
||||||
PAGE_SIZE = 12
|
|
||||||
title = self._html_search_regex(
|
|
||||||
r'(?s)<h1>(.+?)</h1>', webpage, 'title', fatal=False)
|
|
||||||
description = self._html_search_meta('description', webpage)
|
|
||||||
|
|
||||||
def _get_page(idx):
|
|
||||||
page_url = 'https://vimeo.com/%s/likes/page:%d/sort:date' % (
|
|
||||||
user_id, idx + 1)
|
|
||||||
webpage = self._download_webpage(
|
|
||||||
page_url, user_id,
|
|
||||||
note='Downloading page %d/%d' % (idx + 1, page_count))
|
|
||||||
video_list = self._search_regex(
|
|
||||||
r'(?s)<ol class="js-browse_list[^"]+"[^>]*>(.*?)</ol>',
|
|
||||||
webpage, 'video content')
|
|
||||||
paths = re.findall(
|
|
||||||
r'<li[^>]*>\s*<a\s+href="([^"]+)"', video_list)
|
|
||||||
for path in paths:
|
|
||||||
yield {
|
|
||||||
'_type': 'url',
|
|
||||||
'url': compat_urlparse.urljoin(page_url, path),
|
|
||||||
}
|
|
||||||
|
|
||||||
pl = InAdvancePagedList(_get_page, page_count, PAGE_SIZE)
|
|
||||||
|
|
||||||
return {
|
|
||||||
'_type': 'playlist',
|
|
||||||
'id': '%s_likes' % user_id,
|
|
||||||
'title': title,
|
|
||||||
'description': description,
|
|
||||||
'entries': pl,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class VHXEmbedIE(InfoExtractor):
|
class VHXEmbedIE(InfoExtractor):
|
||||||
|
@ -24,6 +24,7 @@ from ..utils import (
|
|||||||
class VLiveIE(InfoExtractor):
|
class VLiveIE(InfoExtractor):
|
||||||
IE_NAME = 'vlive'
|
IE_NAME = 'vlive'
|
||||||
_VALID_URL = r'https?://(?:(?:www|m)\.)?vlive\.tv/video/(?P<id>[0-9]+)'
|
_VALID_URL = r'https?://(?:(?:www|m)\.)?vlive\.tv/video/(?P<id>[0-9]+)'
|
||||||
|
_NETRC_MACHINE = 'vlive'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
'url': 'http://www.vlive.tv/video/1326',
|
'url': 'http://www.vlive.tv/video/1326',
|
||||||
'md5': 'cc7314812855ce56de70a06a27314983',
|
'md5': 'cc7314812855ce56de70a06a27314983',
|
||||||
@ -47,12 +48,55 @@ class VLiveIE(InfoExtractor):
|
|||||||
'params': {
|
'params': {
|
||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
},
|
},
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.vlive.tv/video/129100',
|
||||||
|
'md5': 'ca2569453b79d66e5b919e5d308bff6b',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '129100',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': '[V LIVE] [BTS+] Run BTS! 2019 - EP.71 :: Behind the scene',
|
||||||
|
'creator': 'BTS+',
|
||||||
|
'view_count': int,
|
||||||
|
'subtitles': 'mincount:10',
|
||||||
|
},
|
||||||
|
'skip': 'This video is only available for CH+ subscribers',
|
||||||
}]
|
}]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def suitable(cls, url):
|
def suitable(cls, url):
|
||||||
return False if VLivePlaylistIE.suitable(url) else super(VLiveIE, cls).suitable(url)
|
return False if VLivePlaylistIE.suitable(url) else super(VLiveIE, cls).suitable(url)
|
||||||
|
|
||||||
|
def _real_initialize(self):
|
||||||
|
self._login()
|
||||||
|
|
||||||
|
def _login(self):
|
||||||
|
email, password = self._get_login_info()
|
||||||
|
if None in (email, password):
|
||||||
|
return
|
||||||
|
|
||||||
|
def is_logged_in():
|
||||||
|
login_info = self._download_json(
|
||||||
|
'https://www.vlive.tv/auth/loginInfo', None,
|
||||||
|
note='Downloading login info',
|
||||||
|
headers={'Referer': 'https://www.vlive.tv/home'})
|
||||||
|
return try_get(
|
||||||
|
login_info, lambda x: x['message']['login'], bool) or False
|
||||||
|
|
||||||
|
LOGIN_URL = 'https://www.vlive.tv/auth/email/login'
|
||||||
|
self._request_webpage(
|
||||||
|
LOGIN_URL, None, note='Downloading login cookies')
|
||||||
|
|
||||||
|
self._download_webpage(
|
||||||
|
LOGIN_URL, None, note='Logging in',
|
||||||
|
data=urlencode_postdata({'email': email, 'pwd': password}),
|
||||||
|
headers={
|
||||||
|
'Referer': LOGIN_URL,
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
})
|
||||||
|
|
||||||
|
if not is_logged_in():
|
||||||
|
raise ExtractorError('Unable to log in', expected=True)
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
video_id = self._match_id(url)
|
video_id = self._match_id(url)
|
||||||
|
|
||||||
@ -77,10 +121,7 @@ class VLiveIE(InfoExtractor):
|
|||||||
if status in ('LIVE_ON_AIR', 'BIG_EVENT_ON_AIR'):
|
if status in ('LIVE_ON_AIR', 'BIG_EVENT_ON_AIR'):
|
||||||
return self._live(video_id, webpage)
|
return self._live(video_id, webpage)
|
||||||
elif status in ('VOD_ON_AIR', 'BIG_EVENT_INTRO'):
|
elif status in ('VOD_ON_AIR', 'BIG_EVENT_INTRO'):
|
||||||
if long_video_id and key:
|
return self._replay(video_id, webpage, long_video_id, key)
|
||||||
return self._replay(video_id, webpage, long_video_id, key)
|
|
||||||
else:
|
|
||||||
status = 'COMING_SOON'
|
|
||||||
|
|
||||||
if status == 'LIVE_END':
|
if status == 'LIVE_END':
|
||||||
raise ExtractorError('Uploading for replay. Please wait...',
|
raise ExtractorError('Uploading for replay. Please wait...',
|
||||||
@ -91,13 +132,15 @@ class VLiveIE(InfoExtractor):
|
|||||||
raise ExtractorError('We are sorry, '
|
raise ExtractorError('We are sorry, '
|
||||||
'but the live broadcast has been canceled.',
|
'but the live broadcast has been canceled.',
|
||||||
expected=True)
|
expected=True)
|
||||||
|
elif status == 'ONLY_APP':
|
||||||
|
raise ExtractorError('Unsupported video type', expected=True)
|
||||||
else:
|
else:
|
||||||
raise ExtractorError('Unknown status %s' % status)
|
raise ExtractorError('Unknown status %s' % status)
|
||||||
|
|
||||||
def _get_common_fields(self, webpage):
|
def _get_common_fields(self, webpage):
|
||||||
title = self._og_search_title(webpage)
|
title = self._og_search_title(webpage)
|
||||||
creator = self._html_search_regex(
|
creator = self._html_search_regex(
|
||||||
r'<div[^>]+class="info_area"[^>]*>\s*<a\s+[^>]*>([^<]+)',
|
r'<div[^>]+class="info_area"[^>]*>\s*(?:<em[^>]*>.*?</em\s*>\s*)?<a\s+[^>]*>([^<]+)',
|
||||||
webpage, 'creator', fatal=False)
|
webpage, 'creator', fatal=False)
|
||||||
thumbnail = self._og_search_thumbnail(webpage)
|
thumbnail = self._og_search_thumbnail(webpage)
|
||||||
return {
|
return {
|
||||||
@ -107,14 +150,7 @@ class VLiveIE(InfoExtractor):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def _live(self, video_id, webpage):
|
def _live(self, video_id, webpage):
|
||||||
init_page = self._download_webpage(
|
init_page = self._download_init_page(video_id)
|
||||||
'https://www.vlive.tv/video/init/view',
|
|
||||||
video_id, note='Downloading live webpage',
|
|
||||||
data=urlencode_postdata({'videoSeq': video_id}),
|
|
||||||
headers={
|
|
||||||
'Referer': 'https://www.vlive.tv/video/%s' % video_id,
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
})
|
|
||||||
|
|
||||||
live_params = self._search_regex(
|
live_params = self._search_regex(
|
||||||
r'"liveStreamInfo"\s*:\s*(".*"),',
|
r'"liveStreamInfo"\s*:\s*(".*"),',
|
||||||
@ -140,6 +176,17 @@ class VLiveIE(InfoExtractor):
|
|||||||
return info
|
return info
|
||||||
|
|
||||||
def _replay(self, video_id, webpage, long_video_id, key):
|
def _replay(self, video_id, webpage, long_video_id, key):
|
||||||
|
if '' in (long_video_id, key):
|
||||||
|
init_page = self._download_init_page(video_id)
|
||||||
|
video_info = self._parse_json(self._search_regex(
|
||||||
|
(r'(?s)oVideoStatus\s*=\s*({.+?})\s*</script',
|
||||||
|
r'(?s)oVideoStatus\s*=\s*({.+})'), init_page, 'video info'),
|
||||||
|
video_id)
|
||||||
|
if video_info.get('status') == 'NEED_CHANNEL_PLUS':
|
||||||
|
self.raise_login_required(
|
||||||
|
'This video is only available for CH+ subscribers')
|
||||||
|
long_video_id, key = video_info['vid'], video_info['inkey']
|
||||||
|
|
||||||
playinfo = self._download_json(
|
playinfo = self._download_json(
|
||||||
'http://global.apis.naver.com/rmcnmv/rmcnmv/vod_play_videoInfo.json?%s'
|
'http://global.apis.naver.com/rmcnmv/rmcnmv/vod_play_videoInfo.json?%s'
|
||||||
% compat_urllib_parse_urlencode({
|
% compat_urllib_parse_urlencode({
|
||||||
@ -180,6 +227,16 @@ class VLiveIE(InfoExtractor):
|
|||||||
})
|
})
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
def _download_init_page(self, video_id):
|
||||||
|
return self._download_webpage(
|
||||||
|
'https://www.vlive.tv/video/init/view',
|
||||||
|
video_id, note='Downloading live webpage',
|
||||||
|
data=urlencode_postdata({'videoSeq': video_id}),
|
||||||
|
headers={
|
||||||
|
'Referer': 'https://www.vlive.tv/video/%s' % video_id,
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class VLiveChannelIE(InfoExtractor):
|
class VLiveChannelIE(InfoExtractor):
|
||||||
IE_NAME = 'vlive:channel'
|
IE_NAME = 'vlive:channel'
|
||||||
@ -275,26 +332,45 @@ class VLiveChannelIE(InfoExtractor):
|
|||||||
class VLivePlaylistIE(InfoExtractor):
|
class VLivePlaylistIE(InfoExtractor):
|
||||||
IE_NAME = 'vlive:playlist'
|
IE_NAME = 'vlive:playlist'
|
||||||
_VALID_URL = r'https?://(?:(?:www|m)\.)?vlive\.tv/video/(?P<video_id>[0-9]+)/playlist/(?P<id>[0-9]+)'
|
_VALID_URL = r'https?://(?:(?:www|m)\.)?vlive\.tv/video/(?P<video_id>[0-9]+)/playlist/(?P<id>[0-9]+)'
|
||||||
_TEST = {
|
_VIDEO_URL_TEMPLATE = 'http://www.vlive.tv/video/%s'
|
||||||
|
_TESTS = [{
|
||||||
|
# regular working playlist
|
||||||
|
'url': 'https://www.vlive.tv/video/117956/playlist/117963',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '117963',
|
||||||
|
'title': '아이돌룸(IDOL ROOM) 41회 - (여자)아이들'
|
||||||
|
},
|
||||||
|
'playlist_mincount': 10
|
||||||
|
}, {
|
||||||
|
# playlist with no playlistVideoSeqs
|
||||||
'url': 'http://www.vlive.tv/video/22867/playlist/22912',
|
'url': 'http://www.vlive.tv/video/22867/playlist/22912',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '22912',
|
'id': '22867',
|
||||||
'title': 'Valentine Day Message from TWICE'
|
'ext': 'mp4',
|
||||||
|
'title': '[V LIVE] Valentine Day Message from MINA',
|
||||||
|
'creator': 'TWICE',
|
||||||
|
'view_count': int
|
||||||
},
|
},
|
||||||
'playlist_mincount': 9
|
'params': {
|
||||||
}
|
'skip_download': True,
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _build_video_result(self, video_id, message):
|
||||||
|
self.to_screen(message)
|
||||||
|
return self.url_result(
|
||||||
|
self._VIDEO_URL_TEMPLATE % video_id,
|
||||||
|
ie=VLiveIE.ie_key(), video_id=video_id)
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
mobj = re.match(self._VALID_URL, url)
|
mobj = re.match(self._VALID_URL, url)
|
||||||
video_id, playlist_id = mobj.group('video_id', 'id')
|
video_id, playlist_id = mobj.group('video_id', 'id')
|
||||||
|
|
||||||
VIDEO_URL_TEMPLATE = 'http://www.vlive.tv/video/%s'
|
|
||||||
if self._downloader.params.get('noplaylist'):
|
if self._downloader.params.get('noplaylist'):
|
||||||
self.to_screen(
|
return self._build_video_result(
|
||||||
'Downloading just video %s because of --no-playlist' % video_id)
|
video_id,
|
||||||
return self.url_result(
|
'Downloading just video %s because of --no-playlist'
|
||||||
VIDEO_URL_TEMPLATE % video_id,
|
% video_id)
|
||||||
ie=VLiveIE.ie_key(), video_id=video_id)
|
|
||||||
|
|
||||||
self.to_screen(
|
self.to_screen(
|
||||||
'Downloading playlist %s - add --no-playlist to just download video'
|
'Downloading playlist %s - add --no-playlist to just download video'
|
||||||
@ -304,15 +380,21 @@ class VLivePlaylistIE(InfoExtractor):
|
|||||||
'http://www.vlive.tv/video/%s/playlist/%s'
|
'http://www.vlive.tv/video/%s/playlist/%s'
|
||||||
% (video_id, playlist_id), playlist_id)
|
% (video_id, playlist_id), playlist_id)
|
||||||
|
|
||||||
item_ids = self._parse_json(
|
raw_item_ids = self._search_regex(
|
||||||
self._search_regex(
|
r'playlistVideoSeqs\s*=\s*(\[[^]]+\])', webpage,
|
||||||
r'playlistVideoSeqs\s*=\s*(\[[^]]+\])', webpage,
|
'playlist video seqs', default=None, fatal=False)
|
||||||
'playlist video seqs'),
|
|
||||||
playlist_id)
|
if not raw_item_ids:
|
||||||
|
return self._build_video_result(
|
||||||
|
video_id,
|
||||||
|
'Downloading just video %s because no playlist was found'
|
||||||
|
% video_id)
|
||||||
|
|
||||||
|
item_ids = self._parse_json(raw_item_ids, playlist_id)
|
||||||
|
|
||||||
entries = [
|
entries = [
|
||||||
self.url_result(
|
self.url_result(
|
||||||
VIDEO_URL_TEMPLATE % item_id, ie=VLiveIE.ie_key(),
|
self._VIDEO_URL_TEMPLATE % item_id, ie=VLiveIE.ie_key(),
|
||||||
video_id=compat_str(item_id))
|
video_id=compat_str(item_id))
|
||||||
for item_id in item_ids]
|
for item_id in item_ids]
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ from ..utils import (
|
|||||||
|
|
||||||
|
|
||||||
class VVVVIDIE(InfoExtractor):
|
class VVVVIDIE(InfoExtractor):
|
||||||
_VALID_URL = r'https?://(?:www\.)?vvvvid\.it/#!(?:show|anime|film|series)/(?P<show_id>\d+)/[^/]+/(?P<season_id>\d+)/(?P<id>[0-9]+)'
|
_VALID_URL = r'https?://(?:www\.)?vvvvid\.it/(?:#!)?(?:show|anime|film|series)/(?P<show_id>\d+)/[^/]+/(?P<season_id>\d+)/(?P<id>[0-9]+)'
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
# video_type == 'video/vvvvid'
|
# video_type == 'video/vvvvid'
|
||||||
'url': 'https://www.vvvvid.it/#!show/434/perche-dovrei-guardarlo-di-dario-moccia/437/489048/ping-pong',
|
'url': 'https://www.vvvvid.it/#!show/434/perche-dovrei-guardarlo-di-dario-moccia/437/489048/ping-pong',
|
||||||
|
@ -500,6 +500,12 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
|
|
||||||
# RTMP (unnamed)
|
# RTMP (unnamed)
|
||||||
'_rtmp': {'protocol': 'rtmp'},
|
'_rtmp': {'protocol': 'rtmp'},
|
||||||
|
|
||||||
|
# av01 video only formats sometimes served with "unknown" codecs
|
||||||
|
'394': {'acodec': 'none', 'vcodec': 'av01.0.05M.08'},
|
||||||
|
'395': {'acodec': 'none', 'vcodec': 'av01.0.05M.08'},
|
||||||
|
'396': {'acodec': 'none', 'vcodec': 'av01.0.05M.08'},
|
||||||
|
'397': {'acodec': 'none', 'vcodec': 'av01.0.05M.08'},
|
||||||
}
|
}
|
||||||
_SUBTITLE_FORMATS = ('srv1', 'srv2', 'srv3', 'ttml', 'vtt')
|
_SUBTITLE_FORMATS = ('srv1', 'srv2', 'srv3', 'ttml', 'vtt')
|
||||||
|
|
||||||
@ -1306,11 +1312,18 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
|
|
||||||
def _parse_sig_js(self, jscode):
|
def _parse_sig_js(self, jscode):
|
||||||
funcname = self._search_regex(
|
funcname = self._search_regex(
|
||||||
(r'(["\'])signature\1\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
(r'\b[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
|
r'\b[a-zA-Z0-9]+\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*encodeURIComponent\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
|
r'(?P<sig>[a-zA-Z0-9$]+)\s*=\s*function\(\s*a\s*\)\s*{\s*a\s*=\s*a\.split\(\s*""\s*\)',
|
||||||
|
# Obsolete patterns
|
||||||
|
r'(["\'])signature\1\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
r'\.sig\|\|(?P<sig>[a-zA-Z0-9$]+)\(',
|
r'\.sig\|\|(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
r'yt\.akamaized\.net/\)\s*\|\|\s*.*?\s*c\s*&&\s*d\.set\([^,]+\s*,\s*(?:encodeURIComponent\s*\()?(?P<sig>[a-zA-Z0-9$]+)\(',
|
r'yt\.akamaized\.net/\)\s*\|\|\s*.*?\s*[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*(?:encodeURIComponent\s*\()?\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
r'\bc\s*&&\s*d\.set\([^,]+\s*,\s*(?:encodeURIComponent\s*\()?\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
r'\b[cs]\s*&&\s*[adf]\.set\([^,]+\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
r'\bc\s*&&\s*d\.set\([^,]+\s*,\s*\([^)]*\)\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\('),
|
r'\b[a-zA-Z0-9]+\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
|
r'\bc\s*&&\s*a\.set\([^,]+\s*,\s*\([^)]*\)\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
|
r'\bc\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*\([^)]*\)\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
|
r'\bc\s*&&\s*[a-zA-Z0-9]+\.set\([^,]+\s*,\s*\([^)]*\)\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\('),
|
||||||
jscode, 'Initial JS player signature function name', group='sig')
|
jscode, 'Initial JS player signature function name', group='sig')
|
||||||
|
|
||||||
jsi = JSInterpreter(jscode)
|
jsi = JSInterpreter(jscode)
|
||||||
@ -1575,8 +1588,15 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
return video_id
|
return video_id
|
||||||
|
|
||||||
def _extract_annotations(self, video_id):
|
def _extract_annotations(self, video_id):
|
||||||
url = 'https://www.youtube.com/annotations_invideo?features=1&legacy=1&video_id=%s' % video_id
|
return self._download_webpage(
|
||||||
return self._download_webpage(url, video_id, note='Searching for annotations.', errnote='Unable to download video annotations.')
|
'https://www.youtube.com/annotations_invideo', video_id,
|
||||||
|
note='Downloading annotations',
|
||||||
|
errnote='Unable to download video annotations', fatal=False,
|
||||||
|
query={
|
||||||
|
'features': 1,
|
||||||
|
'legacy': 1,
|
||||||
|
'video_id': video_id,
|
||||||
|
})
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _extract_chapters(description, duration):
|
def _extract_chapters(description, duration):
|
||||||
@ -2224,6 +2244,10 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
r'<[^>]+class=["\']watch-view-count[^>]+>\s*([\d,\s]+)', video_webpage,
|
r'<[^>]+class=["\']watch-view-count[^>]+>\s*([\d,\s]+)', video_webpage,
|
||||||
'view count', default=None))
|
'view count', default=None))
|
||||||
|
|
||||||
|
average_rating = (
|
||||||
|
float_or_none(video_details.get('averageRating'))
|
||||||
|
or try_get(video_info, lambda x: float_or_none(x['avg_rating'][0])))
|
||||||
|
|
||||||
# subtitles
|
# subtitles
|
||||||
video_subtitles = self.extract_subtitles(video_id, video_webpage)
|
video_subtitles = self.extract_subtitles(video_id, video_webpage)
|
||||||
automatic_captions = self.extract_automatic_captions(video_id, video_webpage)
|
automatic_captions = self.extract_automatic_captions(video_id, video_webpage)
|
||||||
@ -2353,7 +2377,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'view_count': view_count,
|
'view_count': view_count,
|
||||||
'like_count': like_count,
|
'like_count': like_count,
|
||||||
'dislike_count': dislike_count,
|
'dislike_count': dislike_count,
|
||||||
'average_rating': float_or_none(video_info.get('avg_rating', [None])[0]),
|
'average_rating': average_rating,
|
||||||
'formats': formats,
|
'formats': formats,
|
||||||
'is_live': is_live,
|
'is_live': is_live,
|
||||||
'start_time': start_time,
|
'start_time': start_time,
|
||||||
|
@ -2529,7 +2529,7 @@ def parse_codecs(codecs_str):
|
|||||||
vcodec, acodec = None, None
|
vcodec, acodec = None, None
|
||||||
for full_codec in splited_codecs:
|
for full_codec in splited_codecs:
|
||||||
codec = full_codec.split('.')[0]
|
codec = full_codec.split('.')[0]
|
||||||
if codec in ('avc1', 'avc2', 'avc3', 'avc4', 'vp9', 'vp8', 'hev1', 'hev2', 'h263', 'h264', 'mp4v', 'hvc1', 'av01'):
|
if codec in ('avc1', 'avc2', 'avc3', 'avc4', 'vp9', 'vp8', 'hev1', 'hev2', 'h263', 'h264', 'mp4v', 'hvc1', 'av01', 'theora'):
|
||||||
if not vcodec:
|
if not vcodec:
|
||||||
vcodec = full_codec
|
vcodec = full_codec
|
||||||
elif codec in ('mp4a', 'opus', 'vorbis', 'mp3', 'aac', 'ac-3', 'ec-3', 'eac3', 'dtsc', 'dtse', 'dtsh', 'dtsl'):
|
elif codec in ('mp4a', 'opus', 'vorbis', 'mp3', 'aac', 'ac-3', 'ec-3', 'eac3', 'dtsc', 'dtse', 'dtsh', 'dtsl'):
|
||||||
@ -2540,13 +2540,8 @@ def parse_codecs(codecs_str):
|
|||||||
if not vcodec and not acodec:
|
if not vcodec and not acodec:
|
||||||
if len(splited_codecs) == 2:
|
if len(splited_codecs) == 2:
|
||||||
return {
|
return {
|
||||||
'vcodec': vcodec,
|
'vcodec': splited_codecs[0],
|
||||||
'acodec': acodec,
|
'acodec': splited_codecs[1],
|
||||||
}
|
|
||||||
elif len(splited_codecs) == 1:
|
|
||||||
return {
|
|
||||||
'vcodec': 'none',
|
|
||||||
'acodec': vcodec,
|
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
return {
|
return {
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
__version__ = '2019.05.20'
|
__version__ = '2019.06.21'
|
||||||
|
Loading…
Reference in New Issue
Block a user