Skip to content

Библиотека python FuzzyWuzzy для нечеткого сравнения текста

Alexander Davydov edited this page Dec 3, 2020 · 2 revisions

Установка

pip install fuzzywuzzy
pip install python-Levenshtein

Импорт в проект

from fuzzywuzzy import fuzz

Функционал FuzzyWuzzy

Самое обычное сравнение:

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 используется для сравнения двух текстов в текущем проекте. Принцип ее работы будет детально рассмотрен ниже

Смотрим под капот функции fuzz.WRatio

Прототип данной функции приведен ниже:

def WRatio(s1, s2, force_ascii=True, full_process=True):
  • s1, s2 - строки на сравнение
  • force_ascii - разрешить только ascii символы
  • full_process - входные данные процесса, используемые здесь, чтобы избежать двойной обработки в функциях извлечения

Алгоритм работы функции:

  1. Запуск 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
  1. Короткое замыкание, если метод utils.validate делает любую строку пустой
if not utils.validate_string(p1):
return 0
if not utils.validate_string(p2):
return 0
  1. Берем соотношение двух обработанных строк s1, s2, методом fuzz.wratio - обычное сравнение.
base = ratio(p1, p2)
  1. Берем соотношение длины строк
len_ratio = float(max(len(p1), len(p2))) / min(len(p1), len(p2))
  1. В зависимости от длины строк производим дальнейшую обработку
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
  1. Запуск других функций соотношения
  • При использовании функции частичного отношения - вызов partial_ratio, partial_token_sort_ratio и partial_token_set_ratio масштабируйте все это по отношению к длине
  • В противном случае вызовите token_sort_ratio и token_set_ratio
  • Все сравнения на основе токенов масштабируются на 0,95 (поверх любых частичных скаляров)
  1. Получаем максимальную отдачу от полученных результатов, округляем их и возвращаем как целое число
return utils.intr(max(base, tsor, tser))
Clone this wiki locally