Нечеткий текстовый поиск в 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
ссылки: