Как машинное обучение помогает проекту «ЗабастКом» освещать трудовые конфликты

l_gwxwouspmyvm4_pkotpe6wd1w.png
# python
import re
from natasha import Segmenter,MorphVocab,NewsEmbedding,NewsMorphTagger,Doc
from navec import Navec
from slovnet import NER

rename_dict = {'ORG': ' _орг ',
               'PER': ' _пер ',
               'LOC': ' _лок '}

text_numbers = ['ноль', 'нуль', 'один', 'два', 'три','четыре','пять',
                'шесть','семь','восемь','девять','десять',
                'одиннадцать','двенадцать','тринадцать','четырнадцать',
                'пятнадцать','шестнадцать','семнадцать','восемнадцать','девятнадцать',
                'двадцать','тридцать','сорок','пятьдесят','шестьдесят',
                'семьдесят','восемьдесят','девяносто',
                'сто','двести','триста','четыреста','пятьсот',
                'шестьсот','семьсот','восемьсот','девятьсот',
                'тысяча','миллион','миллиард','триллион',
                'полтысяча','полмиллиона','полмиллиард','полумиллиард','полмиллиарда',
                'полутриллион','полтриллиона','млрд','млд','млн']

dats = ['декабрь','январь','февраль','март','апрель','май',
       'июнь','июль','август','сентябрь','октябрь','ноябрь',
       'понедельник','вторник','среда','четверг','пятница','суббота','воскресение']

stops = ['что','как','все','она','так','его','только','мне',
        'было','меня','еще','нет','ему','теперь','когда','даже',
        'вдруг','если','уже','или','быть','был','него','вас',
        'нибудь','опять','вам','ведь','там','потом','себя','ничего',
        'может','они','тут','где','есть','надо','ней','для',
        'тебя','чем','была','сам','чтоб','без','будто','чего',
        'раз','тоже','себе','под','будет','тогда','кто','этот',
        'того','потому','этого','какой','совсем','ним','здесь','этом',
        'один','почти','мой','тем','чтобы','нее','сейчас','были',
        'куда','зачем','всех','никогда','можно','при','наконец','два',
        'другой','хоть','после','над','больше','тот','через','эти',
        'нас','про','всего','них','какая','много','разве','три',
        'эту','моя','впрочем','хорошо','свою','этой','перед','иногда',
        'лучше','чуть','том','нельзя','такой','более','всегда','конечно',
        'всю','между','это','вовремя','вновь','вовсе']

class News_cleaner:
    def __init__(self,path_navec_weights,path_ner_weights):
        self.stops = set(stops)
        self.ner = self.prepare_ner(path_navec_weights, path_ner_weights)
        self.morph_vocab = MorphVocab()
        self.segmenter = Segmenter()
        self.morph_tagger = NewsMorphTagger(NewsEmbedding())

    def prepare_ner(self,path_navec_weights,path_ner_weights):
        navec = Navec.load(path_navec_weights) 
        ner = NER.load(path_ner_weights) 
        ner.navec(navec)
        return ner

    def clean_text(self,text):
        ner_tokens = self.ner(text)
        text = text.lower()
        lemm_tokens = []
        doc = Doc(text)
        doc.segment(self.segmenter)
        doc.tag_morph(self.morph_tagger)
        for x in doc.tokens:
            flag = False
            for span in ner_tokens.spans:
                if span.start<=x.start and span.stop>=x.stop:
                    flag = True
                    y = rename_dict[span.type]
                    lemm_tokens.append(y)
                    break
            if flag==False:
                x.lemmatize(self.morph_vocab)
                y = x.lemma
                lemm_tokens.append(y)
        text = ' '.join(lemm_tokens)
        text = re.sub(r'\d+',r' _чсл ',text)
        for x in text_numbers:
            text = text.replace(' '+x+' ',' _чсл ')
        for x in dats:
            text = text.replace(' '+x+' ',' _дат ')           
        text = re.sub(r'[^а-я_ ]',r' ',text)
        text = re.sub(r' _ ',r' ', text)
        text = ' '.join([w for w in text.split() if len(w)>2])
        text = ' '.join([w for w in text.split() if w not in self.stops])
        text = re.sub(r'(_орг )+',r'_орг ',text+' ')
        text = re.sub(r'(_пер )+',r'_пер ',text+' ')
        text = re.sub(r'(_лок )+',r'_лок ',text+' ')
        text = re.sub(r'(_чсл )+',r'_чсл ',text+' ')
        text = re.sub(r'(_дат )+',r'_дат ',text+' ')
        return text.strip()
#//////////////////////////////////////////////////////////////////////////////////////

# weighs from github.com/natasha/navec and github.com/natasha/slovnet
path_navec_weights = './resources/navec_news_v1_1B_250K_300d_100q.tar' 
path_ner_weights = './resources/slovnet_ner_news_v1.tar'
cleaner = News_cleaner(path_navec_weights,path_ner_weights)

text = 'В Лондоне курьеры ООО "Рога и копыта" во главе с Ивановым \
        уже объявляли предупредительную забастовку на два дня в мае 2020 г.'
result = cleaner.clean_text(text)
print(result)
#_лок курьер _орг глава _пер объявлять предупредительный забастовка _чсл день _дат _чсл

© Habrahabr.ru