-
Notifications
You must be signed in to change notification settings - Fork 1
Библиотека python FuzzyWuzzy для нечеткого сравнения текста
Alexander Davydov edited this page Dec 3, 2020
·
2 revisions
pip install fuzzywuzzy
pip install python-Levenshtein
from fuzzywuzzy import fuzz
a = fuzz.ratio('Привет мир', 'Привет мир')
print(a)
#Выводит в консоль: 100
Если мы изменим пару символов:
a = fuzz.ratio('Привет мир', 'Привт кир')
print(a)
#Выводит в консоль: 84
Данный вид сравнения во всей второй строке ищет совпадение с начальной, например:
a = fuzz.partial_ratio('Привет мир', 'Привет мир!')
print(a)
#Выводит в консоль: 100
Но следует помнить про регистр, так как
a = fuzz.partial_ratio('Привет мир', 'Люблю колбасу, привет мир')
print(a)
#Выводит в консоль: 90
1) Token Sort Ratio
Слова сравниваются друг с другом, независимо от регистра или порядка
a = fuzz.token_sort_ratio('Привет наш мир', 'мир наш Привет')
print(a)
#Выводит в консоль: 100
a = fuzz.token_sort_ratio('Привет наш мир', 'мир наш любимый Привет')
print(a)
#Выводит в консоль: 78
a = fuzz.token_sort_ratio('1 2 Привет наш мир', '1 мир наш 2 ПриВЕт')
print(a)
#Выводит в консоль: 100
2) Token Set Ratio
Это сравнение, в отличие от прошлого, приравнивает строки, если их отличие заключается в повторении слов.
a = fuzz.token_set_ratio('Привет наш мир', 'мир мир наш наш наш ПриВЕт')
print(a)
#Выводит в консоль: 100
Во многих случаях более целесообразно использовать именно WRatio, так как оно учитывает регистр букв и знаки препинания (не делящие строку)
a = fuzz.WRatio('Привет наш мир', '!ПриВЕт наш мир!')
print(a)
#Выводит в консоль: 100
a = fuzz.WRatio('Привет наш мир', '!ПриВЕт, наш мир!')
print(a)
#Выводит в консоль: 97
Примечание: Функция fuzz.WRatio используется для сравнения двух текстов в текущем проекте. Принцип ее работы будет детально рассмотрен ниже
Прототип данной функции приведен ниже:
def WRatio(s1, s2, force_ascii=True, full_process=True):
- s1, s2 - строки на сравнение
- force_ascii - разрешить только ascii символы
- full_process - входные данные процесса, используемые здесь, чтобы избежать двойной обработки в функциях извлечения
Алгоритм работы функции:
- Запуск
full_processизutilsв обеих строках в зависимости от параметра
if full_process:
p1 = utils.full_process(s1, force_ascii=force_ascii)
p2 = utils.full_process(s2, force_ascii=force_ascii)
else:
p1 = s1
p2 = s2
- Короткое замыкание, если метод
utils.validateделает любую строку пустой
if not utils.validate_string(p1):
return 0
if not utils.validate_string(p2):
return 0
- Берем соотношение двух обработанных строк
s1,s2, методомfuzz.wratio- обычное сравнение.
base = ratio(p1, p2)
- Берем соотношение длины строк
len_ratio = float(max(len(p1), len(p2))) / min(len(p1), len(p2))
- В зависимости от длины строк производим дальнейшую обработку
try_partial = True
unbase_scale = .95
partial_scale = .90
- Если одна из строк более чем в 1.5 раза длиннее другой - использовать
fuzz.partial_ratio, результаты масштабировать на 0.9 (это гарантирует, что только полные результаты могут вернуть 100)
if try_partial:
partial = partial_ratio(p1, p2) * partial_scale
ptsor = partial_token_sort_ratio(p1, p2, full_process=False) \
* unbase_scale * partial_scale
ptser = partial_token_set_ratio(p1, p2, full_process=False) \
* unbase_scale * partial_scale
- Если одна из строк более чем в 8 раз длиннее другой, вместо этого масштабируем результаты на 0.6
if len_ratio > 8:
partial_scale = .6
if try_partial:
partial = partial_ratio(p1, p2) * partial_scale
ptsor = partial_token_sort_ratio(p1, p2, full_process=False) \
* unbase_scale * partial_scale
ptser = partial_token_set_ratio(p1, p2, full_process=False) \
* unbase_scale * partial_scale
- Запуск других функций соотношения
- При использовании функции частичного отношения - вызов
partial_ratio,partial_token_sort_ratioиpartial_token_set_ratioмасштабируйте все это по отношению к длине - В противном случае вызовите
token_sort_ratioиtoken_set_ratio - Все сравнения на основе токенов масштабируются на 0,95 (поверх любых частичных скаляров)
- Получаем максимальную отдачу от полученных результатов, округляем их и возвращаем как целое число
return utils.intr(max(base, tsor, tser))