commit ae9fb1d7dccf061032b5d4b167086838feb1463d Author: asciimoo Date: Mon Oct 14 23:09:13 2013 +0200 [enh] initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ea93f950 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +env +searx.conf diff --git a/README.md b/README.md new file mode 100644 index 00000000..b2814764 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +searx +===== + +Minimalistic web interface to different search engines. diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..ed27ce9c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +flask +grequests +lxml diff --git a/searx/__init__.py b/searx/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/searx/engines/__init__.py b/searx/engines/__init__.py new file mode 100644 index 00000000..34d88b74 --- /dev/null +++ b/searx/engines/__init__.py @@ -0,0 +1,15 @@ + +from os.path import realpath, dirname, splitext, join +from os import listdir +from imp import load_source + +engine_dir = dirname(realpath(__file__)) + +engines = [] + +for filename in listdir(engine_dir): + modname = splitext(filename)[0] + if filename.startswith('_') or not filename.endswith('.py'): + continue + filepath = join(engine_dir, filename) + engines.append(load_source(modname, filepath)) diff --git a/searx/engines/duckduckgo.py b/searx/engines/duckduckgo.py new file mode 100644 index 00000000..ed93829b --- /dev/null +++ b/searx/engines/duckduckgo.py @@ -0,0 +1,14 @@ +from lxml import html + + +def request(query, params): + params['method'] = 'POST' + params['url'] = 'https://duckduckgo.com/html' + params['data']['q'] = query + return params + + +def response(resp): + dom = html.fromstring(resp.text) + results = dom.xpath('//div[@class="results_links results_links_deep web-result"]') + return [html.tostring(x) for x in results] diff --git a/searx/static/css/style.css b/searx/static/css/style.css new file mode 100644 index 00000000..e69de29b diff --git a/searx/templates/base.html b/searx/templates/base.html new file mode 100644 index 00000000..b1b051fa --- /dev/null +++ b/searx/templates/base.html @@ -0,0 +1,17 @@ + + + + + + + + searx {% block title %}{% endblock %} + + {% block styles %} + {% endblock %} + + +{% block content %} +{% endblock %} + + diff --git a/searx/templates/index.html b/searx/templates/index.html new file mode 100644 index 00000000..2905cbce --- /dev/null +++ b/searx/templates/index.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} +{% block content %} +

searx

+
+ + +
+{% endblock %} diff --git a/searx/templates/results.html b/searx/templates/results.html new file mode 100644 index 00000000..c7851461 --- /dev/null +++ b/searx/templates/results.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} +{% block content %} +

searx

+{% for result in results %} +

{{ result|safe }}

+{% endfor %} +{% endblock %} diff --git a/searx/webapp.py b/searx/webapp.py new file mode 100644 index 00000000..7c859d5d --- /dev/null +++ b/searx/webapp.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python + +if __name__ == "__main__": + from sys import path + from os.path import realpath, dirname + path.append(realpath(dirname(realpath(__file__))+'/../')) + +from flask import Flask, request, flash, render_template +import ConfigParser +from os import getenv +from searx.engines import engines +import grequests + +cfg = ConfigParser.SafeConfigParser() +cfg.read('/etc/searx.conf') +cfg.read(getenv('HOME')+'/.searxrc') +cfg.read(getenv('HOME')+'/.config/searx/searx.conf') +cfg.read('searx.conf') + + +app = Flask(__name__) +app.secret_key = cfg.get('app', 'secret_key') + +def default_request_params(): + return {'method': 'GET', 'headers': {}, 'data': {}, 'url': ''} + +def make_callback(results, callback): + def process_callback(response, **kwargs): + results.extend(callback(response)) + return process_callback + +@app.route('/', methods=['GET', 'POST']) +def index(): + if request.method=='POST': + if not request.form.get('q'): + flash('Wrong post data') + return render_template('index.html') + query = request.form['q'] + requests = [] + results = [] + for engine in engines: + request_params = engine.request(query, default_request_params()) + callback = make_callback(results, engine.response) + if request_params['method'] == 'GET': + req = grequests.get(request_params['url'] + ,headers=request_params['headers'] + ,hooks=dict(response=callback) + ) + else: + req = grequests.post(request_params['url'] + ,data=request_params['data'] + ,headers=request_params['headers'] + ,hooks=dict(response=callback) + ) + requests.append(req) + grequests.map(requests) + return render_template('results.html', results=results) + + + return render_template('index.html') + +if __name__ == "__main__": + from gevent import monkey + monkey.patch_all() + + app.run(debug = cfg.get('server', 'debug') + ,use_debugger = cfg.get('server', 'debug') + ,port = int(cfg.get('server', 'port')) + )