You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
5.1 KiB

  1. # coding: utf-8
  2. from __future__ import unicode_literals
  3. import re
  4. from .common import InfoExtractor
  5. from ..compat import (
  6. compat_urllib_parse_urlencode,
  7. compat_urlparse,
  8. )
  9. from ..utils import (
  10. ExtractorError,
  11. sanitized_Request,
  12. unified_strdate,
  13. urlencode_postdata,
  14. xpath_element,
  15. xpath_text,
  16. )
  17. class Laola1TvIE(InfoExtractor):
  18. _VALID_URL = r'https?://(?:www\.)?laola1\.tv/(?P<lang>[a-z]+)-(?P<portal>[a-z]+)/(?P<kind>[^/]+)/(?P<slug>[^/?#&]+)'
  19. _TESTS = [{
  20. 'url': 'http://www.laola1.tv/de-de/video/straubing-tigers-koelner-haie/227883.html',
  21. 'info_dict': {
  22. 'id': '227883',
  23. 'display_id': 'straubing-tigers-koelner-haie',
  24. 'ext': 'flv',
  25. 'title': 'Straubing Tigers - Kölner Haie',
  26. 'upload_date': '20140912',
  27. 'is_live': False,
  28. 'categories': ['Eishockey'],
  29. },
  30. 'params': {
  31. 'skip_download': True,
  32. },
  33. }, {
  34. 'url': 'http://www.laola1.tv/de-de/video/straubing-tigers-koelner-haie',
  35. 'info_dict': {
  36. 'id': '464602',
  37. 'display_id': 'straubing-tigers-koelner-haie',
  38. 'ext': 'flv',
  39. 'title': 'Straubing Tigers - Kölner Haie',
  40. 'upload_date': '20160129',
  41. 'is_live': False,
  42. 'categories': ['Eishockey'],
  43. },
  44. 'params': {
  45. 'skip_download': True,
  46. },
  47. }, {
  48. 'url': 'http://www.laola1.tv/de-de/livestream/2016-03-22-belogorie-belgorod-trentino-diatec-lde',
  49. 'info_dict': {
  50. 'id': '487850',
  51. 'display_id': '2016-03-22-belogorie-belgorod-trentino-diatec-lde',
  52. 'ext': 'flv',
  53. 'title': 'Belogorie BELGOROD - TRENTINO Diatec',
  54. 'upload_date': '20160322',
  55. 'uploader': 'CEV - Europäischer Volleyball Verband',
  56. 'is_live': True,
  57. 'categories': ['Volleyball'],
  58. },
  59. 'params': {
  60. 'skip_download': True,
  61. },
  62. 'skip': 'This live stream has already finished.',
  63. }]
  64. def _real_extract(self, url):
  65. mobj = re.match(self._VALID_URL, url)
  66. display_id = mobj.group('slug')
  67. kind = mobj.group('kind')
  68. lang = mobj.group('lang')
  69. portal = mobj.group('portal')
  70. webpage = self._download_webpage(url, display_id)
  71. if 'Dieser Livestream ist bereits beendet.' in webpage:
  72. raise ExtractorError('This live stream has already finished.', expected=True)
  73. iframe_url = self._search_regex(
  74. r'<iframe[^>]*?id="videoplayer"[^>]*?src="([^"]+)"',
  75. webpage, 'iframe url')
  76. video_id = self._search_regex(
  77. r'videoid=(\d+)', iframe_url, 'video id')
  78. iframe = self._download_webpage(compat_urlparse.urljoin(
  79. url, iframe_url), display_id, 'Downloading iframe')
  80. partner_id = self._search_regex(
  81. r'partnerid\s*:\s*(["\'])(?P<partner_id>.+?)\1',
  82. iframe, 'partner id', group='partner_id')
  83. hd_doc = self._download_xml(
  84. 'http://www.laola1.tv/server/hd_video.php?%s'
  85. % compat_urllib_parse_urlencode({
  86. 'play': video_id,
  87. 'partner': partner_id,
  88. 'portal': portal,
  89. 'lang': lang,
  90. 'v5ident': '',
  91. }), display_id)
  92. _v = lambda x, **k: xpath_text(hd_doc, './/video/' + x, **k)
  93. title = _v('title', fatal=True)
  94. VS_TARGETS = {
  95. 'video': '2',
  96. 'livestream': '17',
  97. }
  98. req = sanitized_Request(
  99. 'https://club.laola1.tv/sp/laola1/api/v3/user/session/premium/player/stream-access?%s' %
  100. compat_urllib_parse_urlencode({
  101. 'videoId': video_id,
  102. 'target': VS_TARGETS.get(kind, '2'),
  103. 'label': _v('label'),
  104. 'area': _v('area'),
  105. }),
  106. urlencode_postdata(
  107. dict((i, v) for i, v in enumerate(_v('req_liga_abos').split(',')))))
  108. token_url = self._download_json(req, display_id)['data']['stream-access'][0]
  109. token_doc = self._download_xml(token_url, display_id, 'Downloading token')
  110. token_attrib = xpath_element(token_doc, './/token').attrib
  111. token_auth = token_attrib['auth']
  112. if token_auth in ('blocked', 'restricted', 'error'):
  113. raise ExtractorError(
  114. 'Token error: %s' % token_attrib['comment'], expected=True)
  115. formats = self._extract_f4m_formats(
  116. '%s?hdnea=%s&hdcore=3.2.0' % (token_attrib['url'], token_auth),
  117. video_id, f4m_id='hds')
  118. self._sort_formats(formats)
  119. categories_str = _v('meta_sports')
  120. categories = categories_str.split(',') if categories_str else []
  121. return {
  122. 'id': video_id,
  123. 'display_id': display_id,
  124. 'title': title,
  125. 'upload_date': unified_strdate(_v('time_date')),
  126. 'uploader': _v('meta_organisation'),
  127. 'categories': categories,
  128. 'is_live': _v('islive') == 'true',
  129. 'formats': formats,
  130. }