daum.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. import itertools
  2. import urllib.parse
  3. from .common import InfoExtractor
  4. from ..utils import parse_qs
  5. class DaumBaseIE(InfoExtractor):
  6. _KAKAO_EMBED_BASE = 'http://tv.kakao.com/embed/player/cliplink/'
  7. class DaumIE(DaumBaseIE):
  8. _VALID_URL = r'https?://(?:(?:m\.)?tvpot\.daum\.net/v/|videofarm\.daum\.net/controller/player/VodPlayer\.swf\?vid=)(?P<id>[^?#&]+)'
  9. IE_NAME = 'daum.net'
  10. _TESTS = [{
  11. 'url': 'http://tvpot.daum.net/v/vab4dyeDBysyBssyukBUjBz',
  12. 'info_dict': {
  13. 'id': 'vab4dyeDBysyBssyukBUjBz',
  14. 'ext': 'mp4',
  15. 'title': '마크 헌트 vs 안토니오 실바',
  16. 'description': 'Mark Hunt vs Antonio Silva',
  17. 'upload_date': '20131217',
  18. 'thumbnail': r're:^https?://.*\.(?:jpg|png)',
  19. 'duration': 2117,
  20. 'view_count': int,
  21. 'comment_count': int,
  22. 'uploader_id': '186139',
  23. 'uploader': '콘간지',
  24. 'timestamp': 1387310323,
  25. },
  26. }, {
  27. 'url': 'http://m.tvpot.daum.net/v/65139429',
  28. 'info_dict': {
  29. 'id': '65139429',
  30. 'ext': 'mp4',
  31. 'title': '1297회, \'아빠 아들로 태어나길 잘 했어\' 민수, 감동의 눈물[아빠 어디가] 20150118',
  32. 'description': 'md5:79794514261164ff27e36a21ad229fc5',
  33. 'upload_date': '20150118',
  34. 'thumbnail': r're:^https?://.*\.(?:jpg|png)',
  35. 'duration': 154,
  36. 'view_count': int,
  37. 'comment_count': int,
  38. 'uploader': 'MBC 예능',
  39. 'uploader_id': '132251',
  40. 'timestamp': 1421604228,
  41. },
  42. }, {
  43. 'url': 'http://tvpot.daum.net/v/07dXWRka62Y%24',
  44. 'only_matching': True,
  45. }, {
  46. 'url': 'http://videofarm.daum.net/controller/player/VodPlayer.swf?vid=vwIpVpCQsT8%24&ref=',
  47. 'info_dict': {
  48. 'id': 'vwIpVpCQsT8$',
  49. 'ext': 'flv',
  50. 'title': '01-Korean War ( Trouble on the horizon )',
  51. 'description': 'Korean War 01\r\nTrouble on the horizon\r\n전쟁의 먹구름',
  52. 'upload_date': '20080223',
  53. 'thumbnail': r're:^https?://.*\.(?:jpg|png)',
  54. 'duration': 249,
  55. 'view_count': int,
  56. 'comment_count': int,
  57. 'uploader': '까칠한 墮落始祖 황비홍님의',
  58. 'uploader_id': '560824',
  59. 'timestamp': 1203770745,
  60. },
  61. }, {
  62. # Requires dte_type=WEB (#9972)
  63. 'url': 'http://tvpot.daum.net/v/s3794Uf1NZeZ1qMpGpeqeRU',
  64. 'md5': 'a8917742069a4dd442516b86e7d66529',
  65. 'info_dict': {
  66. 'id': 's3794Uf1NZeZ1qMpGpeqeRU',
  67. 'ext': 'mp4',
  68. 'title': '러블리즈 - Destiny (나의 지구) (Lovelyz - Destiny)',
  69. 'description': '러블리즈 - Destiny (나의 지구) (Lovelyz - Destiny)\r\n\r\n[쇼! 음악중심] 20160611, 507회',
  70. 'upload_date': '20170129',
  71. 'uploader': '쇼! 음악중심',
  72. 'uploader_id': '2653210',
  73. 'timestamp': 1485684628,
  74. },
  75. }]
  76. def _real_extract(self, url):
  77. video_id = urllib.parse.unquote(self._match_id(url))
  78. if not video_id.isdigit():
  79. video_id += '@my'
  80. return self.url_result(
  81. self._KAKAO_EMBED_BASE + video_id, 'Kakao', video_id)
  82. class DaumClipIE(DaumBaseIE):
  83. _VALID_URL = r'https?://(?:m\.)?tvpot\.daum\.net/(?:clip/ClipView.(?:do|tv)|mypot/View.do)\?.*?clipid=(?P<id>\d+)'
  84. IE_NAME = 'daum.net:clip'
  85. _URL_TEMPLATE = 'http://tvpot.daum.net/clip/ClipView.do?clipid=%s'
  86. _TESTS = [{
  87. 'url': 'http://tvpot.daum.net/clip/ClipView.do?clipid=52554690',
  88. 'info_dict': {
  89. 'id': '52554690',
  90. 'ext': 'mp4',
  91. 'title': 'DOTA 2GETHER 시즌2 6회 - 2부',
  92. 'description': 'DOTA 2GETHER 시즌2 6회 - 2부',
  93. 'upload_date': '20130831',
  94. 'thumbnail': r're:^https?://.*\.(?:jpg|png)',
  95. 'duration': 3868,
  96. 'view_count': int,
  97. 'uploader': 'GOMeXP',
  98. 'uploader_id': '6667',
  99. 'timestamp': 1377911092,
  100. },
  101. }, {
  102. 'url': 'http://m.tvpot.daum.net/clip/ClipView.tv?clipid=54999425',
  103. 'only_matching': True,
  104. }]
  105. @classmethod
  106. def suitable(cls, url):
  107. return False if DaumPlaylistIE.suitable(url) or DaumUserIE.suitable(url) else super().suitable(url)
  108. def _real_extract(self, url):
  109. video_id = self._match_id(url)
  110. return self.url_result(
  111. self._KAKAO_EMBED_BASE + video_id, 'Kakao', video_id)
  112. class DaumListIE(InfoExtractor): # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor
  113. def _get_entries(self, list_id, list_id_type):
  114. name = None
  115. entries = []
  116. for pagenum in itertools.count(1):
  117. list_info = self._download_json(
  118. f'http://tvpot.daum.net/mypot/json/GetClipInfo.do?size=48&init=true&order=date&page={pagenum}&{list_id_type}={list_id}',
  119. list_id, f'Downloading list info - {pagenum}')
  120. entries.extend([
  121. self.url_result(
  122. 'http://tvpot.daum.net/v/{}'.format(clip['vid']))
  123. for clip in list_info['clip_list']
  124. ])
  125. if not name:
  126. name = list_info.get('playlist_bean', {}).get('name') or \
  127. list_info.get('potInfo', {}).get('name')
  128. if not list_info.get('has_more'):
  129. break
  130. return name, entries
  131. def _check_clip(self, url, list_id):
  132. query_dict = parse_qs(url)
  133. if 'clipid' in query_dict:
  134. clip_id = query_dict['clipid'][0]
  135. if not self._yes_playlist(list_id, clip_id):
  136. return self.url_result(DaumClipIE._URL_TEMPLATE % clip_id, 'DaumClip')
  137. class DaumPlaylistIE(DaumListIE):
  138. _VALID_URL = r'https?://(?:m\.)?tvpot\.daum\.net/mypot/(?:View\.do|Top\.tv)\?.*?playlistid=(?P<id>[0-9]+)'
  139. IE_NAME = 'daum.net:playlist'
  140. _URL_TEMPLATE = 'http://tvpot.daum.net/mypot/View.do?playlistid=%s'
  141. _TESTS = [{
  142. 'note': 'Playlist url with clipid',
  143. 'url': 'http://tvpot.daum.net/mypot/View.do?playlistid=6213966&clipid=73806844',
  144. 'info_dict': {
  145. 'id': '6213966',
  146. 'title': 'Woorissica Official',
  147. },
  148. 'playlist_mincount': 181,
  149. }, {
  150. 'note': 'Playlist url with clipid - noplaylist',
  151. 'url': 'http://tvpot.daum.net/mypot/View.do?playlistid=6213966&clipid=73806844',
  152. 'info_dict': {
  153. 'id': '73806844',
  154. 'ext': 'mp4',
  155. 'title': '151017 Airport',
  156. 'upload_date': '20160117',
  157. },
  158. 'params': {
  159. 'noplaylist': True,
  160. 'skip_download': True,
  161. },
  162. }]
  163. @classmethod
  164. def suitable(cls, url):
  165. return False if DaumUserIE.suitable(url) else super().suitable(url)
  166. def _real_extract(self, url):
  167. list_id = self._match_id(url)
  168. clip_result = self._check_clip(url, list_id)
  169. if clip_result:
  170. return clip_result
  171. name, entries = self._get_entries(list_id, 'playlistid')
  172. return self.playlist_result(entries, list_id, name)
  173. class DaumUserIE(DaumListIE):
  174. _VALID_URL = r'https?://(?:m\.)?tvpot\.daum\.net/mypot/(?:View|Top)\.(?:do|tv)\?.*?ownerid=(?P<id>[0-9a-zA-Z]+)'
  175. IE_NAME = 'daum.net:user'
  176. _TESTS = [{
  177. 'url': 'http://tvpot.daum.net/mypot/View.do?ownerid=o2scDLIVbHc0',
  178. 'info_dict': {
  179. 'id': 'o2scDLIVbHc0',
  180. 'title': '마이 리틀 텔레비전',
  181. },
  182. 'playlist_mincount': 213,
  183. }, {
  184. 'url': 'http://tvpot.daum.net/mypot/View.do?ownerid=o2scDLIVbHc0&clipid=73801156',
  185. 'info_dict': {
  186. 'id': '73801156',
  187. 'ext': 'mp4',
  188. 'title': '[미공개] 김구라, 오만석이 부릅니다 \'오케피\' - 마이 리틀 텔레비전 20160116',
  189. 'upload_date': '20160117',
  190. 'description': 'md5:5e91d2d6747f53575badd24bd62b9f36',
  191. },
  192. 'params': {
  193. 'noplaylist': True,
  194. 'skip_download': True,
  195. },
  196. }, {
  197. 'note': 'Playlist url has ownerid and playlistid, playlistid takes precedence',
  198. 'url': 'http://tvpot.daum.net/mypot/View.do?ownerid=o2scDLIVbHc0&playlistid=6196631',
  199. 'info_dict': {
  200. 'id': '6196631',
  201. 'title': '마이 리틀 텔레비전 - 20160109',
  202. },
  203. 'playlist_count': 11,
  204. }, {
  205. 'url': 'http://tvpot.daum.net/mypot/Top.do?ownerid=o2scDLIVbHc0',
  206. 'only_matching': True,
  207. }, {
  208. 'url': 'http://m.tvpot.daum.net/mypot/Top.tv?ownerid=45x1okb1If50&playlistid=3569733',
  209. 'only_matching': True,
  210. }]
  211. def _real_extract(self, url):
  212. list_id = self._match_id(url)
  213. clip_result = self._check_clip(url, list_id)
  214. if clip_result:
  215. return clip_result
  216. query_dict = parse_qs(url)
  217. if 'playlistid' in query_dict:
  218. playlist_id = query_dict['playlistid'][0]
  219. return self.url_result(DaumPlaylistIE._URL_TEMPLATE % playlist_id, 'DaumPlaylist')
  220. name, entries = self._get_entries(list_id, 'ownerid')
  221. return self.playlist_result(entries, list_id, name)