]>
Commit | Line | Data |
---|---|---|
abc07b55 AG |
1 | # coding: utf-8 |
2 | from __future__ import unicode_literals | |
3 | ||
4 | import itertools | |
5 | ||
6 | from .common import InfoExtractor | |
7 | from ..utils import ( | |
8 | int_or_none, | |
9 | str_or_none, | |
10 | traverse_obj, | |
11 | unified_strdate, | |
12 | ) | |
13 | ||
14 | ||
15 | class NateIE(InfoExtractor): | |
16 | _VALID_URL = r'https?://tv\.nate\.com/clip/(?P<id>[0-9]+)' | |
17 | ||
18 | _TESTS = [{ | |
19 | 'url': 'https://tv.nate.com/clip/1848976', | |
20 | 'info_dict': { | |
21 | 'id': '1848976', | |
22 | 'ext': 'mp4', | |
23 | 'title': '[결승 오프닝 타이틀] 2018 LCK 서머 스플릿 결승전 kt Rolster VS Griffin', | |
24 | 'description': 'md5:e1b79a7dcf0d8d586443f11366f50e6f', | |
25 | 'thumbnail': r're:^https?://.*\.jpg', | |
26 | 'upload_date': '20180908', | |
27 | 'age_limit': 15, | |
28 | 'duration': 73, | |
29 | 'uploader': '2018 LCK 서머 스플릿(롤챔스)', | |
30 | 'channel': '2018 LCK 서머 스플릿(롤챔스)', | |
31 | 'channel_id': '3606', | |
32 | 'uploader_id': '3606', | |
33 | 'tags': 'count:59', | |
34 | }, | |
35 | 'params': {'skip_download': True} | |
36 | }, { | |
37 | 'url': 'https://tv.nate.com/clip/4300566', | |
38 | 'info_dict': { | |
39 | 'id': '4300566', | |
40 | 'ext': 'mp4', | |
41 | 'title': '[심쿵엔딩] 이준호x이세영, 서로를 기억하며 끌어안는 두 사람!💕, MBC 211204 방송', | |
42 | 'description': 'md5:be1653502d9c13ce344ddf7828e089fa', | |
43 | 'thumbnail': r're:^https?://.*\.jpg', | |
44 | 'upload_date': '20211204', | |
45 | 'age_limit': 15, | |
46 | 'duration': 201, | |
47 | 'uploader': '옷소매 붉은 끝동', | |
48 | 'channel': '옷소매 붉은 끝동', | |
49 | 'channel_id': '27987', | |
50 | 'uploader_id': '27987', | |
51 | 'tags': 'count:20', | |
52 | }, | |
53 | 'params': {'skip_download': True} | |
54 | }] | |
55 | ||
56 | _QUALITY = { | |
57 | '36': 2160, | |
58 | '35': 1080, | |
59 | '34': 720, | |
60 | '33': 480, | |
61 | '32': 360, | |
62 | '31': 270, | |
63 | } | |
64 | ||
65 | def _real_extract(self, url): | |
66 | id = self._match_id(url) | |
67 | video_data = self._download_json(f'https://tv.nate.com/api/v1/clip/{id}', id) | |
68 | formats = [{ | |
69 | 'format_id': f_url[-2:], | |
70 | 'url': f_url, | |
71 | 'height': self._QUALITY.get(f_url[-2:]), | |
72 | 'quality': int_or_none(f_url[-2:]), | |
73 | } for f_url in video_data.get('smcUriList') or []] | |
74 | self._sort_formats(formats) | |
75 | return { | |
76 | 'id': id, | |
77 | 'title': video_data.get('clipTitle'), | |
78 | 'description': video_data.get('synopsis'), | |
79 | 'thumbnail': video_data.get('contentImg'), | |
80 | 'upload_date': unified_strdate(traverse_obj(video_data, 'broadDate', 'regDate')), | |
81 | 'age_limit': video_data.get('targetAge'), | |
82 | 'duration': video_data.get('playTime'), | |
83 | 'formats': formats, | |
84 | 'uploader': video_data.get('programTitle'), | |
85 | 'channel': video_data.get('programTitle'), | |
86 | 'channel_id': str_or_none(video_data.get('programSeq')), | |
87 | 'uploader_id': str_or_none(video_data.get('programSeq')), | |
88 | 'tags': video_data['hashTag'].split(',') if video_data.get('hashTag') else None, | |
89 | } | |
90 | ||
91 | ||
92 | class NateProgramIE(InfoExtractor): | |
93 | _VALID_URL = r'https?://tv\.nate\.com/program/clips/(?P<id>[0-9]+)' | |
94 | ||
95 | _TESTS = [{ | |
96 | 'url': 'https://tv.nate.com/program/clips/27987', | |
97 | 'playlist_mincount': 191, | |
98 | 'info_dict': { | |
99 | 'id': '27987', | |
100 | }, | |
101 | }, { | |
102 | 'url': 'https://tv.nate.com/program/clips/3606', | |
103 | 'playlist_mincount': 15, | |
104 | 'info_dict': { | |
105 | 'id': '3606', | |
106 | }, | |
107 | }] | |
108 | ||
109 | def _entries(self, id): | |
110 | for page_num in itertools.count(1): | |
111 | program_data = self._download_json(f'https://tv.nate.com/api/v1/program/{id}/clip/ranking?size=20&page={page_num}', | |
112 | id, note=f'Downloading page {page_num}') | |
113 | for clip in program_data.get('content') or []: | |
114 | clip_id = clip.get('clipSeq') | |
115 | if clip_id: | |
116 | yield self.url_result( | |
117 | 'https://tv.nate.com/clip/%s' % clip_id, | |
118 | ie=NateIE.ie_key(), video_id=clip_id) | |
119 | if program_data.get('last'): | |
120 | break | |
121 | ||
122 | def _real_extract(self, url): | |
123 | id = self._match_id(url) | |
124 | return self.playlist_result(self._entries(id), playlist_id=id) |