fix: исправлен алгоритм парсинга счетов - удаление найденных совпадений

Заменен подход с негативными lookbehind на удаление найденных совпадений:
- Сначала находим все 'КАРТА СЧЕТ' паттерны
- Заменяем их пробелами в копии текста
- Потом ищем только счета в оставшемся тексте
- Это предотвращает дублирование типа '25-22-63-30-90-57-17'
This commit is contained in:
2025-11-17 08:37:40 +09:00
parent 712577e694
commit 7343c1af4c
2 changed files with 16 additions and 13 deletions

View File

@@ -113,30 +113,34 @@ def parse_accounts_from_message(text: str) -> List[str]:
return []
accounts = []
found_accounts_only = set() # Для отслеживания уже найденных счетов
# Паттерн 1: номер карты (4 цифры) + пробел + счет (7 пар цифр)
# Используем негативный lookbehind чтобы не ловить цифры перед картой
pattern_with_card = r'(?<!\d)(\d{4})\s+(\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2})(?!\d)'
matches_with_card = re.findall(pattern_with_card, text)
pattern_with_card = r'(\d{4})\s+(\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2})'
for card, account in matches_with_card:
# Находим все совпадения с картой и удаляем их из текста
text_copy = text
for match in re.finditer(pattern_with_card, text):
card = match.group(1)
account = match.group(2)
formatted = format_account_number(account)
if formatted:
full_account = f"{card} {formatted}"
if full_account not in accounts:
accounts.append(full_account)
found_accounts_only.add(formatted) # Запоминаем этот счет
# Удаляем это совпадение из копии текста, чтобы не найти повторно
text_copy = text_copy.replace(match.group(0), ' ' * len(match.group(0)))
# Паттерн 2: только счет (7 пар цифр) БЕЗ карты перед ним
# Негативный lookbehind для проверки что перед счетом нет "4 цифры + пробел"
pattern_only_account = r'(?<!\d{4}\s)(?<!\d)\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}(?!\d)'
matches_only = re.findall(pattern_only_account, text)
# Паттерн 2: только счет (7 пар цифр) в оставшемся тексте
pattern_only_account = r'\b\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}[-\s]?\d{2}\b'
matches_only = re.findall(pattern_only_account, text_copy)
for match in matches_only:
formatted = format_account_number(match)
if formatted and formatted not in found_accounts_only and formatted not in accounts:
accounts.append(formatted)
if formatted and formatted not in accounts:
# Дополнительная проверка - этот счет не должен быть частью уже найденных "карта + счет"
is_duplicate = any(formatted in acc for acc in accounts)
if not is_duplicate:
accounts.append(formatted)
return accounts