kakao.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. # coding: utf-8
  2. from __future__ import unicode_literals
  3. from .common import InfoExtractor
  4. from ..utils import (
  5. int_or_none,
  6. compat_str,
  7. unified_timestamp,
  8. )
  9. class KakaoIE(InfoExtractor):
  10. _VALID_URL = r'https?://tv.kakao.com/channel/(?P<channel>\d+)/cliplink/(?P<id>\d+)'
  11. IE_NAME = 'kakao.com'
  12. _TESTS = [{
  13. 'url': 'http://tv.kakao.com/channel/2671005/cliplink/301965083',
  14. 'md5': '702b2fbdeb51ad82f5c904e8c0766340',
  15. 'info_dict': {
  16. 'id': '301965083',
  17. 'ext': 'mp4',
  18. 'title': '乃木坂46 バナナマン 「3期生紹介コーナーが始動!顔高低差GPも!」 『乃木坂工事中』',
  19. 'uploader_id': 2671005,
  20. 'uploader': '그랑그랑이',
  21. 'timestamp': 1488160199,
  22. 'upload_date': '20170227',
  23. }
  24. }, {
  25. 'url': 'http://tv.kakao.com/channel/2653210/cliplink/300103180',
  26. 'md5': 'a8917742069a4dd442516b86e7d66529',
  27. 'info_dict': {
  28. 'id': '300103180',
  29. 'ext': 'mp4',
  30. 'description': '러블리즈 - Destiny (나의 지구) (Lovelyz - Destiny)\r\n\r\n[쇼! 음악중심] 20160611, 507회',
  31. 'title': '러블리즈 - Destiny (나의 지구) (Lovelyz - Destiny)',
  32. 'uploader_id': 2653210,
  33. 'uploader': '쇼 음악중심',
  34. 'timestamp': 1485684628,
  35. 'upload_date': '20170129',
  36. }
  37. }]
  38. def _real_extract(self, url):
  39. video_id = self._match_id(url)
  40. player_url = 'http://tv.kakao.com/embed/player/cliplink/' + video_id + \
  41. '?service=kakao_tv&autoplay=1&profile=HIGH&wmode=transparent'
  42. player_header = {'Referer': player_url}
  43. impress = self._download_json(
  44. 'http://tv.kakao.com/api/v1/ft/cliplinks/%s/impress' % video_id,
  45. video_id, 'Downloading video info',
  46. query={
  47. 'player': 'monet_html5',
  48. 'referer': url,
  49. 'uuid': '',
  50. 'service': 'kakao_tv',
  51. 'section': '',
  52. 'dteType': 'PC',
  53. 'fields': 'clipLink,clip,channel,hasPlusFriend,-service,-tagList'
  54. }, headers=player_header)
  55. clipLink = impress['clipLink']
  56. clip = clipLink['clip']
  57. video_info = {
  58. 'id': video_id,
  59. 'title': clip['title'],
  60. 'description': clip.get('description'),
  61. 'uploader': clipLink.get('channel', {}).get('name'),
  62. 'uploader_id': clipLink.get('channelId'),
  63. 'duration': int_or_none(clip.get('duration')),
  64. 'view_count': int_or_none(clip.get('playCount')),
  65. 'like_count': int_or_none(clip.get('likeCount')),
  66. 'comment_count': int_or_none(clip.get('commentCount')),
  67. }
  68. tid = impress.get('tid', '')
  69. raw = self._download_json(
  70. 'http://tv.kakao.com/api/v1/ft/cliplinks/%s/raw' % video_id,
  71. video_id, 'Downloading video formats info',
  72. query={
  73. 'player': 'monet_html5',
  74. 'referer': url,
  75. 'uuid': '',
  76. 'service': 'kakao_tv',
  77. 'section': '',
  78. 'tid': tid,
  79. 'profile': 'HIGH',
  80. 'dteType': 'PC',
  81. }, headers=player_header, fatal=False)
  82. formats = []
  83. for fmt in raw.get('outputList', []):
  84. try:
  85. profile_name = fmt['profile']
  86. fmt_url_json = self._download_json(
  87. 'http://tv.kakao.com/api/v1/ft/cliplinks/%s/raw/videolocation' % video_id,
  88. video_id, 'Downloading video URL for profile %s' % profile_name,
  89. query={
  90. 'service': 'kakao_tv',
  91. 'section': '',
  92. 'tid': tid,
  93. 'profile': profile_name
  94. }, headers=player_header, fatal=False)
  95. if fmt_url_json is None:
  96. continue
  97. fmt_url = fmt_url_json['url']
  98. formats.append({
  99. 'url': fmt_url,
  100. 'format_id': profile_name,
  101. 'width': int_or_none(fmt.get('width')),
  102. 'height': int_or_none(fmt.get('height')),
  103. 'format_note': fmt.get('label'),
  104. 'filesize': int_or_none(fmt.get('filesize'))
  105. })
  106. except KeyError:
  107. pass
  108. self._sort_formats(formats)
  109. video_info['formats'] = formats
  110. top_thumbnail = clip.get('thumbnailUrl')
  111. thumbs = []
  112. for thumb in clip.get('clipChapterThumbnailList', []):
  113. thumbs.append({
  114. 'url': thumb.get('thumbnailUrl'),
  115. 'id': compat_str(thumb.get('timeInSec')),
  116. 'preference': -1 if thumb.get('isDefault') else 0
  117. })
  118. video_info['thumbnail'] = top_thumbnail
  119. video_info['thumbnails'] = thumbs
  120. upload_date = unified_timestamp(clipLink.get('createTime'))
  121. video_info['timestamp'] = upload_date
  122. return video_info