Библиотеки Python. Часть 4. Морфология
Библиотека pymorphy2
Вы уже знаете стандартные строковые функции и пользовались ими. Мы умеем работать со строками посимвольно и знаем, как представляется текстовая информация. Давайте перейдем на уровень выше. Строка и текст в общем случае состоят не из набора букв, а из слов, и иногда нужно работать именно со словами, а не просто с последовательностями байтов.
Возьмем для примера склонение существительных с числительными. Например, на форуме надо написать, что в теме «21 комментарий», но «24 комментария». То же самое нужно делать и для других слов: например, «новость», «пользователь». Иногда на сайтах обходят эту проблему и вставляют машинное «комментариев: 21».
Довольно много статей на эту тему. Например, эта.
Давайте посмотрим, какие средства работы со словами есть в Python, и познакомимся с библиотекой pymorphy2 (морфология).
Если эта библиотека отсутствует в вашем Python, ее надо установить с помощью утилиты pip.
Словари распространяются отдельными пакетами. Для русского языка используется pymorphy2-dicts-ru.
Они обновляются время от времени, для обновления используйте команду
Морфологический анализ
В pymorphy2 для морфологического анализа слов есть класс MorphAnalyzer.
Морфологический анализ — определение характеристик слова на основе того, как оно пишется. При морфологическом анализе не учитываются соседние слова.
Для любого слова библиотека делает несколько предположений, что оно может означать, и обозначает свою уверенность в этом предположении.
Метод MorphAnalyzer.parse() возвращает один или несколько объектов типа Parse с информацией о том, как слово может быть разобрано.
В данном случае предположение одно с уверенностью score=1.0. Итак, мы имеем дело с существительным NOUN, именем собственным, одушевленным, мужского рода. Конечно, предположений может быть несколько:
У каждого разбора есть тег:
Тег
Тег — набор граммем (грамматических признаков), характеризующих данное слово.
Например, тег 'VERB,impf, tran femn, sing,past,indc' означает, что слово — глагол (VERB) несовершенного вида (impf), переходный (tran), женского рода (femn), единственного числа (sing), прошедшего времени (past), изъявительного наклонения (indc).
Полный список граммем (грамматических единиц) можно посмотреть тут и тут.
Работа с тегами
Чтобы проверить, есть ли в данном теге отдельная граммема (или все граммемы из указанного множества), используйте оператор in:
Пример:
Кроме того, у каждого тега есть атрибуты, через которые можно получить часть речи, число и другие характеристики:
Если мы попытаемся получить доступ к граммеме, которой нет для слова данной части речи, получим None.
Итак, мы можем разбирать большие тексты на части и узнавать информацию о словах: например, искать глаголы, подсчитывать имена и т. д.
Для изменения слов (к примеру, склонения существительных) можно использовать метод inflect:
И во множественном числе:
Метод inflect работает и с другими частями речи — например, глаголами:
Вернемся к параметру score.
Мы видим, что предложенные четыре варианта разбора имеют параметр score, который говорит нам о том, какой вариант предпочтительнее. Pymorphy2 использует статистические методы и ориентируется на данные проекта OpenCorpora, чтобы вычислить значение параметра score. Мы не будем останавливаться на этом подробно. Интересующиеся могут прочитать о внутренней кухне на странице документации по Pymorphy2. Скажем только, что эти вычисления не всегда точны.
Разборы сортируются по убыванию score, поэтому почти везде в примерах берется первый вариант разбора из возможных (например, morph.parse('пила')[0]).
Постановка слов в начальную форму
Нормальную (начальную) форму слова можно получить через атрибуты Parse.normal_form и Parse.normalized. Например, для глаголов в нем будет храниться инфинитив. Таким образом, можно привести любую форму глагола к единому виду.
Но что считается за нормальную форму у других слов? Например, возьмем слово «изучающим». Иногда мы захотим нормализовать его в «изучать», иногда — в «изучающий», иногда — в «изучающая».
Посмотрим на примере, что сделает pymorphy2:
Pymorphy2 сейчас использует алгоритм нахождения нормальной формы, который работает наиболее быстро (берется первая форма в лексеме) — именно поэтому, например, все причастия сейчас нормализуются в инфинитивы. Это можно считать деталью реализации.
Если требуется нормализовать слова иначе, можно воспользоваться методом Parse.inflect():
Согласование с числительными
Помимо разбора слов, библиотека может их изменять — например, сопоставлять с числами. Давайте посмотрим, как можно решить задачу с подсчетом и выводом количества комментариев на форуме:
Интересно, что библиотека пытается работать даже со словами, которых не знает, обращаясь к оракулу: