181def parse_web_api(resp):
182 """Parse results from Qwant's API"""
183
184
185 results = []
186
187
188 search_results = loads(resp.text)
189 data = search_results.get('data', {})
190
191
192 if search_results.get('status') != 'success':
193 error_code = data.get('error_code')
194 if error_code == 24:
195 raise SearxEngineTooManyRequestsException()
196 if search_results.get("data", {}).get("error_data", {}).get("captchaUrl") is not None:
197 raise SearxEngineCaptchaException()
198 msg = ",".join(data.get('message', ['unknown']))
199 raise SearxEngineAPIException(f"{msg} ({error_code})")
200
201
202 raise_for_httperror(resp)
203
204 if qwant_categ == 'web':
205
206
207
208 mainline = data.get('result', {}).get('items', {}).get('mainline', {})
209 else:
210
211
212
213 mainline = data.get('result', {}).get('items', [])
214 mainline = [
215 {'type': qwant_categ, 'items': mainline},
216 ]
217
218
219 if not mainline:
220 return []
221
222 for row in mainline:
223 mainline_type = row.get('type', 'web')
224 if mainline_type != qwant_categ:
225 continue
226
227 if mainline_type == 'ads':
228
229 continue
230
231 mainline_items = row.get('items', [])
232 for item in mainline_items:
233
234 title = item.get('title', None)
235 res_url = item.get('url', None)
236
237 if mainline_type == 'web':
238 content = item['desc']
239 results.append(
240 {
241 'title': title,
242 'url': res_url,
243 'content': content,
244 }
245 )
246
247 elif mainline_type == 'news':
248
249 pub_date = item['date']
250 if pub_date is not None:
251 pub_date = datetime.fromtimestamp(pub_date)
252 news_media = item.get('media', [])
253 thumbnail = None
254 if news_media:
255 thumbnail = news_media[0].get('pict', {}).get('url', None)
256 results.append(
257 {
258 'title': title,
259 'url': res_url,
260 'publishedDate': pub_date,
261 'thumbnail': thumbnail,
262 }
263 )
264
265 elif mainline_type == 'images':
266 thumbnail = item['thumbnail']
267 img_src = item['media']
268 results.append(
269 {
270 'title': title,
271 'url': res_url,
272 'template': 'images.html',
273 'thumbnail_src': thumbnail,
274 'img_src': img_src,
275 'resolution': f"{item['width']} x {item['height']}",
276 'img_format': item.get('thumb_type'),
277 }
278 )
279
280 elif mainline_type == 'videos':
281
282
283
284 d, s, c = item.get('desc'), item.get('source'), item.get('channel')
285 content_parts = []
286 if d:
287 content_parts.append(d)
288 if s:
289 content_parts.append("%s: %s " % (gettext("Source"), s))
290 if c:
291 content_parts.append("%s: %s " % (gettext("Channel"), c))
292 content = ' // '.join(content_parts)
293 length = item['duration']
294 if length is not None:
295 length = timedelta(milliseconds=length)
296 pub_date = item['date']
297 if pub_date is not None:
298 pub_date = datetime.fromtimestamp(pub_date)
299 thumbnail = item['thumbnail']
300
301
302 thumbnail = thumbnail.replace('https://s2.qwant.com', 'https://s1.qwant.com', 1)
303 results.append(
304 {
305 'title': title,
306 'url': res_url,
307 'content': content,
308 'iframe_src': get_embeded_stream_url(res_url),
309 'publishedDate': pub_date,
310 'thumbnail': thumbnail,
311 'template': 'videos.html',
312 'length': length,
313 }
314 )
315
316 return results
317
318