Нечеткий текстовый поиск в python

мне интересно, есть ли библиотека Python, которая может проводить нечеткий текстовый поиск. Например:

  • у меня есть три ключевых слова "письма", "марки" и "письма".
  • Я хотел бы иметь функцию, чтобы проверить, если эти три слова в тот же абзац (или определенные расстояния, одна страница).
  • кроме того, эти слова должны поддерживать такой же порядок. Хорошо, что между ними появляются другие слова. эти три слова.

Я пробовал fuzzywuzzy что не решило мою проблему. Еще одна библиотека!--1--> выглядит мощным, но я не нашел правильной функции...

1 ответов


{1} Вы можете сделать это Whoosh 2.7. Он имеет нечеткий поиск, добавив плагин whoosh.qparser.FuzzyTermPlugin:

whoosh.qparser.FuzzyTermPlugin позволяет искать "нечеткие" термины, то есть термины, которые не должны точно совпадать. Нечеткий термин будет соответствовать любому аналогичному термину в пределах определенного количества " изменений "(вставки символов, удаления и/или транспозиции – это называется"расстоянием редактирования Дамерау-Левенштейна").

добавить нечеткий плагин:

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

после добавления нечеткого плагина в парсер вы можете указать нечеткий термин, добавив ~ с последующим дополнительным максимальным расстоянием редактирования. Если расстояние редактирования не указано, по умолчанию используется значение 1.

например, следующий "нечеткий" запрос термина:

letter~
letter~2
letter~2/3

{2} чтобы сохранить слова в порядке, используйте запрос whoosh.query.Phrase но вы должны заменить Phrase плагин whoosh.qparser.SequencePlugin что позволяет использовать fuzzy термины внутри фразы:

"letter~ stamp~ mail~"

чтобы заменить плагин фразы по умолчанию на плагин последовательности:

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

{3} разрешить слов, инициализации slop arg в вашем запросе фразы на большее число:

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

помои - количество слов, разрешенных между каждым "словом" во фразе; значение по умолчанию 1 означает, что фраза должна соответствовать точно.

вы также можете определите slop в запросе следующим образом:

"letter~ stamp~ mail~"~10

{4} общее разрешение:

{4.a} индексатор будет так:

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} Искатель будет так:

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

это дает результат:

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

{5} если вы хотите установить нечеткий поиск по умолчанию без использования синтаксиса word~n в каждом слове запрос, вы можете инициализировать QueryParser такой:

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

теперь вы можете использовать запрос "letter stamp mail"~10 но имейте в виду, что FuzzyTerm имеет расстояние редактирования по умолчанию maxdist = 1. Персонализируйте класс, если вы хотите увеличить расстояние редактирования:

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

ссылки:

  1. свист.запрос.Фраза
  2. добавление нечетких запросов терминов
  3. разрешение сложной фразы запросы
  4. свист класса.запрос.FuzzyTerm
  5. модуль qparser