{"id":14293,"url":"\/distributions\/14293\/click?bit=1&hash=05c87a3ce0b7c4063dd46190317b7d4a16bc23b8ced3bfac605d44f253650a0f","hash":"05c87a3ce0b7c4063dd46190317b7d4a16bc23b8ced3bfac605d44f253650a0f","title":"\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0435 \u043f\u043e\u0442\u0440\u0430\u0442\u0438\u0432 \u043d\u0438 \u043a\u043e\u043f\u0435\u0439\u043a\u0438","buttonText":"","imageUuid":""}

Как извлечь структурированную информацию с помощью Yargy-парсера?

В части задачи NER (извлечение именованных сущностей) для текстов на русском языке, многим знакома библиотека natasha, обладающая большим набором встроенных правил (экстракторов) для извлечения отдельных типов сущностей (Адреса, Имена и т.д.) из текста. Но бывают случаи, когда необходимо создать новое уникальное правило для извлечения данных, и иметь для этого понятный и гибкий инструмент на Python. В таком случае Yargy-парсер является хорошим решением.

Данная библиотека является частью большого проекта Natasha и, собственно, основой библиотеки natasha. Работа Yargy-парсера основана на контекстно-свободных грамматиках и словарях. В Yargy-парсере реализован алгоритм Эрли, временная сложность которого Θ (n3).

Yargy-парсер использует словари и правила для извлечения структурированной информации из текстов на русском языке. Правила (rule) состоят из предикатов. Yargy-парсер имеет множество встроенных предикатов, таких как:

  • is_capitalized — слово начинается с большой буквы,
  • is_single — слово в единственном числе, gram (X), где X – это граммема.

Yargy-парсер использует библиотеку pymorphy для определения формы слова, gram(‘ADJF’) – означает, что слово является прилагательным. У парсера есть метод findall, который возвращает список-результат сопоставлений.

В качестве примера решим задачу определения в тексте заказа наименований напитков. Перечень напитков определим в правиле R_1 через предикат dictionary, перед названием напитка должно идти прилагательное.

from yargy import Parser, rule from yargy.predicates import gram, dictionary R_1 = rule (gram('ADJF'), dictionary({'сок', 'морс', 'компот'})) parser = Parser(R_1) text = 'В заказ на доставку входили апельсиновый сок, вишнёвый морс и абрикосовый компот.' for match in parser.findall(text): print ([x.value for x in match.tokens])

Результат:

['апельсиновый', 'сок'] ['вишнёвый', 'морс'] ['абрикосовый', 'компот']

Попробуем отыскать в тексте обращения информацию о заказе. В данном случае ищем все последовательности, начинающиеся со слова «заказ», после чего должен идти символ или слово «номер» и, непосредственно, сам номер.

from yargy import Parser, rule, and_ from yargy.predicates import gram, dictionary, type as t1 INT = t1('INT') R_1 = rule (dictionary({'заказ'}), dictionary({'номер', '№'}), INT.repeatable()) parser = Parser(R_1) text = ''' Просьба дать обратную связь по статусу заказа номер 12535. В личном кабинете третий день стасус "Ожидает отправки". Заказ № 54321 уже получен. ''' for match in parser.findall(text): print ([x.value for x in match.tokens])

Результат будет следующим:

['заказа', 'номер', '12535'] ['Заказ', '№', '54321']

А теперь решим задачу извлечения из текста свойств банковской карты – это тип карты дебетовая или кредитная, а также классическая, золотая или платиновая. Для распознавания различных вариаций для поиска используем газеттир типа morph_pipeline. Конструктор fact описывает объект-результат интерпретации (interpritation), в нашем случае «Card» (банковская карта), где tarif и type – атрибуты данного объекта.

from yargy import rule, or_ from yargy.predicates import gram, eq from yargy.interpretation import fact from yargy.pipelines import morph_pipeline Card = fact('Card', ['tarif','type']) classic_tatif = morph_pipeline(['класс', 'классич', 'классическая']).interpretation(Card.tarif.const('классическая')) gold_tatif = morph_pipeline(['золот', 'золотая']).interpretation(Card.tarif.const('золотая')) platinum_tatif = morph_pipeline(['платин', 'платинов', 'платиновая']).interpretation(Card.tarif.const('платиновая')) cr_c = morph_pipeline(['кр', 'кред', 'кредитная']).interpretation(Card.type.const('кредитная')) deb_c = morph_pipeline(['деб', 'дебет', 'дебетовая']).interpretation(Card.type.const('дебетовая')) short_c = morph_pipeline(['к', 'карт', 'карта']) CARD = rule(or_(classic_tatif, gold_tatif, platinum_tatif),or_(cr_c, deb_c), eq('.').optional(), short_c, eq('.').optional()).interpretation(Card) parser = Parser(CARD) text = ''' Клиенту была выдана классич дебетовая карта ''' for match in parser.findall(text): print (match.fact)

Результат будет следующим:

Card(tarif='классическая', type='дебетовая')

Yargy-парсер — это мощный инструмент для извлечения структурированной информации из русско-язычных текстов. Вместе с тем, парсер реализован на python, что делает его использование в проекте чаще всего более удобным в сравнении с аналогами, такими, так Tomita-парсер от Yandex.

0
Комментарии
-3 комментариев
Раскрывать всегда