Вы можете идти по синтаксическому дереву от 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
работает странно.