diff options
Diffstat (limited to 'searx/autocomplete.py')
-rw-r--r-- | searx/autocomplete.py | 135 |
1 files changed, 45 insertions, 90 deletions
diff --git a/searx/autocomplete.py b/searx/autocomplete.py index ff89585..761c86c 100644 --- a/searx/autocomplete.py +++ b/searx/autocomplete.py @@ -16,107 +16,43 @@ along with searx. If not, see < http://www.gnu.org/licenses/ >. ''' -import sys from lxml import etree from json import loads +from urllib.parse import urlencode + +from requests import RequestException + from searx import settings -from searx.languages import language_codes -from searx.engines import ( - categories, engines, engine_shortcuts -) from searx.poolrequests import get as http_get -from searx.url_utils import urlencode - -if sys.version_info[0] == 3: - unicode = str +from searx.exceptions import SearxEngineResponseException def get(*args, **kwargs): if 'timeout' not in kwargs: kwargs['timeout'] = settings['outgoing']['request_timeout'] - + kwargs['raise_for_httperror'] = True return http_get(*args, **kwargs) -def searx_bang(full_query): - '''check if the searchQuery contain a bang, and create fitting autocompleter results''' - # check if there is a query which can be parsed - if len(full_query.getSearchQuery()) == 0: - return [] +def brave(query, lang): + # brave search autocompleter + url = 'https://search.brave.com/api/suggest?{query}' + + resp = get(url.format(query=urlencode({'q': query}))) results = [] - # check if current query stats with !bang - first_char = full_query.getSearchQuery()[0] - if first_char == '!' or first_char == '?': - if len(full_query.getSearchQuery()) == 1: - # show some example queries - # TODO, check if engine is not avaliable - results.append(first_char + "images") - results.append(first_char + "wikipedia") - results.append(first_char + "osm") - else: - engine_query = full_query.getSearchQuery()[1:] - - # check if query starts with categorie name - for categorie in categories: - if categorie.startswith(engine_query): - results.append(first_char + '{categorie}'.format(categorie=categorie)) - - # check if query starts with engine name - for engine in engines: - if engine.startswith(engine_query.replace('_', ' ')): - results.append(first_char + '{engine}'.format(engine=engine.replace(' ', '_'))) - - # check if query starts with engine shortcut - for engine_shortcut in engine_shortcuts: - if engine_shortcut.startswith(engine_query): - results.append(first_char + '{engine_shortcut}'.format(engine_shortcut=engine_shortcut)) - - # check if current query stats with :bang - elif first_char == ':': - if len(full_query.getSearchQuery()) == 1: - # show some example queries - results.append(":en") - results.append(":en_us") - results.append(":english") - results.append(":united_kingdom") - else: - engine_query = full_query.getSearchQuery()[1:] - - for lc in language_codes: - lang_id, lang_name, country, english_name = map(unicode.lower, lc) - - # check if query starts with language-id - if lang_id.startswith(engine_query): - if len(engine_query) <= 2: - results.append(u':{lang_id}'.format(lang_id=lang_id.split('-')[0])) - else: - results.append(u':{lang_id}'.format(lang_id=lang_id)) - - # check if query starts with language name - if lang_name.startswith(engine_query) or english_name.startswith(engine_query): - results.append(u':{lang_name}'.format(lang_name=lang_name)) - - # check if query starts with country - if country.startswith(engine_query.replace('_', ' ')): - results.append(u':{country}'.format(country=country.replace(' ', '_'))) - - # remove duplicates - result_set = set(results) - - # remove results which are already contained in the query - for query_part in full_query.query_parts: - if query_part in result_set: - result_set.remove(query_part) - - # convert result_set back to list - return list(result_set) + if resp.ok: + data = loads(resp.text) + for suggestion in data[1]: + results.append(suggestion) + + return results def dbpedia(query, lang): # dbpedia autocompleter, no HTTPS - autocomplete_url = 'http://lookup.dbpedia.org/api/search.asmx/KeywordSearch?' + autocomplete_url = 'https://lookup.dbpedia.org/api/search.asmx/KeywordSearch?' response = get(autocomplete_url + urlencode(dict(QueryString=query))) @@ -124,8 +60,7 @@ def dbpedia(query, lang): if response.ok: dom = etree.fromstring(response.content) - results = dom.xpath('//a:Result/a:Label//text()', - namespaces={'a': 'http://lookup.dbpedia.org/'}) + results = dom.xpath('//Result/Label//text()') return results @@ -157,12 +92,19 @@ def google(query, lang): def startpage(query, lang): # startpage autocompleter - url = 'https://startpage.com/do/suggest?{query}' + lui = ENGINES_LANGUAGES['startpage'].get(lang, 'english') + url = 'https://startpage.com/suggestions?{query}' + resp = get(url.format(query=urlencode({'q': query, 'segment': 'startpage.udog', 'lui': lui}))) + data = resp.json() + return [e['text'] for e in data.get('suggestions', []) if 'text' in e] - resp = get(url.format(query=urlencode({'query': query}))).text.split('\n') - if len(resp) > 1: - return resp - return [] + +def swisscows(query, lang): + # swisscows autocompleter + url = 'https://swisscows.ch/api/suggest?{query}&itemsCount=5' + + resp = loads(get(url.format(query=urlencode({'query': query}))).text) + return resp def qwant(query, lang): @@ -192,10 +134,23 @@ def wikipedia(query, lang): return [] -backends = {'dbpedia': dbpedia, +backends = {'brave': brave, + 'dbpedia': dbpedia, 'duckduckgo': duckduckgo, 'google': google, 'startpage': startpage, + 'swisscows': swisscows, 'qwant': qwant, 'wikipedia': wikipedia } + + +def search_autocomplete(backend_name, query, lang): + backend = backends.get(backend_name) + if backend is None: + return [] + + try: + return backend(query, lang) + except (RequestException, SearxEngineResponseException): + return [] |