206 params[
'headers'][
'Accept-Encoding'] =
'gzip, deflate'
212 args[
'spellcheck'] =
'1'
214 if brave_category
in (
'search',
'goggles'):
215 if params.get(
'pageno', 1) - 1:
216 args[
'offset'] = params.get(
'pageno', 1) - 1
217 if time_range_map.get(params[
'time_range']):
218 args[
'tf'] = time_range_map.get(params[
'time_range'])
220 if brave_category ==
'goggles':
221 args[
'goggles_id'] = Goggles
223 params[
"url"] = f
"{base_url}{brave_category}?{urlencode(args)}"
227 params[
'cookies'][
'safesearch'] = safesearch_map.get(params[
'safesearch'],
'off')
229 params[
'cookies'][
'useLocation'] =
'0'
230 params[
'cookies'][
'summarizer'] =
'0'
232 engine_region = traits.get_region(params[
'searxng_locale'],
'all')
233 params[
'cookies'][
'country'] = engine_region.split(
'-')[-1].lower()
235 ui_lang = locales.get_engine_locale(params[
'searxng_locale'], traits.custom[
"ui_lang"],
'en-us')
236 params[
'cookies'][
'ui_lang'] = ui_lang
238 logger.debug(
"cookies %s", params[
'cookies'])
301 dom = html.fromstring(resp.text)
305 answer_tag = eval_xpath_getindex(dom,
'//div[@class="answer"]', 0, default=
None)
307 url = eval_xpath_getindex(dom,
'//div[@id="featured_snippet"]/a[@class="result-header"]/@href', 0, default=
None)
308 answer = extract_text(answer_tag)
309 if answer
is not None:
310 result_list.add(result_list.types.Answer(answer=answer, url=url))
313 xpath_results =
'//div[contains(@class, "snippet ")]'
315 for result
in eval_xpath_list(dom, xpath_results):
317 url = eval_xpath_getindex(result,
'.//a[contains(@class, "h")]/@href', 0, default=
None)
318 title_tag = eval_xpath_getindex(
319 result,
'.//a[contains(@class, "h")]//div[contains(@class, "title")]', 0, default=
None
321 if url
is None or title_tag
is None or not urlparse(url).netloc:
324 content: str = extract_text(
325 eval_xpath_getindex(result,
'.//div[contains(@class, "snippet-description")]', 0, default=
'')
327 pub_date_raw = eval_xpath(result,
'substring-before(.//div[contains(@class, "snippet-description")], "-")')
329 if pub_date
and content.startswith(pub_date_raw):
330 content = content.lstrip(pub_date_raw).strip(
"- \n\t")
332 thumbnail = eval_xpath_getindex(result,
'.//img[contains(@class, "thumb")]/@src', 0, default=
'')
336 'title': extract_text(title_tag),
338 'publishedDate': pub_date,
339 'thumbnail': thumbnail,
342 video_tag = eval_xpath_getindex(
343 result,
'.//div[contains(@class, "video-snippet") and @data-macro="video"]', 0, default=
None
345 if video_tag
is not None:
350 iframe_src = get_embeded_stream_url(url)
352 item[
'iframe_src'] = iframe_src
353 item[
'template'] =
'videos.html'
354 item[
'thumbnail'] = eval_xpath_getindex(video_tag,
'.//img/@src', 0, default=
'')
355 pub_date_raw = extract_text(
356 eval_xpath(video_tag,
'.//div[contains(@class, "snippet-attributes")]/div/text()')
360 item[
'thumbnail'] = eval_xpath_getindex(video_tag,
'.//img/@src', 0, default=
'')
362 result_list.append(item)
370 dom = html.fromstring(resp.text)
372 for result
in eval_xpath_list(dom,
'//div[contains(@class, "results")]//div[@data-type="news"]'):
377 url = eval_xpath_getindex(result,
'.//a[contains(@class, "result-header")]/@href', 0, default=
None)
381 title = extract_text(eval_xpath_list(result,
'.//span[contains(@class, "snippet-title")]'))
382 content = extract_text(eval_xpath_list(result,
'.//p[contains(@class, "desc")]'))
383 thumbnail = eval_xpath_getindex(result,
'.//div[contains(@class, "image-wrapper")]//img/@src', 0, default=
'')
389 "thumbnail": thumbnail,
392 result_list.append(item)
445 """Fetch :ref:`languages <brave languages>` and :ref:`regions <brave
446 regions>` from Brave."""
450 import babel.languages
454 engine_traits.custom[
"ui_lang"] = {}
457 'Accept-Encoding':
'gzip, deflate',
459 lang_map = {
'no':
'nb'}
463 resp = get(
'https://search.brave.com/settings', headers=headers)
466 print(
"ERROR: response from Brave is not OK.")
467 dom = html.fromstring(resp.text)
469 for option
in dom.xpath(
'//section//option[@value="en-us"]/../option'):
471 ui_lang = option.get(
'value')
473 l = babel.Locale.parse(ui_lang, sep=
'-')
475 sxng_tag = region_tag(babel.Locale.parse(ui_lang, sep=
'-'))
477 sxng_tag = language_tag(babel.Locale.parse(ui_lang, sep=
'-'))
479 except babel.UnknownLocaleError:
480 print(
"ERROR: can't determine babel locale of Brave's (UI) language %s" % ui_lang)
483 conflict = engine_traits.custom[
"ui_lang"].get(sxng_tag)
485 if conflict != ui_lang:
486 print(
"CONFLICT: babel %s --> %s, %s" % (sxng_tag, conflict, ui_lang))
488 engine_traits.custom[
"ui_lang"][sxng_tag] = ui_lang
492 resp = get(
'https://cdn.search.brave.com/serp/v2/_app/immutable/chunks/parameters.734c106a.js', headers=headers)
495 print(
"ERROR: response from Brave is not OK.")
497 country_js = resp.text[resp.text.index(
"options:{all") + len(
'options:') :]
498 country_js = country_js[: country_js.index(
"},k={default")]
499 country_tags = js_variable_to_python(country_js)
501 for k, v
in country_tags.items():
503 engine_traits.all_locale =
'all'
505 country_tag = v[
'value']
508 for lang_tag
in babel.languages.get_official_languages(country_tag, de_facto=
True):
509 lang_tag = lang_map.get(lang_tag, lang_tag)
510 sxng_tag = region_tag(babel.Locale.parse(
'%s_%s' % (lang_tag, country_tag.upper())))
513 conflict = engine_traits.regions.get(sxng_tag)
515 if conflict != country_tag:
516 print(
"CONFLICT: babel %s --> %s, %s" % (sxng_tag, conflict, country_tag))
518 engine_traits.regions[sxng_tag] = country_tag