mirror of
https://github.com/yt-dlp/yt-dlp
synced 2024-12-26 21:59:08 +01:00
[ie/learningonscreen] Add extractor (#10590)
Some checks failed
CodeQL / Analyze (python) (push) Waiting to run
Download Tests / Quick Download Tests (push) Waiting to run
Download Tests / Full Download Tests (ubuntu-latest, 3.10) (push) Waiting to run
Download Tests / Full Download Tests (ubuntu-latest, 3.11) (push) Waiting to run
Download Tests / Full Download Tests (ubuntu-latest, 3.12) (push) Waiting to run
Download Tests / Full Download Tests (ubuntu-latest, pypy-3.10) (push) Waiting to run
Download Tests / Full Download Tests (ubuntu-latest, pypy-3.8) (push) Waiting to run
Download Tests / Full Download Tests (windows-latest, 3.8) (push) Waiting to run
Download Tests / Full Download Tests (windows-latest, pypy-3.9) (push) Waiting to run
Quick Test / Core Test (push) Waiting to run
Quick Test / Code check (push) Waiting to run
Release (master) / release (push) Waiting to run
Core Tests / Core Tests (ubuntu-latest, 3.10) (push) Has been cancelled
Core Tests / Core Tests (ubuntu-latest, 3.11) (push) Has been cancelled
Core Tests / Core Tests (ubuntu-latest, 3.12) (push) Has been cancelled
Core Tests / Core Tests (ubuntu-latest, 3.9) (push) Has been cancelled
Core Tests / Core Tests (ubuntu-latest, pypy-3.10) (push) Has been cancelled
Core Tests / Core Tests (ubuntu-latest, pypy-3.8) (push) Has been cancelled
Core Tests / Core Tests (windows-latest, 3.12) (push) Has been cancelled
Core Tests / Core Tests (windows-latest, 3.8) (push) Has been cancelled
Core Tests / Core Tests (windows-latest, pypy-3.9) (push) Has been cancelled
Some checks failed
CodeQL / Analyze (python) (push) Waiting to run
Download Tests / Quick Download Tests (push) Waiting to run
Download Tests / Full Download Tests (ubuntu-latest, 3.10) (push) Waiting to run
Download Tests / Full Download Tests (ubuntu-latest, 3.11) (push) Waiting to run
Download Tests / Full Download Tests (ubuntu-latest, 3.12) (push) Waiting to run
Download Tests / Full Download Tests (ubuntu-latest, pypy-3.10) (push) Waiting to run
Download Tests / Full Download Tests (ubuntu-latest, pypy-3.8) (push) Waiting to run
Download Tests / Full Download Tests (windows-latest, 3.8) (push) Waiting to run
Download Tests / Full Download Tests (windows-latest, pypy-3.9) (push) Waiting to run
Quick Test / Core Test (push) Waiting to run
Quick Test / Code check (push) Waiting to run
Release (master) / release (push) Waiting to run
Core Tests / Core Tests (ubuntu-latest, 3.10) (push) Has been cancelled
Core Tests / Core Tests (ubuntu-latest, 3.11) (push) Has been cancelled
Core Tests / Core Tests (ubuntu-latest, 3.12) (push) Has been cancelled
Core Tests / Core Tests (ubuntu-latest, 3.9) (push) Has been cancelled
Core Tests / Core Tests (ubuntu-latest, pypy-3.10) (push) Has been cancelled
Core Tests / Core Tests (ubuntu-latest, pypy-3.8) (push) Has been cancelled
Core Tests / Core Tests (windows-latest, 3.12) (push) Has been cancelled
Core Tests / Core Tests (windows-latest, 3.8) (push) Has been cancelled
Core Tests / Core Tests (windows-latest, pypy-3.9) (push) Has been cancelled
Authored by: bashonly, Grub4K Co-authored-by: Simon Sawicki <contact@grub4k.xyz>
This commit is contained in:
parent
94a1c5e642
commit
fe15d3178e
3 changed files with 84 additions and 3 deletions
|
@ -986,6 +986,7 @@ from .lcp import (
|
||||||
LcpIE,
|
LcpIE,
|
||||||
LcpPlayIE,
|
LcpPlayIE,
|
||||||
)
|
)
|
||||||
|
from .learningonscreen import LearningOnScreenIE
|
||||||
from .lecture2go import Lecture2GoIE
|
from .lecture2go import Lecture2GoIE
|
||||||
from .lecturio import (
|
from .lecturio import (
|
||||||
LecturioCourseIE,
|
LecturioCourseIE,
|
||||||
|
|
|
@ -3150,7 +3150,7 @@ class InfoExtractor:
|
||||||
})
|
})
|
||||||
return formats, subtitles
|
return formats, subtitles
|
||||||
|
|
||||||
def _parse_html5_media_entries(self, base_url, webpage, video_id, m3u8_id=None, m3u8_entry_protocol='m3u8_native', mpd_id=None, preference=None, quality=None):
|
def _parse_html5_media_entries(self, base_url, webpage, video_id, m3u8_id=None, m3u8_entry_protocol='m3u8_native', mpd_id=None, preference=None, quality=None, _headers=None):
|
||||||
def absolute_url(item_url):
|
def absolute_url(item_url):
|
||||||
return urljoin(base_url, item_url)
|
return urljoin(base_url, item_url)
|
||||||
|
|
||||||
|
@ -3174,11 +3174,11 @@ class InfoExtractor:
|
||||||
formats = self._extract_m3u8_formats(
|
formats = self._extract_m3u8_formats(
|
||||||
full_url, video_id, ext='mp4',
|
full_url, video_id, ext='mp4',
|
||||||
entry_protocol=m3u8_entry_protocol, m3u8_id=m3u8_id,
|
entry_protocol=m3u8_entry_protocol, m3u8_id=m3u8_id,
|
||||||
preference=preference, quality=quality, fatal=False)
|
preference=preference, quality=quality, fatal=False, headers=_headers)
|
||||||
elif ext == 'mpd':
|
elif ext == 'mpd':
|
||||||
is_plain_url = False
|
is_plain_url = False
|
||||||
formats = self._extract_mpd_formats(
|
formats = self._extract_mpd_formats(
|
||||||
full_url, video_id, mpd_id=mpd_id, fatal=False)
|
full_url, video_id, mpd_id=mpd_id, fatal=False, headers=_headers)
|
||||||
else:
|
else:
|
||||||
is_plain_url = True
|
is_plain_url = True
|
||||||
formats = [{
|
formats = [{
|
||||||
|
@ -3272,6 +3272,8 @@ class InfoExtractor:
|
||||||
})
|
})
|
||||||
for f in media_info['formats']:
|
for f in media_info['formats']:
|
||||||
f.setdefault('http_headers', {})['Referer'] = base_url
|
f.setdefault('http_headers', {})['Referer'] = base_url
|
||||||
|
if _headers:
|
||||||
|
f['http_headers'].update(_headers)
|
||||||
if media_info['formats'] or media_info['subtitles']:
|
if media_info['formats'] or media_info['subtitles']:
|
||||||
entries.append(media_info)
|
entries.append(media_info)
|
||||||
return entries
|
return entries
|
||||||
|
|
78
yt_dlp/extractor/learningonscreen.py
Normal file
78
yt_dlp/extractor/learningonscreen.py
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import functools
|
||||||
|
import re
|
||||||
|
|
||||||
|
from .common import InfoExtractor
|
||||||
|
from ..utils import (
|
||||||
|
ExtractorError,
|
||||||
|
clean_html,
|
||||||
|
extract_attributes,
|
||||||
|
get_element_by_class,
|
||||||
|
get_element_html_by_id,
|
||||||
|
join_nonempty,
|
||||||
|
parse_duration,
|
||||||
|
unified_timestamp,
|
||||||
|
)
|
||||||
|
from ..utils.traversal import traverse_obj
|
||||||
|
|
||||||
|
|
||||||
|
class LearningOnScreenIE(InfoExtractor):
|
||||||
|
_VALID_URL = r'https?://learningonscreen\.ac\.uk/ondemand/index\.php/prog/(?P<id>\w+)'
|
||||||
|
_TESTS = [{
|
||||||
|
'url': 'https://learningonscreen.ac.uk/ondemand/index.php/prog/005D81B2?bcast=22757013',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '005D81B2',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'Planet Earth',
|
||||||
|
'duration': 3600.0,
|
||||||
|
'timestamp': 1164567600.0,
|
||||||
|
'upload_date': '20061126',
|
||||||
|
'thumbnail': 'https://stream.learningonscreen.ac.uk/trilt-cover-images/005D81B2-Planet-Earth-2006-11-26T190000Z-BBC4.jpg',
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
|
||||||
|
def _real_initialize(self):
|
||||||
|
if not self._get_cookies('https://learningonscreen.ac.uk/').get('PHPSESSID-BOB-LIVE'):
|
||||||
|
self.raise_login_required(
|
||||||
|
'Use --cookies for authentication. See '
|
||||||
|
' https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp '
|
||||||
|
'for how to manually pass cookies', method=None)
|
||||||
|
|
||||||
|
def _real_extract(self, url):
|
||||||
|
video_id = self._match_id(url)
|
||||||
|
webpage = self._download_webpage(url, video_id)
|
||||||
|
|
||||||
|
details = traverse_obj(webpage, (
|
||||||
|
{functools.partial(get_element_html_by_id, 'programme-details')}, {
|
||||||
|
'title': ({functools.partial(re.search, r'<h2>([^<]+)</h2>')}, 1, {clean_html}),
|
||||||
|
'timestamp': (
|
||||||
|
{functools.partial(get_element_by_class, 'broadcast-date')},
|
||||||
|
{functools.partial(re.match, r'([^<]+)')}, 1, {unified_timestamp}),
|
||||||
|
'duration': (
|
||||||
|
{functools.partial(get_element_by_class, 'prog-running-time')},
|
||||||
|
{clean_html}, {parse_duration}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
title = details.pop('title', None) or traverse_obj(webpage, (
|
||||||
|
{functools.partial(get_element_html_by_id, 'add-to-existing-playlist')},
|
||||||
|
{extract_attributes}, 'data-record-title', {clean_html}))
|
||||||
|
|
||||||
|
entries = self._parse_html5_media_entries(
|
||||||
|
'https://stream.learningonscreen.ac.uk', webpage, video_id, m3u8_id='hls', mpd_id='dash',
|
||||||
|
_headers={'Origin': 'https://learningonscreen.ac.uk', 'Referer': 'https://learningonscreen.ac.uk/'})
|
||||||
|
if not entries:
|
||||||
|
raise ExtractorError('No video found')
|
||||||
|
|
||||||
|
if len(entries) > 1:
|
||||||
|
duration = details.pop('duration', None)
|
||||||
|
for idx, entry in enumerate(entries, start=1):
|
||||||
|
entry.update(details)
|
||||||
|
entry['id'] = join_nonempty(video_id, idx)
|
||||||
|
entry['title'] = join_nonempty(title, idx)
|
||||||
|
return self.playlist_result(entries, video_id, title, duration=duration)
|
||||||
|
|
||||||
|
return {
|
||||||
|
**entries[0],
|
||||||
|
**details,
|
||||||
|
'id': video_id,
|
||||||
|
'title': title,
|
||||||
|
}
|
Loading…
Reference in a new issue