Время прочтения: 3 мин.

При подготовке различной текстовой документации, договоров, отчётов и т.д. важно соблюдать правописание. Используемые в настоящее время программные средства, в частности MS Office Word, подсвечивают слова, в которых допущены ошибки. Это очень удобно и, что немаловажно, наглядно.

Но нам может понадобиться автоматизировать обнаружение ошибок в текстах при отсутствии упомянутых выше программных средств. Либо, при их наличии, делать это, не открывая документ/множество документов. Или же искомый текст может быть попросту очень длинным, его проверка займёт много времени.

На помощь приходят небезызвестный язык программирования Python и модуль pyenchant, который не только позволяет проверять правописание слов, но и предлагает варианты исправления.

Для установки модуля используется стандартная команда:

 pip install pyenchant 

Код для проверки правописания слова довольно прост:

import enchant  # при импроте пишем именно enchant (не pyenchant)   
dictionary = enchant.Dict("en_US")
print(dictionary.check("driver"))

Вывод: True

Намеренно допустим ошибку в проверяемом слове:

print(dictionary.check("draiver"))

Вывод: False

Мы можем вывести список возможных исправлений слова:

print(dictionary.suggest(u"draiver"))

Вывод: [‘driver’, ‘drainer’, ‘Rivera’]

Читатель скорее всего заинтересуется, предоставляет ли модуль возможность проверять правописание слов русского языка, и ответ – да. Однако, по умолчанию это недоступно, нам нужен словарь.  Он может быть найден, например, в пакете LibreOffice по пути его установки:

«…\LibreOffice\share\extensions\dict-ru»

Здесь нам нужны два файла: «ru_RU.aff» и «ru_RU.dic». Их необходимо разместить в папке модуля enchant, где хранятся словари для других языков по пути

C:\...\Python\Python36\site-packages\enchant\data\mingw64\share\enchant\hunspell»

Теперь, при создании объекта Dict достаточно передать строку «ru_RU», и мы сможем работать со словами русского языка.

Вернёмся к нашему примеру с ошибочно написанным словом driver. При помощи метода suggest() мы получили список возможных исправлений, и вручную мы конечно же легко сможем выбрать нужный вариант.

Но что, если мы хотим автоматизировать и этот процесс?

Давайте использовать модуль Python difflib, который позволяет сравнивать строковые последовательности. Попробуем выбрать из списка слово «driver»:

import enchant
import difflib

woi = "draiver" 
sim = dict() 

dictionary = enchant.Dict("en_US")
suggestions = set(dictionary.suggest(woi))

for word in suggestions:
    measure = difflib.SequenceMatcher(None, woi, word).ratio()
    sim[measure] = word

print("Correct word is:", sim[max(sim.keys())])

Немного прокомментируем код. В словаре sim будут храниться значения степеней сходства (диапазон от 0 до 1) предложенных методом suggest() класса Dict слов с искомым словом («draiver»). Данные значения мы получаем в цикле при вызове метода ratio() класса SequenceMatcher и записываем в словарь. В конце получаем слово, которое максимально близко к проверяемому.

Вывод: Correct word is driver

Выше мы работали с отдельными словами, но будет полезно разобраться, как работать с целыми блоками текста. Для этой задачи нужно использовать класс SpellChecker:

from enchant.checker import SpellChecker

checker = SpellChecker("en_US")
checker.set_text("I have got a new kar and it is ameizing.")
print([i.word for i in checker])

Вывод: [‘kar’, ‘ameizing’]

Как видно, это не сложнее работы с отдельными словами. Кроме того, класс SpellChecker предоставляет возможность использовать фильтры, которые будут игнорировать особые последовательности, не являющиеся ошибочными, например, адрес электронной почты. Для этого необходимо импортировать класс или классы фильтров, если их несколько, и передать список фильтров параметру filters классу SpellChecker:

from enchant.checker import SpellChecker
from enchant.tokenize import EmailFilter, URLFilter

checker_with_filters = SpellChecker("en_US", filters=[EmailFilter])
checker_with_filters.set_text("Hi! My neim is John and thiz is my email: johnnyhatesjazz@gmail.com.")
print([i.word for i in checker_with_filters])

Вывод: [‘neim’, ‘thiz’]

Как видно, адрес электронной почты не был выведен в качестве последовательности, содержащей ошибки в правописании.

Таким образом, комбинируя возможности модулей enchant и difflib, мы можем получить действительно мощный инструмент, позволяющий не только обнаруживать ошибки, но и подбирать варианты исправления с довольно высокой точностью, а также вносить эти исправления в текст.