File size: 6,278 Bytes
d869f0d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e42dbc0
d869f0d
 
 
 
 
e42dbc0
d869f0d
 
 
e42dbc0
d869f0d
 
 
 
 
 
 
 
e42dbc0
fd53dcf
fdc26d9
 
 
e42dbc0
 
d869f0d
 
 
 
 
 
 
 
 
e42dbc0
 
d869f0d
 
fd53dcf
 
 
d869f0d
 
 
 
 
 
 
 
 
e42dbc0
d869f0d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e42dbc0
 
 
d869f0d
 
 
 
 
 
 
 
 
 
 
 
e42dbc0
 
d869f0d
e42dbc0
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
def flatten(items, seqtypes=(list, tuple)):
    try:
        for i, x in enumerate(items):
            while isinstance(x, seqtypes):    
                items[i:i+1] = x
                x = items[i]
    except IndexError:
        pass
    return items

aliases = [
  #('canonical name', ['aliases', ...])
  ('почта россия', ['почта', 'почта рф', 'пр', 'gh']),
  ('почта россия трекинг', ['пр трекинг', 'почта трекинг', 'пр трэкинг', 'почта трэкинг']),
  ('реестр почта', ['реестр пр', 'реестр почта россии']),
  ('реестр пэк', []),
  ('реестры наложенных платежей', ['документы наложенных платежей']),
  ('реквизиты', []),
  ('пешкарики', []),
  ('импорт лидов директ', []),
  ('яндекс доставка экспресс', ['яндекс доставка express', 'яд экспресс', 'ядоставка экспресс']),
  ('яндекс доставка ndd', ['яд ндд', 'я доставка ндд', 'ядоставка ндд', 'модуль ндд']),
  ('яндекс доставка', ['яд', 'я доставка', 'ядоставка']),
  ('яндекс метрика', ['яндекс метрика импорт']),
  ('альфабанк', ['альфа банк', 'alfabank', 'альфа']),
  ('импорт лидов facebook', ['импорт лидов fb', 'загрузка лидов fb', 'лиды фейсбук', 'импорт лидов фб', 'fb lead']),
  ('импорт лидов вк', ['импорт лидов вконтакте', 'загрузка лидов вк', 'лиды вконтакте', 'импорт лидов vk', 'vk lead']),
  ('маркетинговые расходы', ['расходы', 'загрузка расходов']),
  ('cloudpayments', ['клауд', 'клаудпеймент', 'клаудпейментс']),
  ('robokassa', ['робокасса', 'робокаса']),
  ('sipuni', ['сипуни', 'сипьюни']),
  ('mailchimp', ['майлчимп', 'мейлчим', 'мейлчимп']),
  ('unisender', ['юнисендер']),
  ('яндекс аудитории', ['экспорт аудитории', 'экспорт яндекс аудитории']),
  ('экспорт facebook', ['экспорт сегментов facebook', 'экспорт fb', 'экспорт фейсбук', 'экспорт аудиторий фб', 'fb экспорт']),
  ('экспорт вк', ['экспорт сегментов vkontakte', 'экспорт vk', 'экспорт контакте', 'экспорт сегментов вконтакте']),
  ('retailcrm', ['срм', 'ритейл', 'ритейл срм', 'ритейлсрм', 'retail crm', 'ритейлцрм', 'ритейл црм']),
  ('retailcrm services', [
    'retailcrmservices', 'ритейлцрм services', 'лк crm services', 'ритейлцрм сервисес',
    'ритейлсрм сервисес', 'ритейлцрм сервисе', 'ритейлцрмсервисес', 'ритейлсрмсервисес',
  ]),
  ('digital pipeline', ['digital pipline']),
]

vocab_raw = flatten([[k] + keywords for k, keywords in aliases])

import string
import pymorphy3

morph = None
def normalize_word(word):
    if word == 'в' or word == 'из':
        return ''
    if word == 'лид':
        return word
    if word in ['росии', 'росси']:
        return 'россия'

    global morph
    if morph is None:
        morph = pymorphy3.MorphAnalyzer()
    return morph.parse(word)[0].normal_form

def tokenize_sentence(text):
    # remove punctuation
    text = text.translate(str.maketrans(string.punctuation, ' ' * len(string.punctuation)))
    # tokenize
    return list(filter(bool, [normalize_word(word) for word in text.split()]))
  
def normalize_sentence(text):
    return " ".join(tokenize_sentence(text))

def canonical_keywords(keywords):
    """
    replace keyword aliases with canonical keyword names
    """
    result = []
    for k in keywords:
        k = normalize_sentence(k)
        for canonical_name, alias_names in aliases:
            canonical_name = normalize_sentence(canonical_name)
            for a in alias_names:
                a = normalize_sentence(a)
                #print('a', a)
                if a == k:
                    result.append(canonical_name)
                    break
            else:
                continue
            break
        else:
            result.append(k)
    return result

def merge_keywords(keywords):
    """
    remove subkeywords
    """
    result = []
    sorted_keywords = sorted(keywords, key=len, reverse=True)
    
    for k in sorted_keywords:
        for rk in result:
            if rk.lower().startswith(k):
                break
        else:
            result.append(k)
            continue

    return result


vectorizer = None
kw_model = None

def init_keyword_extractor():
    global vectorizer
    global kw_model

    from keybert import KeyBERT
    import spacy
    from sklearn.feature_extraction.text import CountVectorizer
    
    import warnings
    warnings.filterwarnings("ignore", category=UserWarning)

    kw_model = KeyBERT(model=spacy.load("ru_core_news_sm", exclude=['tokenizer', 'tagger', 'parser', 'ner', 'attribute_ruler', 'lemmatizer']))
    vocab = [" ".join(tokenize_sentence(s)) for s in vocab_raw]
    vectorizer = CountVectorizer(ngram_range=(1, 4), vocabulary=vocab, tokenizer=tokenize_sentence)

def extract_keywords(text):
    global vectorizer
    global kw_model

    if vectorizer is None or kw_model is None:
        init_keyword_extractor()

    #print(normalize_sentence(text))
    keywords = [k for k, score in kw_model.extract_keywords(normalize_sentence(text), vectorizer=vectorizer)]
    return merge_keywords(canonical_keywords(keywords))

def extract_keywords2(text):
    vocab = sorted([" ".join(tokenize_sentence(s)) for s in vocab_raw], key=len, reverse=True)
    text = normalize_sentence(text)
    keywords = []
    for w in vocab:
        if w in text:
            keywords.append(w)
    return merge_keywords(canonical_keywords(keywords))