2015-05-26 23 views
6

Mi chiedo se ci sia una libreria Python in grado di condurre ricerche di testo sfocate. Per esempio:Ricerca testo sfocata in python

  • Ho tre parole chiave "lettera", "timbro", e "posta".
  • Mi piacerebbe avere una funzione per verificare se quelle tre parole sono all'interno dello stesso paragrafo (o certe distanze, una pagina).
  • Inoltre, queste parole devono mantenere lo stesso ordine. Va bene che altre parole appaiano tra quelle tre parole.

Ho provato fuzzywuzzy che non ha risolto il mio problema. Un'altra libreria Whoosh sembra potente, ma non ho trovato il corretto funzionamento ...

+0

vedere se questo collegamento aiuta: http://stackoverflow.com/questions/2923420/what-is-a-simple-fuzzy-string-matching-algorithm-in-python –

+0

@JosephSeungJaeDollar grazie per il commento. Ho controllato quel post, ma non ha risolto il mio problema. –

risposta

16

{1} È possibile farlo in Whoosh 2.7. Ha ricerca fuzzy aggiungendo il plugin whoosh.qparser.FuzzyTermPlugin:

whoosh.qparser.FuzzyTermPlugin ti permette di cercare i termini “fuzzy”, cioè, termini che non devono corrispondere esattamente. Il termine fuzzy corrisponderà a qualsiasi termine simile all'interno di un certo numero di "modifiche" (inserimento di caratteri, delezioni e/o trasposizioni - questa è chiamata la "distanza di modifica di Damerau-Levenshtein").

Per aggiungere il plugin sfocata:

parser = qparser.QueryParser("fieldname", my_index.schema) 
parser.add_plugin(qparser.FuzzyTermPlugin()) 

Una volta aggiunto il plugin fuzzy per il parser, è possibile specificare un termine confuso con l'aggiunta di un ~ seguita da una distanza massima di modifica opzionale. Se non si specifica una distanza di modifica, il valore predefinito è 1.

Ad esempio, il seguente “fuzzy” interrogazione termine:

letter~ 
letter~2 
letter~2/3 

{2} Per mantenere parole in ordine , utilizzare la query whoosh.query.Phrase ma è necessario sostituire Phrase plugin whoosh.qparser.SequencePlugin che permette di utilizzare termini sfocati all'interno di una frase:

"letter~ stamp~ mail~" 

Per sostituire la frase predefinita plugin con il plug-in sequenza:

parser = qparser.QueryParser("fieldname", my_index.schema) 
parser.remove_plugin_class(qparser.PhrasePlugin) 
parser.add_plugin(qparser.SequencePlugin()) 

{3} Per consentire parole tra, inizializzare il slop arg nella query frase per un numero maggiore:

whoosh.query.Phrase(fieldname, words, slop=1, boost=1.0, char_ranges=None) 

slop - il numero di parole consentito tra ogni "parola" nella frase; il valore predefinito di 1 indica che la frase deve corrispondere esattamente.

È inoltre possibile definire slop in Query come questo:

"letter~ stamp~ mail~"~10 

{4} soluzione complessiva:

{} 4.aindicizzatore sarebbe Mi piace:

from whoosh.index import create_in 
from whoosh.fields import * 

schema = Schema(title=TEXT(stored=True), content=TEXT) 
ix = create_in("indexdir", schema) 
writer = ix.writer() 
writer.add_document(title=u"First document", content=u"This is the first document we've added!") 
writer.add_document(title=u"Second document", content=u"The second one is even more interesting!") 
writer.add_document(title=u"Third document", content=u"letter first, stamp second, mail third") 
writer.add_document(title=u"Fourth document", content=u"stamp first, mail third") 
writer.add_document(title=u"Fivth document", content=u"letter first, mail third") 
writer.add_document(title=u"Sixth document", content=u"letters first, stamps second, mial third wrong") 
writer.add_document(title=u"Seventh document", content=u"stamp first, letters second, mail third") 
writer.commit() 

{} 4.bRicercatore sarebbe come:

from whoosh.qparser import QueryParser, FuzzyTermPlugin, PhrasePlugin, SequencePlugin 

with ix.searcher() as searcher: 
    parser = QueryParser(u"content", ix.schema) 
    parser.add_plugin(FuzzyTermPlugin()) 
    parser.remove_plugin_class(PhrasePlugin) 
    parser.add_plugin(SequencePlugin()) 
    query = parser.parse(u"\"letter~2 stamp~2 mail~2\"~10") 
    results = searcher.search(query) 
    print "nb of results =", len(results) 
    for r in results: 
     print r 

che dà il risultato:

nb of results = 2 
<Hit {'title': u'Sixth document'}> 
<Hit {'title': u'Third document'}> 

{5} Se si desidera impostare ricerca fuzzy come predefinita senza utilizzare la sintassi word~n in ogni parola della query, è possibile inizializzare QueryParser come questo:

from whoosh.query import FuzzyTerm 
parser = QueryParser(u"content", ix.schema, termclass = FuzzyTerm) 

Ora è possibile utilizzare la query "letter stamp mail"~10 ma di tenere presente che FuzzyTerm ha predefinita Modifica distanza maxdist = 1. Personalizzare la classe, se si desidera modificare più grande distanza:

class MyFuzzyTerm(FuzzyTerm): 
    def __init__(self, fieldname, text, boost=1.0, maxdist=2, prefixlength=1, constantscore=True): 
     super(D, self).__init__(fieldname, text, boost, maxdist, prefixlength, constantscore) 
     # super().__init__() for Python 3 I think 

Riferimenti:

  1. whoosh.query.Phrase
  2. Adding fuzzy term queries
  3. Allowing complex phrase queries
  4. class whoosh.query.FuzzyTerm
  5. qparser module
+0

Wow, grazie mille per aver scritto questo esempio indipendente! Apprezzo davvero il tuo aiuto! –