Нормализация адресов и телефонов: типичные ошибки
«ул. Ленина, д. 5» и «улица Ленина, дом 5» могут обозначать один адрес, а одинаково выглядящие номера телефонов — разные страны. Разбираем, что безопасно приводить к общему виду, а что нельзя нормализовать без контекста.

«ул. Ленина, д. 5» и «улица Ленина, дом 5» могут обозначать один адрес, а одинаково выглядящие номера телефонов — разные страны. Если без правил привести все значения к нижнему регистру и оставить только цифры, часть дублей вы исчезнете, но часть разных контактов сольёте в один. Ниже — практические приёмы для Python 3.11 и новее: где нормализация безопасна, а где требуется страна и справочник.
Сначала определите, что именно должно совпадать
Нормализация — преобразование разных записей к согласованному виду. Но «одинаковый текст» и «один и тот же объект» — не одно и то же. Для поиска можно использовать нормализованный ключ, сохраняя исходную строку. Для отправки посылки нужен проверенный адрес с отдельными компонентами: регион, город, улица, дом, корпус, квартира.
Для телефонов похожая граница: удаление пробелов и скобок приводит запись к удобному виду, но само по себе не проверяет, существует ли номер и кому он принадлежит. Международный формат E.164 — стандарт записи номера с кодом страны; чтобы получить его, недостаточно просто удалить знаки пунктуации.
Не перезаписывайте исходные адрес и телефон результатом нормализации. Храните исходное значение, нормализованный ключ и, если применимо, результат проверки отдельно.
Это упрощает разбор ошибок: вы можете изменить правила и пересчитать ключи, не пытаясь восстановить потерянные данные.
Где ломается «просто убрать лишнее»
Телефоны: код страны нельзя угадать по цифрам
Номер без плюса и кода страны неоднозначен. Последовательность цифр, введённая как местный номер, может означать разное в зависимости от страны. Даже начальный ноль нельзя отбрасывать по универсальному правилу: его значение зависит от плана нумерации.
Уберите лишь форматирующие символы, если задача — сравнить ввод с тем же номером в другом оформлении, и только при известном контексте. Для проверки и перевода в международный формат используйте библиотеку с актуальными данными о телефонных планах, например Google libphonenumber. Перед внедрением проверьте документацию выбранной версии и задайте страну по надёжному источнику, а не по языку интерфейса.
Адреса: сокращения не всегда взаимозаменяемы
Замена «ул.» на «улица» может помочь в конкретном справочнике, но не превращает произвольный текст в точный адрес. «Северная» может быть названием улицы или частью другого объекта; корпуса и строения нельзя бездумно удалять. Регистр и повторные пробелы обычно пригодны для поискового ключа, но транслитерация, исправление опечаток и раскрытие сокращений требуют правил конкретного региона или адресного справочника.
Unicode добавляет ещё одну ловушку: визуально похожие символы могут иметь разные кодовые представления. Нормализация Unicode помогает согласовать некоторые такие варианты, но не заменяет проверку адреса. Для поисковых ключей часто используют форму NFC; выбирать её нужно с учётом того, как данные обрабатывают остальные системы.
Три подхода и цена каждого
| Подход | Что делает | Цена и риск |
|---|---|---|
| Очистка оформления | Убирает повторные пробелы, нормализует Unicode, приводит выбранные символы к единому регистру. | Дёшево и обратимо, но не подтверждает, что адреса или номера обозначают один объект. |
| Разбор по правилам страны | Для телефона применяет региональный план нумерации; для адреса — правила и формат конкретной страны. | Точнее, но нужны контекст, обновляемая библиотека или справочник и обработка ошибок разбора. |
| Сверка со справочником | Сопоставляет ввод с известными адресами или подтверждёнными контактами. | Дает более надёжный результат, но требует источника данных, контроля обновлений и решения спорных совпадений. |
Не превращайте нечёткое совпадение в автоматическое объединение записей. Для дедупликации безопаснее сначала предложить кандидатов, а слияние выполнять по дополнительным полям или после подтверждения.
Безопасный первый шаг в Python
Следующий код рассчитан на Python 3.11+. Он делает только консервативную очистку: выравнивает Unicode для поискового ключа, схлопывает пробелы и удаляет из телефона знаки форматирования. Функция не проверяет номер и не преобразует его в E.164. Цифры, исходная строка и возможные ошибки остаются доступны вызывающему коду.
import unicodedata
def normalize_text_for_search(value: str) -> str:
"""Готовит текстовый ключ, не меняя смысловые слова."""
normalized = unicodedata.normalize("NFC", value)
return " ".join(normalized.casefold().split())
def normalize_phone_presentation(value: str) -> str:
"""Убирает пробелы и пунктуацию, сохраняя цифры и начальный плюс."""
normalized = unicodedata.normalize("NFC", value).strip()
digits = "".join(character for character in normalized if character.isdecimal())
has_plus_prefix = normalized.startswith("+")
if not digits:
return ""
return f"+{digits}" if has_plus_prefix else digits
print(normalize_text_for_search(" ул. Ленина, д. 5 "))
print(normalize_phone_presentation("+7 (999) 123-45-67"))
Результат для телефона будет компактной записью с цифрами и плюсом, а не подтверждённым международным номером. Для адреса функция лишь создаёт поисковый ключ: она не заменяет «ул.» на «улица» и не решает, что два написания — один адрес.
Когда какой подход выбирать
- Нужно искать одинаковый ввод в разных пробелах и регистрах. Храните исходное значение и используйте консервативный ключ. Не удаляйте значимые части адреса.
- Нужно отправлять SMS или звонить. Собирайте страну вместе с вводом, разбирайте номер по региональным правилам и отдельно проверяйте, подходит ли он для нужного канала.
- Нужно доставлять заказ. Храните компоненты адреса и используйте подходящий стране адресный справочник или сервис проверки. Не считайте результат простой очистки подтверждённым адресом.
- Нужно объединять дубли. Сравнивайте нормализованные ключи как признак для поиска кандидатов, а не как единственное доказательство совпадения.
Что ломается на практике
- Удалили всё, кроме цифр. Пропал начальный плюс, и номер из международного формата стал неотличим от локального набора цифр. Храните признак страны и исходный ввод отдельно.
- Приняли успешную очистку за валидацию. Строка стала аккуратной, но номер может быть невозможным или адрес — неполным. Состояние проверки храните отдельным полем.
- Слили записи по одной нормализованной строке. Совпадение ключей может быть следствием потери корпуса, квартиры или кода страны. Добавьте другие признаки и ручную проверку спорных случаев.
- Применили правила одной страны ко всем данным. Результат зависит от региона. Не подставляйте страну по умолчанию, если происхождение записи неизвестно.
- Изменили алгоритм, но не пересчитали ключи. В базе остаются значения, созданные по разным правилам. Зафиксируйте версию нормализатора и планируйте пересчёт с проверкой дублей.
Как проверить изменения перед запуском
Соберите набор примеров из реальных данных с разрешённым доступом: варианты с пробелами, скобками, плюсами, разными странами, корпусами и сокращениями. Для каждого задайте ожидаемый результат и отдельно отметьте случаи, где автоматическое решение запрещено. Сравните старые и новые ключи, посчитайте число новых совпадений и проверьте выборку вручную до объединения записей.
В мониторинге полезны доля пустых или неразобранных значений, число конфликтов при сопоставлении и количество записей, у которых изменился ключ после обновления правил. Не называйте эти показатели точностью: без размеченной выборки они не показывают, сколько нормализаций верны.
Дальше выберите один целевой сценарий — поиск, связь с клиентом или доставку — и задайте для него контракт данных: исходное значение, нормализованное представление, страна, статус проверки и версия правил. Затем прогоните контрольный набор перед обновлением библиотеки или справочника. Инвалидация и перенос уже накопленных ключей — отдельная тема; здесь важно не смешивать новые и старые правила без проверки.
Сноска. NFC — форма нормализации Unicode, которая приводит некоторые последовательности символов к согласованному представлению. Она помогает сравнивать текст, но не исправляет опечатки и не определяет, что два адреса физически совпадают.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: Python 3.11: unicodedata — Unicode Database, Google libphonenumber
Частые вопросы
Можно ли для дедупликации оставить в телефоне только цифры?
Как понять, что номер телефона настоящий?
Можно ли автоматически заменить «ул.» на «улица»?
Нормализация Unicode исправит похожие символы и опечатки?
Как не потерять данные при изменении правил?
Можно ли считать одинаковые нормализованные адреса дублями?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.