как можно сопоставить фамилии и место работы в библиотеке natasha

Рейтинг: -1Ответов: 1Опубликовано: 09.05.2023
from natasha.doc import DocSpan
for span1 in doc.spans:
    span1.normalize(morph_vocab)
{_.text: _.normal for _ in doc.spans}
 
for span1 in doc.spans:
    if span1.type == ORG:
        print(span1)

данная часть кода отвечает за вывод организаций в тексте,как можно из DocsPan вытащить данные относящиеся к полю text. И как затем их сопоставить с фамилиями

Ответы

▲ 2

Вы можете идти по синтаксическому дереву от PER до ORG. Вот код который реализует этот алгоритм:

from natasha import *
from natasha.syntax import SyntaxMarkup, token_deps


def tree_parser(dps, tok, orgs, got=None):
    if got is None:
        got = []
    if tok in got:
        return None
    if tok in orgs:
        print(tok.text)
        return tok
    print(tok.text, end='->')
    got.append(tok)
    sentence, token_in_sentence_id = tok.id.split('_')
    token_id = int(token_in_sentence_id) - 1
    for sent_id in range(int(sentence) - 1):
        token_id += len(doc.sents[sent_id].tokens)
    for dp in dps:
        if dp[1] == token_id:
            tok = tree_parser(dps, doc.tokens[dp[0]], orgs, got)
            if tok is not None:
                return tok
    for dp in dps:
        if dp[0] == token_id:
            tok = tree_parser(dps, doc.tokens[dp[1]], orgs, got)
            if tok is not None:
                return tok
    return None


segmenter = Segmenter()
morph_vocab = MorphVocab()

emb = NewsEmbedding()
morph_tagger = NewsMorphTagger(emb)
syntax_parser = NewsSyntaxParser(emb)
ner_tagger = NewsNERTagger(emb)

names_extractor = NamesExtractor(morph_vocab)
SyntaxMarkup()
text = 'Дэвид Оксмарк работающий в компании Detron HB. Михаил Видениус aka Monty из шведской компании TcX.'
doc = Doc(text)
doc.segment(segmenter)
doc.tag_morph(morph_tagger)
doc.parse_syntax(syntax_parser)
doc.tag_ner(ner_tagger)
for span1 in doc.spans:
    span1.normalize(morph_vocab)

organizations = []
organizations_normalized = []

for span1 in doc.spans:
    if span1.type == ORG:
        for token in span1.tokens:
            organizations.append(token)
            organizations_normalized.append(span1.normal)

deps = list(token_deps(doc.tokens))

for span1 in doc.spans:
    if span1.type == PER:
        token = span1.tokens[0]
        org = tree_parser(deps, token, organizations)
        if org is not None:
            print(span1.normal, organizations_normalized[organizations.index(org)], sep=' - ')
        else:
            print(span1.normal, 'Не найдено', sep=' - ')


Результат:

Дэвид->работающий->компании->в->Detron
Дэвид Оксмарк - Detron HB
Михаил->Видениус->aka->Monty->компании->из->шведской->TcX
Михаил Видениус - TcX

Из текста лучше удалять запятые, а после точек ставить пробел иначе natasha работает странно.