#!/usr/bin/python2.6 # coding: utf-8 import os import json from StringIO import StringIO from whoosh.index import open_dir from whoosh.qparser import QueryParser import whoosh.searching as searching import whoosh.fields as fields import whoosh.analysis as analysis import whoosh.highlight as highlight import whoosh.query as query import flask import pyPdf import werkzeug import subprocess app = flask.Flask("booksearch") index_book = open_dir(u"index", u"book") index_metadata = open_dir(u"index", u"metadata") @app.route("/") def do_index(): return flask.redirect(flask.url_for("do_search",term="")) @app.route("/download/file/") def do_download_file(docnum): document = index.reader().stored_fields(docnum) r = werkzeug.Response(open(document['path'], "r"), mimetype="application/pdf",) r.headers.add('Content-Disposition', 'attachment', filename=os.path.basename(document['path'])) return r @app.route("/download/image/", methods=["GET"]) @app.route("/download/image//", methods=["GET"]) def do_download_image(docnum,page=0): def generator(process, input): input.seek(0) while not process.stdin.closed: stdout, stderr = process.communicate(input.read()) if stdout: yield stdout with index_metadata.reader() as reader: document = reader.stored_fields(docnum) filepath = document['path'] pdffile = StringIO() page = pyPdf.PdfFileReader(file(filepath, 'r')).getPage(page) out = pyPdf.PdfFileWriter() out.addPage(page) out.write(pdffile) process = subprocess.Popen(["/usr/bin/convert", "pdf:-", "jpeg:-"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) return werkzeug.Response(generator(process,pdffile), mimetype="image/jpeg") @app.route("/download/page//", methods=["GET"]) def do_download_page(docnum,page): document = index.reader().stored_fields(docnum) inputfile = pyPdf.PdfFileReader(file(document['path'], 'r')) page = inputfile.getPage(page) outbuf = StringIO() outfile = pyPdf.PdfFileWriter() outfile.addPage(page) outfile.write(outbuf) outbuf.seek(0) r = werkzeug.Response(outbuf, mimetype="application/pdf") client_filename = os.path.basename(document['path'])[:-3] client_filename += u".Page-{0}".format(document['pagenumber']) r.headers.add('Content-Disposition', 'attachment', filename=client_filename) return r class MyHtmlFormatter(highlight.HtmlFormatter): def _format_fragment(self, text, fragment, seen): text = unicode( flask.Markup.escape(text) ) return highlight.HtmlFormatter._format_fragment(self, text, fragment, seen) @app.route("/json/excerpt//", methods=["GET"]) def json_excerpt(docnum, term): searcher = index.searcher() def generator(q): for result in searcher.search(q, limit=1, sortedby="pagenumber"): terms = [ text for fieldname, text in q.all_terms() if fieldname == "content" ] excerpt = highlight.highlight(result.get("content"), terms, analysis.FancyAnalyzer(), highlight.SimpleFragmenter(), MyHtmlFormatter()) yield json.dumps( { 'pagenumber':result.get("pagenumber"), 'excerpt':excerpt, 'docnum':result.docnum} ) document = searcher.reader().stored_fields(docnum) q = QueryParser("content").parse(term) q = query.And([ q, query.Term("path", document['path']) ] ) return werkzeug.Response( generator(q) ) @app.route("/search/skip=/",methods=["GET"]) @app.route("/search/",methods=["GET"]) @app.route("/search/", methods=["GET"]) def do_search(skip=0,term=None): if skip == 0 and not term: return flask.render_template('search.html', objects=[], term="", skip=0) searcher = index_book.searcher() query = QueryParser("content").parse(term) facets = searching.Facets.from_field(searcher, "path") results = searcher.search(query, limit=None) categories = facets.categorize(results).items() searcher.close() matches = {} for book in categories: filepath = book[0] with index_metadata.searcher() as searcher: docnum = searcher.document_number(path=filepath) matches[docnum] = [] for match in book[1]: matches[docnum].append(match) return flask.render_template('search.html', matches=matches, term=term) """ terms = [text for fieldname, text in query.all_terms() if fieldname == "content"] matches = [] for result in results: title = result.get("title") path = result.get("path") excerpt = highlight.highlight(result.get("content"), terms, analysis.StandardAnalyzer(), highlight.SimpleFragmenter(), MyHtmlFormatter()) matches.append( {'path':result.get('path'), 'excerpt':excerpt, 'docnum':result.docnum, 'pagenumber':result.get('pagenumber'), 'title':title }) match_groups = {} for match in matches: print match if not match_groups.has_key(match['path']): match_groups[match['path']] = { 'matches':[], 'title' : match['title'], 'first_docnum' : match['docnum'], 'filename':os.path.basename(match['path']) } match_groups[ match['path'] ]['matches'].append( { 'excerpt':match['excerpt'], 'docnum':match['docnum'], 'pagenumber':match['pagenumber'] }) objects = match_groups.values()[skip:skip+5] return flask.render_template('search.html', match_groups=objects, term=term, skip=skip, resultlen=len(results)) """ if __name__ == "__main__": app.debug = True app.run(host="0.0.0.0")