on master help sign in
[enh] initial commit
commitae9fb1d7dccf061032b5d4b167086838feb1463d authorasciimoo <asciimoo@gmail.com> dateMon 14 Oct 2013, 23:09 (13 years ago)
11 files changed+139
.gitignore+2 README.md+4 requirements.txt+3 searx/__init__.py searx/engines/__init__.py+15 searx/engines/duckduckgo.py+14 searx/static/css/style.css searx/templates/base.html+17 searx/templates/index.html+8 searx/templates/results.html+7 searx/webapp.py+69
.gitignorenew file+2
@@ -0,0 +1,2 @@
1+env
2+searx.conf
README.mdnew file+4
@@ -0,0 +1,4 @@
1+searx
2+=====
3+
4+Minimalistic web interface to different search engines.
requirements.txtnew file+3
@@ -0,0 +1,3 @@
1+flask
2+grequests
3+lxml
searx/__init__.pynew file

No changes to the content.

searx/engines/__init__.pynew file+15
@@ -0,0 +1,15 @@
1+
2+from os.path import realpath, dirname, splitext, join
3+from os import listdir
4+from imp import load_source
5+
6+engine_dir = dirname(realpath(__file__))
7+
8+engines = []
9+
10+for filename in listdir(engine_dir):
11+ modname = splitext(filename)[0]
12+ if filename.startswith('_') or not filename.endswith('.py'):
13+ continue
14+ filepath = join(engine_dir, filename)
15+ engines.append(load_source(modname, filepath))
searx/engines/duckduckgo.pynew file+14
@@ -0,0 +1,14 @@
1+from lxml import html
2+
3+
4+def request(query, params):
5+ params['method'] = 'POST'
6+ params['url'] = 'https://duckduckgo.com/html'
7+ params['data']['q'] = query
8+ return params
9+
10+
11+def response(resp):
12+ dom = html.fromstring(resp.text)
13+ results = dom.xpath('//div[@class="results_links results_links_deep web-result"]')
14+ return [html.tostring(x) for x in results]
searx/static/css/style.cssnew file

No changes to the content.

searx/templates/base.htmlnew file+17
@@ -0,0 +1,17 @@
1+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
3+<head>
4+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
5+ <meta http-equiv="content-language" content="en" />
6+ <meta name="description" content="" />
7+ <meta name="keywords" content="" />
8+ <title>searx {% block title %}{% endblock %}</title>
9+ <link rel="stylesheet" href="/static/css/style.css" type="text/css" media="screen" charset="utf-8" />
10+ {% block styles %}
11+ {% endblock %}
12+</head>
13+<body>
14+{% block content %}
15+{% endblock %}
16+</body>
17+</html>
searx/templates/index.htmlnew file+8
@@ -0,0 +1,8 @@
1+{% extends "base.html" %}
2+{% block content %}
3+<h1>searx</h1>
4+<form method="post" action="">
5+ <input type="text" name="q" />
6+ <input type="submit" value="search" />
7+</form>
8+{% endblock %}
searx/templates/results.htmlnew file+7
@@ -0,0 +1,7 @@
1+{% extends "base.html" %}
2+{% block content %}
3+<h1>searx</h1>
4+{% for result in results %}
5+ <p>{{ result|safe }}</p>
6+{% endfor %}
7+{% endblock %}
searx/webapp.pynew file+69
@@ -0,0 +1,69 @@
1+#!/usr/bin/env python
2+
3+if __name__ == "__main__":
4+ from sys import path
5+ from os.path import realpath, dirname
6+ path.append(realpath(dirname(realpath(__file__))+'/../'))
7+
8+from flask import Flask, request, flash, render_template
9+import ConfigParser
10+from os import getenv
11+from searx.engines import engines
12+import grequests
13+
14+cfg = ConfigParser.SafeConfigParser()
15+cfg.read('/etc/searx.conf')
16+cfg.read(getenv('HOME')+'/.searxrc')
17+cfg.read(getenv('HOME')+'/.config/searx/searx.conf')
18+cfg.read('searx.conf')
19+
20+
21+app = Flask(__name__)
22+app.secret_key = cfg.get('app', 'secret_key')
23+
24+def default_request_params():
25+ return {'method': 'GET', 'headers': {}, 'data': {}, 'url': ''}
26+
27+def make_callback(results, callback):
28+ def process_callback(response, **kwargs):
29+ results.extend(callback(response))
30+ return process_callback
31+
32+@app.route('/', methods=['GET', 'POST'])
33+def index():
34+ if request.method=='POST':
35+ if not request.form.get('q'):
36+ flash('Wrong post data')
37+ return render_template('index.html')
38+ query = request.form['q']
39+ requests = []
40+ results = []
41+ for engine in engines:
42+ request_params = engine.request(query, default_request_params())
43+ callback = make_callback(results, engine.response)
44+ if request_params['method'] == 'GET':
45+ req = grequests.get(request_params['url']
46+ ,headers=request_params['headers']
47+ ,hooks=dict(response=callback)
48+ )
49+ else:
50+ req = grequests.post(request_params['url']
51+ ,data=request_params['data']
52+ ,headers=request_params['headers']
53+ ,hooks=dict(response=callback)
54+ )
55+ requests.append(req)
56+ grequests.map(requests)
57+ return render_template('results.html', results=results)
58+
59+
60+ return render_template('index.html')
61+
62+if __name__ == "__main__":
63+ from gevent import monkey
64+ monkey.patch_all()
65+
66+ app.run(debug = cfg.get('server', 'debug')
67+ ,use_debugger = cfg.get('server', 'debug')
68+ ,port = int(cfg.get('server', 'port'))
69+ )