2"""This module implements functions needed for the autocompleter.
10from urllib.parse
import urlencode, quote_plus
14from httpx
import HTTPError
16from searx
import settings
30 if 'timeout' not in kwargs:
31 kwargs[
'timeout'] = settings[
'outgoing'][
'request_timeout']
32 kwargs[
'raise_for_httperror'] =
True
35def get(*args, **kwargs) -> "SXNG_Response":
37 return http_get(*args, **kwargs)
40def post(*args, **kwargs) -> "SXNG_Response":
42 return http_post(*args, **kwargs)
45def baidu(query: str, _sxng_locale: str) -> list[str]:
47 base_url =
"https://www.baidu.com/sugrec?"
48 response =
get(base_url + urlencode({
'ie':
'utf-8',
'json': 1,
'prod':
'pc',
'wd': query}))
49 results: list[str] = []
52 data: dict[str, t.Any] = response.json()
54 for item
in data[
'g']:
55 results.append(item[
'q'])
59def brave(query: str, _sxng_locale: str) -> list[str]:
61 url =
'https://search.brave.com/api/suggest?'
62 url += urlencode({
'q': query})
64 kwargs = {
'cookies': {
'country': country}}
65 resp =
get(url, **kwargs)
66 results: list[str] = []
69 data: list[list[str]] = resp.json()
75def dbpedia(query: str, _sxng_locale: str) -> list[str]:
76 autocomplete_url =
'https://lookup.dbpedia.org/api/search.asmx/KeywordSearch?'
77 resp =
get(autocomplete_url + urlencode(dict(QueryString=query)))
78 results: list[str] = []
81 dom = lxml.etree.fromstring(resp.content)
82 results = [str(x)
for x
in dom.xpath(
'//Result/Label//text()')]
87def duckduckgo(query: str, sxng_locale: str) -> list[str]:
88 """Autocomplete from DuckDuckGo. Supports DuckDuckGo's languages"""
90 traits = engines[
'duckduckgo'].traits
91 args: dict[str, str] = {
93 'kl': traits.get_region(sxng_locale, traits.all_locale),
96 url =
'https://duckduckgo.com/ac/?type=list&' + urlencode(args)
98 results: list[str] = []
108 """Autocomplete from Google. Supports Google's languages and subdomains
109 (:py:obj:`searx.engines.google.get_google_info`) by using the async REST
112 https://{subdomain}/complete/search?{args}
116 google_info: dict[str, t.Any] = google.get_google_info({
'searxng_locale': sxng_locale}, engines[
'google'].traits)
117 url =
'https://{subdomain}/complete/search?{args}'
122 'hl': google_info[
'params'][
'hl'],
125 results: list[str] = []
127 resp =
get(url.format(subdomain=google_info[
'subdomain'], args=args))
129 json_txt = resp.text[resp.text.find(
'[') : resp.text.find(
']', -3) + 1]
130 data = json.loads(json_txt)
132 results.append(lxml.html.fromstring(item[0]).text_content())
136def mwmbl(query: str, _sxng_locale: str) -> list[str]:
137 """Autocomplete from Mwmbl_."""
140 url =
'https://api.mwmbl.org/search/complete?{query}'
142 results: list[str] =
get(url.format(query=urlencode({
'q': query}))).
json()[1]
145 return [result
for result
in results
if not result.startswith(
"go: ")
and not result.startswith(
"search: ")]
148def naver(query: str, _sxng_locale: str) -> list[str]:
150 url = f
"https://ac.search.naver.com/nx/ac?{urlencode({'q': query, 'r_format': 'json', 'st': 0})}"
152 results: list[str] = []
155 data: dict[str, t.Any] = response.json()
156 if data.get(
'items'):
157 for item
in data[
'items'][0]:
158 results.append(item[0])
164 url = f
"https://sug.so.360.cn/suggest?{urlencode({'format': 'json', 'word': query})}"
166 results: list[str] = []
169 data: dict[str, t.Any] = response.json()
171 for item
in data[
'result']:
172 results.append(item[
'word'])
176def quark(query: str, _sxng_locale: str) -> list[str]:
178 url = f
"https://sugs.m.sm.cn/web?{urlencode({'q': query})}"
180 results: list[str] = []
183 data = response.json()
184 for item
in data.get(
'r', []):
185 results.append(item[
'w'])
189def seznam(query: str, _sxng_locale: str) -> list[str]:
191 url =
'https://suggest.seznam.cz/fulltext/cs?{query}'
195 {
'phrase': query,
'cursorPosition': len(query),
'format':
'json-2',
'highlight':
'1',
'count':
'6'}
199 results: list[str] = []
204 ''.join([part.get(
'text',
'')
for part
in item.get(
'text', [])])
205 for item
in data.get(
'result', [])
206 if item.get(
'itemType',
None) ==
'ItemType.TEXT'
211def sogou(query: str, _sxng_locale: str) -> list[str]:
213 base_url =
"https://sor.html5.qq.com/api/getsug?"
214 resp =
get(base_url + urlencode({
'm':
'searxng',
'key': query}))
215 results: list[str] = []
218 raw_json = extr(resp.text,
"[",
"]", default=
"")
220 data = json.loads(f
"[{raw_json}]]")
222 except json.JSONDecodeError:
227def startpage(query: str, sxng_locale: str) -> list[str]:
228 """Autocomplete from Startpage's Firefox extension.
229 Supports the languages specified in lang_map.
245 base_lang = sxng_locale.split(
'-')[0]
246 lui = lang_map.get(base_lang,
'english')
250 'format':
'opensearch',
251 'segment':
'startpage.defaultffx',
254 url = f
'https://www.startpage.com/suggestions?{urlencode(url_params)}'
257 h = {
'User-Agent': gen_useragent()}
259 resp =
get(url, headers=h)
260 results: list[str] = []
265 if len(data) >= 2
and isinstance(data[1], list):
267 except json.JSONDecodeError:
273def stract(query: str, _sxng_locale: str) -> list[str]:
275 url = f
"https://stract.com/beta/api/autosuggest?q={quote_plus(query)}"
277 results: list[str] = []
280 results = [html.unescape(suggestion[
'raw'])
for suggestion
in resp.json()]
285def swisscows(query: str, _sxng_locale: str) -> list[str]:
287 url =
'https://swisscows.ch/api/suggest?{query}&itemsCount=5'
288 results: list[str] = json.loads(
get(url.format(query=urlencode({
'query': query}))).text)
292def qwant(query: str, sxng_locale: str) -> list[str]:
293 """Autocomplete from Qwant. Supports Qwant's regions."""
294 locale = engines[
'qwant'].traits.get_region(sxng_locale,
'en_US')
295 url =
'https://api.qwant.com/v3/suggest?{query}'
296 resp =
get(url.format(query=urlencode({
'q': query,
'locale': locale,
'version':
'2'})))
297 results: list[str] = []
301 if data[
'status'] ==
'success':
302 for item
in data[
'data'][
'items']:
303 results.append(item[
'value'])
308def wikipedia(query: str, sxng_locale: str) -> list[str]:
309 """Autocomplete from Wikipedia. Supports Wikipedia's languages (aka netloc)."""
310 eng_traits = engines[
'wikipedia'].traits
311 wiki_lang = eng_traits.get_language(sxng_locale,
'en')
312 wiki_netloc: str = eng_traits.custom[
'wiki_netloc'].
get(wiki_lang,
'en.wikipedia.org')
316 'action':
'opensearch',
318 'formatversion':
'2',
324 resp =
get(f
'https://{wiki_netloc}/w/api.php?{args}')
325 results: list[str] = []
335def yandex(query: str, _sxng_locale: str) -> list[str]:
337 url =
"https://suggest.yandex.com/suggest-ff.cgi?{0}"
338 resp = json.loads(
get(url.format(urlencode(dict(part=query)))).text)
339 results: list[str] = []
346backends: dict[str, t.Callable[[str, str], list[str]]] = {
347 '360search': qihu360search,
351 'duckduckgo': duckduckgo,
352 'google': google_complete,
359 'startpage': startpage,
361 'swisscows': swisscows,
362 'wikipedia': wikipedia,
368 backend = backends.get(backend_name)
372 return backend(query, sxng_locale)
373 except (HTTPError, SearxEngineResponseException):
list[str] google_complete(str query, str sxng_locale)
"SXNG_Response" post(*args, **kwargs)
list[str] swisscows(str query, str _sxng_locale)
list[str] wikipedia(str query, str sxng_locale)
list[str] stract(str query, str _sxng_locale)
list[str] seznam(str query, str _sxng_locale)
list[str] yandex(str query, str _sxng_locale)
list[str] naver(str query, str _sxng_locale)
list[str] baidu(str query, str _sxng_locale)
list[str] qihu360search(str query, str _sxng_locale)
list[str] qwant(str query, str sxng_locale)
list[str] brave(str query, str _sxng_locale)
list[str] mwmbl(str query, str _sxng_locale)
list[str] dbpedia(str query, str _sxng_locale)
list[str] quark(str query, str _sxng_locale)
"SXNG_Response" get(*args, **kwargs)
list[str] sogou(str query, str _sxng_locale)
list[str] search_autocomplete(str backend_name, str query, str sxng_locale)
list[str] startpage(str query, str sxng_locale)
list[str] duckduckgo(str query, str sxng_locale)
None update_kwargs(**kwargs)