diff --git a/searx/search.py b/searx/search.py index 66e3d62d..9c66f75f 100644 --- a/searx/search.py +++ b/searx/search.py @@ -414,30 +414,86 @@ class Search: super().__init__() self.search_query = search_query self.result_container = ResultContainer() + self.start_time = None self.actual_timeout = None - # do search-request - def search(self): - global number_of_searches - - # Check if there is a external bang. After that we can stop because the search will terminate. + def search_external_bang(self): + """ + Check if there is a external bang. + If yes, update self.result_container and return True + """ if self.search_query.external_bang: self.result_container.redirect_url = get_bang_url(self.search_query) # This means there was a valid bang and the # rest of the search does not need to be continued if isinstance(self.result_container.redirect_url, str): - return self.result_container - # start time - start_time = time() + return True + return False - # answeres ? + def search_answerers(self): + """ + Check if an answer return a result. + If yes, update self.result_container and return True + """ answerers_results = ask(self.search_query) if answerers_results: for results in answerers_results: self.result_container.extend('answer', results) - return self.result_container + return True + return False + + def _is_accepted(self, engine_name, engine): + if not self.search_query.preferences.validate_token(engine): + return False + + # skip suspended engines + if engine.suspend_end_time >= time(): + logger.debug('Engine currently suspended: %s', engine_name) + return False + + # if paging is not supported, skip + if self.search_query.pageno > 1 and not engine.paging: + return False + + # if time_range is not supported, skip + if self.search_query.time_range and not engine.time_range_support: + return False + + return True + + def _get_params(self, selected_engine, user_agent): + if selected_engine['name'] not in engines: + return None, None + + engine = engines[selected_engine['name']] + + if not self._is_accepted(selected_engine['name'], engine): + return None, None + + # set default request parameters + request_params = {} + if not engine.offline: + request_params = default_request_params() + request_params['headers']['User-Agent'] = user_agent + + if hasattr(engine, 'language') and engine.language: + request_params['language'] = engine.language + else: + request_params['language'] = self.search_query.lang + + request_params['safesearch'] = self.search_query.safesearch + request_params['time_range'] = self.search_query.time_range + + request_params['category'] = selected_engine['category'] + request_params['pageno'] = self.search_query.pageno + + return request_params, engine.timeout + + # do search-request + def _get_requests(self): + global number_of_searches # init vars requests = [] @@ -449,59 +505,24 @@ class Search: # user_agent = request.headers.get('User-Agent', '') user_agent = gen_useragent() - search_query = self.search_query - # max of all selected engine timeout default_timeout = 0 # start search-reqest for all selected engines - for selected_engine in search_query.engines: - if selected_engine['name'] not in engines: - continue - - engine = engines[selected_engine['name']] - - if not search_query.preferences.validate_token(engine): - continue - - # skip suspended engines - if engine.suspend_end_time >= time(): - logger.debug('Engine currently suspended: %s', selected_engine['name']) - continue - - # if paging is not supported, skip - if search_query.pageno > 1 and not engine.paging: - continue - - # if time_range is not supported, skip - if search_query.time_range and not engine.time_range_support: - continue - + for selected_engine in self.search_query.engines: # set default request parameters - request_params = {} - if not engine.offline: - request_params = default_request_params() - request_params['headers']['User-Agent'] = user_agent - - if hasattr(engine, 'language') and engine.language: - request_params['language'] = engine.language - else: - request_params['language'] = search_query.lang - - request_params['safesearch'] = search_query.safesearch - request_params['time_range'] = search_query.time_range - - request_params['category'] = selected_engine['category'] - request_params['pageno'] = search_query.pageno + request_params, engine_timeout = self._get_params(selected_engine, user_agent) + if request_params is None: + continue # append request to list - requests.append((selected_engine['name'], search_query.query, request_params)) + requests.append((selected_engine['name'], self.search_query.query, request_params)) # update default_timeout - default_timeout = max(default_timeout, engine.timeout) + default_timeout = max(default_timeout, engine_timeout) # adjust timeout - self.actual_timeout = default_timeout + actual_timeout = default_timeout query_timeout = self.search_query.timeout_limit if max_request_timeout is None and query_timeout is None: @@ -509,23 +530,41 @@ class Search: pass elif max_request_timeout is None and query_timeout is not None: # No max, but user query: From user query except if above default - self.actual_timeout = min(default_timeout, query_timeout) + actual_timeout = min(default_timeout, query_timeout) elif max_request_timeout is not None and query_timeout is None: # Max, no user query: Default except if above max - self.actual_timeout = min(default_timeout, max_request_timeout) + actual_timeout = min(default_timeout, max_request_timeout) elif max_request_timeout is not None and query_timeout is not None: # Max & user query: From user query except if above max - self.actual_timeout = min(query_timeout, max_request_timeout) + actual_timeout = min(query_timeout, max_request_timeout) logger.debug("actual_timeout={0} (default_timeout={1}, ?timeout_limit={2}, max_request_timeout={3})" .format(self.actual_timeout, default_timeout, query_timeout, max_request_timeout)) + return requests, actual_timeout + + def search_standard(self): + """ + Update self.result_container, self.actual_timeout + """ + requests, self.actual_timeout = self._get_requests() + # send all search-request if requests: - search_multiple_requests(requests, self.result_container, start_time, self.actual_timeout) + search_multiple_requests(requests, self.result_container, self.start_time, self.actual_timeout) start_new_thread(gc.collect, tuple()) # return results, suggestions, answers and infoboxes + return True + + # do search-request + def search(self): + self.start_time = time() + + if not self.search_external_bang(): + if not self.search_answerers(): + self.search_standard() + return self.result_container