daum.py 9.2 KB

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