| 
									
										
										
										
											2021-01-13 11:31:25 +01:00
										 |  |  | # SPDX-License-Identifier: AGPL-3.0-or-later | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  |  Wolfram|Alpha (Science) | 
					
						
							|  |  |  | """
 | 
					
						
							| 
									
										
										
										
											2015-12-30 03:59:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-30 07:53:15 +01:00
										 |  |  | from json import loads | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  | from time import time | 
					
						
							| 
									
										
										
										
											2020-08-06 17:42:46 +02:00
										 |  |  | from urllib.parse import urlencode | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												[httpx] replace searx.poolrequests by searx.network
settings.yml:
* outgoing.networks:
   * can contains network definition
   * propertiers: enable_http, verify, http2, max_connections, max_keepalive_connections,
     keepalive_expiry, local_addresses, support_ipv4, support_ipv6, proxies, max_redirects, retries
   * retries: 0 by default, number of times searx retries to send the HTTP request (using different IP & proxy each time)
   * local_addresses can be "192.168.0.1/24" (it supports IPv6)
   * support_ipv4 & support_ipv6: both True by default
     see https://github.com/searx/searx/pull/1034
* each engine can define a "network" section:
   * either a full network description
   * either reference an existing network
* all HTTP requests of engine use the same HTTP configuration (it was not the case before, see proxy configuration in master)
											
										 
											2021-04-05 10:43:33 +02:00
										 |  |  | from searx.network import get as http_get | 
					
						
							| 
									
										
										
										
											2015-12-30 03:59:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-13 11:31:25 +01:00
										 |  |  | # about | 
					
						
							|  |  |  | about = { | 
					
						
							|  |  |  |     "website": 'https://www.wolframalpha.com/', | 
					
						
							|  |  |  |     "wikidata_id": 'Q207006', | 
					
						
							|  |  |  |     "official_api_documentation": 'https://products.wolframalpha.com/api/', | 
					
						
							|  |  |  |     "use_official_api": False, | 
					
						
							|  |  |  |     "require_api_key": False, | 
					
						
							|  |  |  |     "results": 'JSON', | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-30 03:59:51 +01:00
										 |  |  | # search-url | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  | url = 'https://www.wolframalpha.com/' | 
					
						
							| 
									
										
										
										
											2016-01-02 08:49:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 09:26:22 +01:00
										 |  |  | search_url = ( | 
					
						
							|  |  |  |     url + 'input/json.jsp' | 
					
						
							|  |  |  |     '?async=false' | 
					
						
							|  |  |  |     '&banners=raw' | 
					
						
							|  |  |  |     '&debuggingdata=false' | 
					
						
							|  |  |  |     '&format=image,plaintext,imagemap,minput,moutput' | 
					
						
							|  |  |  |     '&formattimeout=2' | 
					
						
							|  |  |  |     '&{query}' | 
					
						
							|  |  |  |     '&output=JSON' | 
					
						
							|  |  |  |     '&parsetimeout=2' | 
					
						
							|  |  |  |     '&proxycode={token}' | 
					
						
							|  |  |  |     '&scantimeout=0.5' | 
					
						
							|  |  |  |     '&sponsorcategories=true' | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  |     '&statemethod=deploybutton' | 
					
						
							| 
									
										
										
										
											2021-12-27 09:26:22 +01:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 02:06:44 +01:00
										 |  |  | referer_url = url + 'input/?{query}' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 09:26:22 +01:00
										 |  |  | token = {'value': '', 'last_updated': None} | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 02:06:44 +01:00
										 |  |  | # pods to display as image in infobox | 
					
						
							|  |  |  | # this pods do return a plaintext, but they look better and are more useful as images | 
					
						
							| 
									
										
										
										
											2021-12-27 09:26:22 +01:00
										 |  |  | image_pods = {'VisualRepresentation', 'Illustration', 'Symbol'} | 
					
						
							| 
									
										
										
										
											2016-02-28 02:06:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | # seems, wolframalpha resets its token in every hour | 
					
						
							|  |  |  | def obtain_token(): | 
					
						
							|  |  |  |     update_time = time() - (time() % 3600) | 
					
						
							| 
									
										
										
										
											2016-02-17 17:21:54 +01:00
										 |  |  |     try: | 
					
						
							|  |  |  |         token_response = http_get('https://www.wolframalpha.com/input/api/v1/code?ts=9999999999999999999', timeout=2.0) | 
					
						
							|  |  |  |         token['value'] = loads(token_response.text)['code'] | 
					
						
							|  |  |  |         token['last_updated'] = update_time | 
					
						
							|  |  |  |     except: | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  |     return token | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-23 17:14:32 +02:00
										 |  |  | def init(engine_settings=None): | 
					
						
							| 
									
										
										
										
											2017-06-06 22:20:20 +02:00
										 |  |  |     obtain_token() | 
					
						
							| 
									
										
										
										
											2015-12-30 03:59:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # do search-request | 
					
						
							|  |  |  | def request(query, params): | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  |     # obtain token if last update was more than an hour | 
					
						
							| 
									
										
										
										
											2016-11-30 18:43:03 +01:00
										 |  |  |     if time() - (token['last_updated'] or 0) > 3600: | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  |         obtain_token() | 
					
						
							|  |  |  |     params['url'] = search_url.format(query=urlencode({'input': query}), token=token['value']) | 
					
						
							| 
									
										
										
										
											2016-02-28 02:06:44 +01:00
										 |  |  |     params['headers']['Referer'] = referer_url.format(query=urlencode({'i': query})) | 
					
						
							| 
									
										
										
										
											2015-12-30 03:59:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return params | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-30 04:11:49 +01:00
										 |  |  | # get response from search-request | 
					
						
							|  |  |  | def response(resp): | 
					
						
							| 
									
										
										
										
											2016-02-28 02:06:44 +01:00
										 |  |  |     results = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  |     resp_json = loads(resp.text) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not resp_json['queryresult']['success']: | 
					
						
							|  |  |  |         return [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # TODO handle resp_json['queryresult']['assumptions'] | 
					
						
							|  |  |  |     result_chunks = [] | 
					
						
							| 
									
										
										
										
											2016-07-08 01:41:33 +02:00
										 |  |  |     infobox_title = "" | 
					
						
							|  |  |  |     result_content = "" | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  |     for pod in resp_json['queryresult']['pods']: | 
					
						
							| 
									
										
										
										
											2016-02-28 07:47:36 +01:00
										 |  |  |         pod_id = pod.get('id', '') | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  |         pod_title = pod.get('title', '') | 
					
						
							| 
									
										
										
										
											2016-07-07 00:29:40 +02:00
										 |  |  |         pod_is_result = pod.get('primary', None) | 
					
						
							| 
									
										
										
										
											2016-02-28 02:06:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  |         if 'subpods' not in pod: | 
					
						
							| 
									
										
										
										
											2016-02-28 09:05:52 +01:00
										 |  |  |             continue | 
					
						
							| 
									
										
										
										
											2016-02-28 02:06:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 07:47:36 +01:00
										 |  |  |         if pod_id == 'Input' or not infobox_title: | 
					
						
							|  |  |  |             infobox_title = pod['subpods'][0]['plaintext'] | 
					
						
							| 
									
										
										
										
											2016-02-28 02:06:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  |         for subpod in pod['subpods']: | 
					
						
							| 
									
										
										
										
											2016-02-28 07:47:36 +01:00
										 |  |  |             if subpod['plaintext'] != '' and pod_id not in image_pods: | 
					
						
							| 
									
										
										
										
											2016-02-28 02:06:44 +01:00
										 |  |  |                 # append unless it's not an actual answer | 
					
						
							|  |  |  |                 if subpod['plaintext'] != '(requires interactivity)': | 
					
						
							|  |  |  |                     result_chunks.append({'label': pod_title, 'value': subpod['plaintext']}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-08 01:41:33 +02:00
										 |  |  |                 if pod_is_result or not result_content: | 
					
						
							|  |  |  |                     if pod_id != "Input": | 
					
						
							|  |  |  |                         result_content = pod_title + ': ' + subpod['plaintext'] | 
					
						
							| 
									
										
										
										
											2016-07-07 00:29:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-28 02:06:44 +01:00
										 |  |  |             elif 'img' in subpod: | 
					
						
							|  |  |  |                 result_chunks.append({'label': pod_title, 'image': subpod['img']}) | 
					
						
							| 
									
										
										
										
											2016-02-17 17:07:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if not result_chunks: | 
					
						
							|  |  |  |         return [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-27 09:26:22 +01:00
										 |  |  |     results.append( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             'infobox': infobox_title, | 
					
						
							|  |  |  |             'attributes': result_chunks, | 
					
						
							|  |  |  |             'urls': [{'title': 'Wolfram|Alpha', 'url': resp.request.headers['Referer']}], | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     results.append( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             'url': resp.request.headers['Referer'], | 
					
						
							|  |  |  |             'title': 'Wolfram|Alpha (' + infobox_title + ')', | 
					
						
							|  |  |  |             'content': result_content, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2016-02-28 02:06:44 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return results |