summaryrefslogtreecommitdiff
path: root/searx/engines
diff options
context:
space:
mode:
Diffstat (limited to 'searx/engines')
-rw-r--r--searx/engines/wolframalpha_api.py23
-rw-r--r--searx/engines/wolframalpha_noapi.py83
2 files changed, 97 insertions, 9 deletions
diff --git a/searx/engines/wolframalpha_api.py b/searx/engines/wolframalpha_api.py
index d61d25747..540d81351 100644
--- a/searx/engines/wolframalpha_api.py
+++ b/searx/engines/wolframalpha_api.py
@@ -14,7 +14,11 @@ from lxml import etree
# search-url
base_url = 'http://api.wolframalpha.com/v2/query'
search_url = base_url + '?appid={api_key}&{query}&format=plaintext'
-api_key = ''
+api_key = '' # defined in settings.yml
+
+# xpath variables
+failure_xpath = '/queryresult[attribute::success="false"]'
+answer_xpath = '//pod[attribute::primary="true"]/subpod/plaintext'
# do search-request
@@ -45,16 +49,17 @@ def response(resp):
search_results = etree.XML(resp.content)
# return empty array if there are no results
- if search_results.xpath('/queryresult[attribute::success="false"]'):
+ if search_results.xpath(failure_xpath):
return []
- # parse result
- result = search_results.xpath('//pod[attribute::primary="true"]/subpod/plaintext')[0].text
- result = replace_pua_chars(result)
+ # parse answers
+ answers = search_results.xpath(answer_xpath)
+ if answers:
+ for answer in answers:
+ answer = replace_pua_chars(answer.text)
+
+ results.append({'answer': answer})
- # append result
- # TODO: shouldn't it bind the source too?
- results.append({'answer': result})
+ # TODO: append a result with title and link, like in the no api version
- # return results
return results
diff --git a/searx/engines/wolframalpha_noapi.py b/searx/engines/wolframalpha_noapi.py
new file mode 100644
index 000000000..0f0315630
--- /dev/null
+++ b/searx/engines/wolframalpha_noapi.py
@@ -0,0 +1,83 @@
+# WolframAlpha (Maths)
+#
+# @website http://www.wolframalpha.com/
+# @provide-api yes (http://api.wolframalpha.com/v2/)
+#
+# @using-api no
+# @results HTML
+# @stable no
+# @parse answer
+
+from re import search, sub
+from json import loads
+from urllib import urlencode
+from lxml import html
+import HTMLParser
+
+# search-url
+url = 'http://www.wolframalpha.com/'
+search_url = url+'input/?{query}'
+
+# xpath variables
+scripts_xpath = '//script'
+title_xpath = '//title'
+failure_xpath = '//p[attribute::class="pfail"]'
+
+
+# do search-request
+def request(query, params):
+ params['url'] = search_url.format(query=urlencode({'i': query}))
+
+ return params
+
+
+# get response from search-request
+def response(resp):
+ results = []
+ line = None
+
+ dom = html.fromstring(resp.text)
+ scripts = dom.xpath(scripts_xpath)
+
+ # the answer is inside a js function
+ # answer can be located in different 'pods', although by default it should be in pod_0200
+ possible_locations = ['pod_0200\.push(.*)\n',
+ 'pod_0100\.push(.*)\n']
+
+ # failed result
+ if dom.xpath(failure_xpath):
+ return results
+
+ # get line that matches the pattern
+ for pattern in possible_locations:
+ for script in scripts:
+ try:
+ line = search(pattern, script.text_content()).group(1)
+ break
+ except AttributeError:
+ continue
+ if line:
+ break
+
+ if line:
+ # extract answer from json
+ answer = line[line.find('{'):line.rfind('}')+1]
+ answer = loads(answer.encode('unicode-escape'))
+ answer = answer['stringified']
+
+ # clean plaintext answer
+ h = HTMLParser.HTMLParser()
+ answer = h.unescape(answer.decode('unicode-escape'))
+ answer = sub(r'\\', '', answer)
+
+ results.append({'answer': answer})
+
+ # user input is in first part of title
+ title = dom.xpath(title_xpath)[0].text
+ result_url = request(title[:-16], {})['url']
+
+ # append result
+ results.append({'url': result_url,
+ 'title': title})
+
+ return results