]>
Commit | Line | Data |
---|---|---|
a820dc72 | 1 | import json |
29f7c58a | 2 | |
13de91c9 | 3 | from .common import InfoExtractor |
4bb58fa1 S |
4 | from ..utils import ( |
5 | clean_html, | |
a820dc72 | 6 | int_or_none, |
4bb58fa1 S |
7 | try_get, |
8 | unified_strdate, | |
a820dc72 | 9 | unified_timestamp, |
4bb58fa1 | 10 | ) |
13de91c9 DW |
11 | |
12 | ||
13 | class AmericasTestKitchenIE(InfoExtractor): | |
45b2ee6f | 14 | _VALID_URL = r'https?://(?:www\.)?(?:americastestkitchen|cooks(?:country|illustrated))\.com/(?:cooks(?:country|illustrated)/)?(?P<resource_type>episode|videos)/(?P<id>\d+)' |
13de91c9 | 15 | _TESTS = [{ |
2c482bff | 16 | 'url': 'https://www.americastestkitchen.com/episode/582-weeknight-japanese-suppers', |
13de91c9 DW |
17 | 'md5': 'b861c3e365ac38ad319cfd509c30577f', |
18 | 'info_dict': { | |
2c482bff | 19 | 'id': '5b400b9ee338f922cb06450c', |
29f7c58a | 20 | 'title': 'Japanese Suppers', |
13de91c9 | 21 | 'ext': 'mp4', |
c66ed4e2 | 22 | 'display_id': 'weeknight-japanese-suppers', |
29f7c58a | 23 | 'description': 'md5:64e606bfee910627efc4b5f050de92b3', |
c66ed4e2 | 24 | 'timestamp': 1523304000, |
25 | 'upload_date': '20180409', | |
26 | 'release_date': '20180409', | |
27 | 'series': 'America\'s Test Kitchen', | |
28 | 'season': 'Season 18', | |
29f7c58a | 29 | 'episode': 'Japanese Suppers', |
c66ed4e2 | 30 | 'season_number': 18, |
2c482bff | 31 | 'episode_number': 15, |
c66ed4e2 | 32 | 'duration': 1376, |
33 | 'thumbnail': r're:^https?://', | |
34 | 'average_rating': 0, | |
35 | 'view_count': int, | |
13de91c9 DW |
36 | }, |
37 | 'params': { | |
13de91c9 DW |
38 | 'skip_download': True, |
39 | }, | |
a820dc72 RA |
40 | }, { |
41 | # Metadata parsing behaves differently for newer episodes (705) as opposed to older episodes (582 above) | |
42 | 'url': 'https://www.americastestkitchen.com/episode/705-simple-chicken-dinner', | |
43 | 'md5': '06451608c57651e985a498e69cec17e5', | |
44 | 'info_dict': { | |
45 | 'id': '5fbe8c61bda2010001c6763b', | |
46 | 'title': 'Simple Chicken Dinner', | |
47 | 'ext': 'mp4', | |
c66ed4e2 | 48 | 'display_id': 'atktv_2103_simple-chicken-dinner_full-episode_web-mp4', |
a820dc72 | 49 | 'description': 'md5:eb68737cc2fd4c26ca7db30139d109e7', |
c66ed4e2 | 50 | 'timestamp': 1610737200, |
51 | 'upload_date': '20210115', | |
52 | 'release_date': '20210115', | |
53 | 'series': 'America\'s Test Kitchen', | |
54 | 'season': 'Season 21', | |
a820dc72 | 55 | 'episode': 'Simple Chicken Dinner', |
c66ed4e2 | 56 | 'season_number': 21, |
a820dc72 | 57 | 'episode_number': 3, |
c66ed4e2 | 58 | 'duration': 1397, |
59 | 'thumbnail': r're:^https?://', | |
60 | 'view_count': int, | |
61 | 'average_rating': 0, | |
a820dc72 RA |
62 | }, |
63 | 'params': { | |
64 | 'skip_download': True, | |
65 | }, | |
13de91c9 | 66 | }, { |
4bb58fa1 S |
67 | 'url': 'https://www.americastestkitchen.com/videos/3420-pan-seared-salmon', |
68 | 'only_matching': True, | |
29f7c58a | 69 | }, { |
c66ed4e2 | 70 | 'url': 'https://www.americastestkitchen.com/cookscountry/episode/564-when-only-chocolate-will-do', |
29f7c58a | 71 | 'only_matching': True, |
72 | }, { | |
c66ed4e2 | 73 | 'url': 'https://www.americastestkitchen.com/cooksillustrated/videos/4478-beef-wellington', |
29f7c58a | 74 | 'only_matching': True, |
45b2ee6f | 75 | }, { |
76 | 'url': 'https://www.cookscountry.com/episode/564-when-only-chocolate-will-do', | |
77 | 'only_matching': True, | |
78 | }, { | |
79 | 'url': 'https://www.cooksillustrated.com/videos/4478-beef-wellington', | |
80 | 'only_matching': True, | |
13de91c9 DW |
81 | }] |
82 | ||
83 | def _real_extract(self, url): | |
5ad28e7f | 84 | resource_type, video_id = self._match_valid_url(url).groups() |
29f7c58a | 85 | is_episode = resource_type == 'episode' |
86 | if is_episode: | |
87 | resource_type = 'episodes' | |
13de91c9 | 88 | |
29f7c58a | 89 | resource = self._download_json( |
add96eb9 | 90 | f'https://www.americastestkitchen.com/api/v6/{resource_type}/{video_id}', video_id) |
29f7c58a | 91 | video = resource['video'] if is_episode else resource |
92 | episode = resource if is_episode else resource.get('episode') or {} | |
13de91c9 DW |
93 | |
94 | return { | |
95 | '_type': 'url_transparent', | |
add96eb9 | 96 | 'url': 'https://player.zype.com/embed/{}.js?api_key=jZ9GUhRmxcPvX7M3SlfejB6Hle9jyHTdk2jVxG7wOHPLODgncEKVdPYBhuz9iWXQ'.format(video['zypeId']), |
2c482bff | 97 | 'ie_key': 'Zype', |
29f7c58a | 98 | 'description': clean_html(video.get('description')), |
a820dc72 | 99 | 'timestamp': unified_timestamp(video.get('publishDate')), |
29f7c58a | 100 | 'release_date': unified_strdate(video.get('publishDate')), |
a820dc72 RA |
101 | 'episode_number': int_or_none(episode.get('number')), |
102 | 'season_number': int_or_none(episode.get('season')), | |
29f7c58a | 103 | 'series': try_get(episode, lambda x: x['show']['title']), |
104 | 'episode': episode.get('title'), | |
13de91c9 | 105 | } |
a820dc72 RA |
106 | |
107 | ||
108 | class AmericasTestKitchenSeasonIE(InfoExtractor): | |
45b2ee6f | 109 | _VALID_URL = r'https?://(?:www\.)?(?P<show>americastestkitchen|(?P<cooks>cooks(?:country|illustrated)))\.com(?:(?:/(?P<show2>cooks(?:country|illustrated)))?(?:/?$|(?<!ated)(?<!ated\.com)/episodes/browse/season_(?P<season>\d+)))' |
a820dc72 RA |
110 | _TESTS = [{ |
111 | # ATK Season | |
112 | 'url': 'https://www.americastestkitchen.com/episodes/browse/season_1', | |
113 | 'info_dict': { | |
114 | 'id': 'season_1', | |
115 | 'title': 'Season 1', | |
116 | }, | |
117 | 'playlist_count': 13, | |
118 | }, { | |
119 | # Cooks Country Season | |
c66ed4e2 | 120 | 'url': 'https://www.americastestkitchen.com/cookscountry/episodes/browse/season_12', |
a820dc72 RA |
121 | 'info_dict': { |
122 | 'id': 'season_12', | |
123 | 'title': 'Season 12', | |
124 | }, | |
125 | 'playlist_count': 13, | |
45b2ee6f | 126 | }, { |
127 | # America's Test Kitchen Series | |
128 | 'url': 'https://www.americastestkitchen.com/', | |
129 | 'info_dict': { | |
130 | 'id': 'americastestkitchen', | |
131 | 'title': 'America\'s Test Kitchen', | |
132 | }, | |
133 | 'playlist_count': 558, | |
134 | }, { | |
135 | # Cooks Country Series | |
136 | 'url': 'https://www.americastestkitchen.com/cookscountry', | |
137 | 'info_dict': { | |
138 | 'id': 'cookscountry', | |
139 | 'title': 'Cook\'s Country', | |
140 | }, | |
141 | 'playlist_count': 199, | |
142 | }, { | |
143 | 'url': 'https://www.americastestkitchen.com/cookscountry/', | |
144 | 'only_matching': True, | |
145 | }, { | |
146 | 'url': 'https://www.cookscountry.com/episodes/browse/season_12', | |
147 | 'only_matching': True, | |
148 | }, { | |
149 | 'url': 'https://www.cookscountry.com', | |
150 | 'only_matching': True, | |
151 | }, { | |
152 | 'url': 'https://www.americastestkitchen.com/cooksillustrated/', | |
153 | 'only_matching': True, | |
154 | }, { | |
155 | 'url': 'https://www.cooksillustrated.com', | |
156 | 'only_matching': True, | |
a820dc72 RA |
157 | }] |
158 | ||
159 | def _real_extract(self, url): | |
45b2ee6f | 160 | season_number, show1, show = self._match_valid_url(url).group('season', 'show', 'show2') |
161 | show_path = ('/' + show) if show else '' | |
162 | show = show or show1 | |
163 | season_number = int_or_none(season_number) | |
164 | ||
165 | slug, title = { | |
166 | 'americastestkitchen': ('atk', 'America\'s Test Kitchen'), | |
167 | 'cookscountry': ('cco', 'Cook\'s Country'), | |
168 | 'cooksillustrated': ('cio', 'Cook\'s Illustrated'), | |
169 | }[show] | |
a820dc72 | 170 | |
45b2ee6f | 171 | facet_filters = [ |
172 | 'search_document_klass:episode', | |
173 | 'search_show_slug:' + slug, | |
174 | ] | |
a820dc72 | 175 | |
45b2ee6f | 176 | if season_number: |
add96eb9 | 177 | playlist_id = f'season_{season_number}' |
178 | playlist_title = f'Season {season_number}' | |
45b2ee6f | 179 | facet_filters.append('search_season_list:' + playlist_title) |
180 | else: | |
181 | playlist_id = show | |
182 | playlist_title = title | |
a820dc72 RA |
183 | |
184 | season_search = self._download_json( | |
add96eb9 | 185 | f'https://y1fnzxui30-dsn.algolia.net/1/indexes/everest_search_{slug}_season_desc_production', |
45b2ee6f | 186 | playlist_id, headers={ |
c66ed4e2 | 187 | 'Origin': 'https://www.americastestkitchen.com', |
a820dc72 RA |
188 | 'X-Algolia-API-Key': '8d504d0099ed27c1b73708d22871d805', |
189 | 'X-Algolia-Application-Id': 'Y1FNZXUI30', | |
190 | }, query={ | |
45b2ee6f | 191 | 'facetFilters': json.dumps(facet_filters), |
add96eb9 | 192 | 'attributesToRetrieve': f'description,search_{slug}_episode_number,search_document_date,search_url,title,search_atk_episode_season', |
a820dc72 RA |
193 | 'attributesToHighlight': '', |
194 | 'hitsPerPage': 1000, | |
195 | }) | |
196 | ||
197 | def entries(): | |
198 | for episode in (season_search.get('hits') or []): | |
c66ed4e2 | 199 | search_url = episode.get('search_url') # always formatted like '/episode/123-title-of-episode' |
a820dc72 RA |
200 | if not search_url: |
201 | continue | |
202 | yield { | |
203 | '_type': 'url', | |
c66ed4e2 | 204 | 'url': f'https://www.americastestkitchen.com{show_path or ""}{search_url}', |
a820dc72 RA |
205 | 'id': try_get(episode, lambda e: e['objectID'].split('_')[-1]), |
206 | 'title': episode.get('title'), | |
207 | 'description': episode.get('description'), | |
208 | 'timestamp': unified_timestamp(episode.get('search_document_date')), | |
209 | 'season_number': season_number, | |
add96eb9 | 210 | 'episode_number': int_or_none(episode.get(f'search_{slug}_episode_number')), |
a820dc72 RA |
211 | 'ie_key': AmericasTestKitchenIE.ie_key(), |
212 | } | |
213 | ||
214 | return self.playlist_result( | |
45b2ee6f | 215 | entries(), playlist_id, playlist_title) |