206 params[
'headers'][
'Accept-Encoding'] =
'gzip, deflate'
213 args[
'spellcheck'] =
'1'
215 if brave_category
in (
'search',
'goggles'):
216 if params.get(
'pageno', 1) - 1:
217 args[
'offset'] = params.get(
'pageno', 1) - 1
218 if time_range_map.get(params[
'time_range']):
219 args[
'tf'] = time_range_map.get(params[
'time_range'])
221 if brave_category ==
'goggles':
222 args[
'goggles_id'] = Goggles
224 params[
"url"] = f
"{base_url}{brave_category}?{urlencode(args)}"
228 params[
'cookies'][
'safesearch'] = safesearch_map.get(params[
'safesearch'],
'off')
230 params[
'cookies'][
'useLocation'] =
'0'
231 params[
'cookies'][
'summarizer'] =
'0'
233 engine_region = traits.get_region(params[
'searxng_locale'],
'all')
234 params[
'cookies'][
'country'] = engine_region.split(
'-')[-1].lower()
236 ui_lang = locales.get_engine_locale(params[
'searxng_locale'], traits.custom[
"ui_lang"],
'en-us')
237 params[
'cookies'][
'ui_lang'] = ui_lang
239 logger.debug(
"cookies %s", params[
'cookies'])
241 params[
'headers'][
'Sec-Fetch-Dest'] =
"document"
242 params[
'headers'][
'Sec-Fetch-Mode'] =
"navigate"
243 params[
'headers'][
'Sec-Fetch-Site'] =
"same-origin"
244 params[
'headers'][
'Sec-Fetch-User'] =
"?1"
288 dom = html.fromstring(resp.text)
292 answer_tag = eval_xpath_getindex(dom,
'//div[@class="answer"]', 0, default=
None)
294 url = eval_xpath_getindex(dom,
'//div[@id="featured_snippet"]/a[@class="result-header"]/@href', 0, default=
None)
295 answer = extract_text(answer_tag)
296 if answer
is not None:
297 result_list.add(result_list.types.Answer(answer=answer, url=url))
300 xpath_results =
'//div[contains(@class, "snippet ")]'
302 for result
in eval_xpath_list(dom, xpath_results):
304 url = eval_xpath_getindex(result,
'.//a[contains(@class, "h")]/@href', 0, default=
None)
305 title_tag = eval_xpath_getindex(
306 result,
'.//a[contains(@class, "h")]//div[contains(@class, "title")]', 0, default=
None
308 if url
is None or title_tag
is None or not urlparse(url).netloc:
311 content: str = extract_text(
312 eval_xpath_getindex(result,
'.//div[contains(@class, "snippet-description")]', 0, default=
'')
314 pub_date_raw = eval_xpath(result,
'substring-before(.//div[contains(@class, "snippet-description")], "-")')
316 if pub_date
and content.startswith(pub_date_raw):
317 content = content.lstrip(pub_date_raw).strip(
"- \n\t")
319 thumbnail = eval_xpath_getindex(result,
'.//img[contains(@class, "thumb")]/@src', 0, default=
'')
323 'title': extract_text(title_tag),
325 'publishedDate': pub_date,
326 'thumbnail': thumbnail,
329 video_tag = eval_xpath_getindex(
330 result,
'.//div[contains(@class, "video-snippet") and @data-macro="video"]', 0, default=
None
332 if video_tag
is not None:
337 iframe_src = get_embeded_stream_url(url)
339 item[
'iframe_src'] = iframe_src
340 item[
'template'] =
'videos.html'
341 item[
'thumbnail'] = eval_xpath_getindex(video_tag,
'.//img/@src', 0, default=
'')
342 pub_date_raw = extract_text(
343 eval_xpath(video_tag,
'.//div[contains(@class, "snippet-attributes")]/div/text()')
347 item[
'thumbnail'] = eval_xpath_getindex(video_tag,
'.//img/@src', 0, default=
'')
349 result_list.append(item)
357 dom = html.fromstring(resp.text)
359 for result
in eval_xpath_list(dom,
'//div[contains(@class, "results")]//div[@data-type="news"]'):
364 url = eval_xpath_getindex(result,
'.//a[contains(@class, "result-header")]/@href', 0, default=
None)
368 title = extract_text(eval_xpath_list(result,
'.//span[contains(@class, "snippet-title")]'))
369 content = extract_text(eval_xpath_list(result,
'.//p[contains(@class, "desc")]'))
370 thumbnail = eval_xpath_getindex(result,
'.//div[contains(@class, "image-wrapper")]//img/@src', 0, default=
'')
376 "thumbnail": thumbnail,
379 result_list.append(item)
432 """Fetch :ref:`languages <brave languages>` and :ref:`regions <brave
433 regions>` from Brave."""
437 import babel.languages
441 engine_traits.custom[
"ui_lang"] = {}
444 'Accept-Encoding':
'gzip, deflate',
446 lang_map = {
'no':
'nb'}
450 resp = get(
'https://search.brave.com/settings', headers=headers)
453 print(
"ERROR: response from Brave is not OK.")
454 dom = html.fromstring(resp.text)
456 for option
in dom.xpath(
'//section//option[@value="en-us"]/../option'):
458 ui_lang = option.get(
'value')
460 l = babel.Locale.parse(ui_lang, sep=
'-')
462 sxng_tag = region_tag(babel.Locale.parse(ui_lang, sep=
'-'))
464 sxng_tag = language_tag(babel.Locale.parse(ui_lang, sep=
'-'))
466 except babel.UnknownLocaleError:
467 print(
"ERROR: can't determine babel locale of Brave's (UI) language %s" % ui_lang)
470 conflict = engine_traits.custom[
"ui_lang"].get(sxng_tag)
472 if conflict != ui_lang:
473 print(
"CONFLICT: babel %s --> %s, %s" % (sxng_tag, conflict, ui_lang))
475 engine_traits.custom[
"ui_lang"][sxng_tag] = ui_lang
479 resp = get(
'https://cdn.search.brave.com/serp/v2/_app/immutable/chunks/parameters.734c106a.js', headers=headers)
482 print(
"ERROR: response from Brave is not OK.")
484 country_js = resp.text[resp.text.index(
"options:{all") + len(
'options:') :]
485 country_js = country_js[: country_js.index(
"},k={default")]
486 country_tags = js_variable_to_python(country_js)
488 for k, v
in country_tags.items():
490 engine_traits.all_locale =
'all'
492 country_tag = v[
'value']
495 for lang_tag
in babel.languages.get_official_languages(country_tag, de_facto=
True):
496 lang_tag = lang_map.get(lang_tag, lang_tag)
497 sxng_tag = region_tag(babel.Locale.parse(
'%s_%s' % (lang_tag, country_tag.upper())))
500 conflict = engine_traits.regions.get(sxng_tag)
502 if conflict != country_tag:
503 print(
"CONFLICT: babel %s --> %s, %s" % (sxng_tag, conflict, country_tag))
505 engine_traits.regions[sxng_tag] = country_tag