medialaan.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import re
  2. from .common import InfoExtractor
  3. from ..utils import (
  4. extract_attributes,
  5. int_or_none,
  6. mimetype2ext,
  7. parse_iso8601,
  8. )
  9. class MedialaanIE(InfoExtractor):
  10. _VALID_URL = r'''(?x)
  11. https?://
  12. (?:
  13. (?:embed\.)?mychannels.video/embed/|
  14. embed\.mychannels\.video/(?:s(?:dk|cript)/)?production/|
  15. (?:www\.)?(?:
  16. (?:
  17. 7sur7|
  18. demorgen|
  19. hln|
  20. joe|
  21. qmusic
  22. )\.be|
  23. (?:
  24. [abe]d|
  25. bndestem|
  26. destentor|
  27. gelderlander|
  28. pzc|
  29. tubantia|
  30. volkskrant
  31. )\.nl
  32. )/video/(?:[^/]+/)*[^/?&#]+~p
  33. )
  34. (?P<id>\d+)
  35. '''
  36. _TESTS = [{
  37. 'url': 'https://www.bndestem.nl/video/de-terugkeer-van-ally-de-aap-en-wie-vertrekt-er-nog-bij-nac~p193993',
  38. 'info_dict': {
  39. 'id': '193993',
  40. 'ext': 'mp4',
  41. 'title': 'De terugkeer van Ally de Aap en wie vertrekt er nog bij NAC?',
  42. 'timestamp': 1611663540,
  43. 'upload_date': '20210126',
  44. 'duration': 238,
  45. },
  46. 'params': {
  47. 'skip_download': True,
  48. },
  49. }, {
  50. 'url': 'https://www.gelderlander.nl/video/kanalen/degelderlander~c320/series/snel-nieuws~s984/noodbevel-in-doetinchem-politie-stuurt-mensen-centrum-uit~p194093',
  51. 'only_matching': True,
  52. }, {
  53. 'url': 'https://embed.mychannels.video/sdk/production/193993?options=TFTFF_default',
  54. 'only_matching': True,
  55. }, {
  56. 'url': 'https://embed.mychannels.video/script/production/193993',
  57. 'only_matching': True,
  58. }, {
  59. 'url': 'https://embed.mychannels.video/production/193993',
  60. 'only_matching': True,
  61. }, {
  62. 'url': 'https://mychannels.video/embed/193993',
  63. 'only_matching': True,
  64. }, {
  65. 'url': 'https://embed.mychannels.video/embed/193993',
  66. 'only_matching': True,
  67. }]
  68. @classmethod
  69. def _extract_embed_urls(cls, url, webpage):
  70. entries = []
  71. for element in re.findall(r'(<div[^>]+data-mychannels-type="video"[^>]*>)', webpage):
  72. mychannels_id = extract_attributes(element).get('data-mychannels-id')
  73. if mychannels_id:
  74. entries.append('https://mychannels.video/embed/' + mychannels_id)
  75. return entries
  76. def _real_extract(self, url):
  77. production_id = self._match_id(url)
  78. production = self._download_json(
  79. 'https://embed.mychannels.video/sdk/production/' + production_id,
  80. production_id, query={'options': 'UUUU_default'})['productions'][0]
  81. title = production['title']
  82. formats = []
  83. for source in (production.get('sources') or []):
  84. src = source.get('src')
  85. if not src:
  86. continue
  87. ext = mimetype2ext(source.get('type'))
  88. if ext == 'm3u8':
  89. formats.extend(self._extract_m3u8_formats(
  90. src, production_id, 'mp4', 'm3u8_native',
  91. m3u8_id='hls', fatal=False))
  92. else:
  93. formats.append({
  94. 'ext': ext,
  95. 'url': src,
  96. })
  97. return {
  98. 'id': production_id,
  99. 'title': title,
  100. 'formats': formats,
  101. 'thumbnail': production.get('posterUrl'),
  102. 'timestamp': parse_iso8601(production.get('publicationDate'), ' '),
  103. 'duration': int_or_none(production.get('duration')) or None,
  104. }