Собесов

Градус: извлечение бренда и подбренда из наименования товара

PythonПарсинг текстаСредняяMiddle

Условие

Дана выгрузка с колонками Сегмент, Название семьи, Наименование, Бренд (пуст), Подбренд (пуст). Нужно на основе колонок 1–3 заполнить бренд и подбренд. Если что-то не определяется — НЕ УКАЗАН.

Дополнительно (со звёздочкой): обобщить подход на наименования других групп товаров.

Примеры строк:

  • НИВЕЯ КРЕМ СОФТ 200 МЛНИВЕЯ
  • БАРХ. РУЧКИ КР. ПИТАТЕЛЬН.БАРХАТНЫЕ РУЧКИ
  • Ч/Л ЛОСЬОН ОГУРЕЧНЫЙ 100 МЛ → подбренд ОГУРЕЧНЫЙ, бренд = НЕ УКАЗАН/ЧИСТАЯ ЛИНИЯ.

Решение

Подход

  1. Словарь брендов (известный список): НИВЕЯ, БАРХАТНЫЕ РУЧКИ, ЧИСТАЯ ЛИНИЯ (Ч/Л), СВОБОДА, ARKO, LURE, EVO, TOLK и т. п.
  2. Алиасы: БАРХ.БАРХАТНЫЕ РУЧКИ, Ч/ЛЧИСТАЯ ЛИНИЯ, Ч/ЖЧЁРНЫЙ ЖЕМЧУГ, БРБАРХАТНЫЕ РУЧКИ.
  3. Подбренд — поисковый словарь специальных названий: СОФТ, BIO-ПРОГРАММА, КАЛЕНДУЛА, ОГУРЕЧНЫЙ, АНТИВОЗРАСТ.
  4. Если не нашли — НЕ УКАЗАН.

Реализация

import re, pandas as pd
 
BRAND_RULES = [
    (r'\bНИВЕЯ\b|\bNIVEA\b',                'НИВЕЯ'),
    (r'\bБАРХ?\.?\s*РУЧКИ\b|\bБР\b\s*КР?',  'БАРХАТНЫЕ РУЧКИ'),
    (r'\bЧ\s*/\s*Л\b|\bЧИСТАЯ\s*ЛИНИЯ\b',   'ЧИСТАЯ ЛИНИЯ'),
    (r'\bЧ\s*/\s*Ж\b|\bЧЁРНЫЙ\s*ЖЕМЧУГ\b',  'ЧЁРНЫЙ ЖЕМЧУГ'),
    (r'\bСВОБОДА\b',                        'СВОБОДА'),
    (r'\bARKO\b',                           'ARKO'),
    (r'\bLURE\b',                           'LURE'),
    (r'\bEVO\b',                            'EVO'),
    (r'\bTOLK\b',                           'TOLK'),
]
 
SUBBRAND_RULES = [
    r'СОФТ', r'BIO[-\s]*ПРОГРАММА', r'КАЛЕНДУЛА', r'ОГУРЕЧНЫЙ',
    r'АНТИВОЗР[АО][СТ]', r'ВОЗРАСТ\s*ЭКСПЕРТ', r'ГЕРОНТОЛ',
]
 
def extract(name: str):
    name = name.upper()
    brand = 'НЕ УКАЗАН'
    for pat, b in BRAND_RULES:
        if re.search(pat, name):
            brand = b
            break
 
    sub = 'НЕ УКАЗАН'
    for pat in SUBBRAND_RULES:
        m = re.search(pat, name)
        if m:
            sub = m.group(0)
            break
 
    return brand, sub
 
df['Бренд'], df['Подбренд'] = zip(*df['Наименование'].map(extract))

Обобщение

  • Перевести правила в YAML/JSON-словарь по сегментам:
    ПАРФЮМЕРИЯ:
      brands: [НИВЕЯ, БАРХАТНЫЕ РУЧКИ, ...]
      aliases: { "БАРХ.": "БАРХАТНЫЕ РУЧКИ" }
  • На неопознанных строках использовать fuzzy match с rapidfuzz и базой брендов (порог 85%).
  • Можно поверх — лёгкий ML: TF-IDF + KNN; для самообновления.

Подводные камни

  1. Регистр: данные UPPERCASE, но регэкспы должны быть устойчивы к мусорным символам (БРКР Д\\РУК).
  2. Порядок правил важен: БР короче и может ложно сработать на других словах. Использовать \b и контекст.
  3. Аббревиатуры конкурируют (Ч/Л = чистая линия, но в др. сегменте может быть «чёрная лимита»). Учитывать сегмент из колонки 1.
  4. Подбренд в одних строках 'СОФТ', в других — СОФТТЮБ — нормализуйте.
  5. На больших данных — сохранять словарь правил отдельно (CSV/YAML), не в коде.

Эталонный ответ

Двухэтапная экстракция: словарь брендов + регэкспы алиасов; отдельный словарь подбрендов; fallback НЕ УКАЗАН. Для обобщения — конфиг по сегменту + fuzzy match.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти