2015-05-26 26 views
6

Zastanawiam się, czy istnieje jakakolwiek biblioteka Pythona może przeprowadzać wyszukiwanie tekstu rozmytego. Na przykład:Wyszukiwanie tekstu rozmytego w pythonie

  • mam trzy słowa kluczowe "list", "pieczęć" i "Poczta".
  • Chciałbym mieć funkcję, aby sprawdzić, czy te trzy słowa są w tym samym akapicie w ciągu (lub pewne odległości, jedna strona).
  • Ponadto te słowa muszą zachować tę samą kolejność. Dobrze, że między tymi trzema słowami pojawiają się inne słowa.

Próbowałem fuzzywuzzy, który nie rozwiązał mojego problemu. Inna biblioteka Whoosh wygląda silny, ale nie mogę znaleźć właściwą funkcję ...

+0

Sprawdź, czy ten link pomoże: http://stackoverflow.com/questions/2923420/what-is-a-simple-fuzzy-string-matching-algorithm-in-python –

+0

@JosephSeungJaeDollar Dzięki za komentarz. Sprawdziłem ten post, ale to nie rozwiązało mojego problemu. –

Odpowiedz

16

{1} Można to zrobić w Whoosh 2.7. Ma rozmyty wyszukiwania poprzez dodanie wtyczki whoosh.qparser.FuzzyTermPlugin:

whoosh.qparser.FuzzyTermPlugin pozwala szukać „rozmytych” chodzi, to znaczy, że warunki nie muszą dokładnie odpowiadać. Termin rozmytania będzie pasował do dowolnego podobnego terminu w ramach pewnej liczby "edycji" (wstawiania, usuwania i/lub transpozycji postaci - to się nazywa "Odległość edytowania Damerau-Levenshtein").

Aby dodać wtyczkę rozmytej:

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

Po dodaniu wtyczki rozmytej do parsera, można określić termin rozmytej dodając ~ następnie opcjonalnie maksymalnej odległości edycji. Jeśli nie zostanie określony dystans edycji, domyślnie jest to 1.

Na przykład, następujący „rozmyta” query termin:

letter~ 
letter~2 
letter~2/3 

{2} Aby utrzymać słowa w kolejności użyj Query whoosh.query.Phrase ale należy zastąpić Phrase wtyczki przez whoosh.qparser.SequencePlugin który pozwala używać terminów rozmytych wewnątrz fraza:

"letter~ stamp~ mail~" 

Aby zastąpić domyślną frazę wtyczki z sekwencji plugin:

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

{3} aby umożliwić rozmowę między inicjować slop Arg w zapytaniu frazę do większej liczby:

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

slop - liczba słów dozwolonych między każdym "słowem" w wyrażeniu; wartość domyślna 1 oznacza, że ​​fraza musi dokładnie pasować.

Można również zdefiniować odstojnika w Query tak:

"letter~ stamp~ mail~"~10 

{4} Ogólnie rozwiązanie:

{4.a}Indexer byłoby na przykład:

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.b}Searcher byłoby jak:

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 

który daje wynik:

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

{5} Jeśli chcesz ustawić wyszukiwanie rozmyte jako domyślne bez użycia składni word~n w każdym słowie zapytania, można zainicjować QueryParser tak:

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

Teraz można użyć zapytania "letter stamp mail"~10 ale należy pamiętać, że FuzzyTerm ma domyślną edycji dystans maxdist = 1. Personalizacja klasy, jeśli chcesz większy edycji dystans:

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 

Referencje:

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

Wow, bardzo dziękuję za napisanie tego samodzielnego przykładu! Naprawdę doceniam twoją pomoc! –