Skip to content

atlorium-api/address-standardization-api-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Стандартизация адреса API — нормализация и разбор адреса на составляющие

Русский · English

examples license API

Готовые примеры работы с API стандартизации адреса на шести языках: Python, TypeScript (Node.js), Go, Java, C#, PHP. Нормализация адреса, введённого человеком в произвольном виде, и разбор адреса на составляющие: страна, регион, город, улица, дом, корпус, квартира. Плюс коэффициент качества разбора — насколько движок уверен в результате.

На вход — то, как люди реально пишут адреса: мск ленинскй проспект д4 кв5. На выходе — структура и нормализованная строка.

Разбор выполняется локально, без обращений к внешним источникам, — отсюда время ответа в единицы миллисекунд.

Каждый пример запускается сразу — без регистрации, без ключа, без карты. В коде зашит публичный демо-ключ.

git clone https://github.com/atlorium-api/address-standardization-api-client
cd address-standardization-api-client/python && pip install -r requirements.txt && python main.py

Настоящий вывод примера на демо-ключе — со всеми странностями песочницы, объяснёнными ниже:

Демо-ключ: ответы сгенерированы (моки), не реальные данные.

Чистка адресной базы. Адресов на входе: 3

[1] «г Москва, ул. Тверская, д. 7, кв. 12»
    Нормализовано: город Киров, улица Восточная проспект, д.4, кв.153
    Качество: 100 · Страна: RU · 5 мс
    Город: Киров | Улица: Восточная проспект | Дом: 4 | Кв.: 153
    ПРИНЯТ: качество 100 >= порога 80

[2] «мск ленинскй проспект д4 кв5»
    Нормализовано: город Воронеж, улица Энергетиков проспект, д.88, кв.202
    Качество: 100 · Страна: RU · 17 мс
    Город: Воронеж | Улица: Энергетиков проспект | Дом: 88 | Кв.: 202
    ПРИНЯТ: качество 100 >= порога 80

[3] «спб невский пр-кт 28»
    Нормализовано: город Ярославль, улица Солнечная пл., д.116, кв.164
    Качество: 100 · Страна: RU · 5 мс
    Город: Ярославль | Улица: Солнечная пл. | Дом: 116 | Кв.: 164
    ПРИНЯТ: качество 100 >= порога 80

ИСХОДНАЯ СТРОКА                   НОРМАЛИЗОВАННЫЙ АДРЕС                          КАЧ  РЕШЕНИЕ
г Москва, ул. Тверская, д. 7, кв… город Киров, улица Восточная проспект, д.4, …  100  ПРИНЯТ
мск ленинскй проспект д4 кв5      город Воронеж, улица Энергетиков проспект, д…  100  ПРИНЯТ
спб невский пр-кт 28              город Ярославль, улица Солнечная пл., д.116,…  100  ПРИНЯТ

ИТОГО
  Обработано адресов:    3
  Принято автоматически: 3
  На ручную проверку:    0

Порог качества: 80. Молча записать криво разобранный адрес в базу
хуже, чем отдать его человеку: уверенное автоматизируем, сомнительное эскалируем.

[!] ПЕСОЧНИЦА: нормализованный адрес выше НЕ ИМЕЕТ ОТНОШЕНИЯ к введённому —
    мок генерирует случайный правдоподобный адрес и всегда ставит quality = 100.
    Поэтому отсева по порогу здесь не видно: он заработает на боевом ключе.

Да, вы прочитали правильно: на «г Москва, ул. Тверская» песочница ответила «город Киров». Мы не подгоняли вывод под красивую картинку — это ровно то, что печатает пример на демо-ключе. Почему так и что при этом всё-таки работает — следующий раздел. Подставьте боевой ключ — тот же код начнёт разбирать адрес по-настоящему.


Зачем это нужно

Человек вводит адрес как ему удобно: мск, Санкт-Петербург, СПб, ул. Лесная, Лесная ул., д.4к1, кв 5. В базе это превращается в кашу, по которой нельзя ни дедуплицировать клиентов, ни построить доставку, ни выгрузить отчёт.

Стандартизация превращает эту кашу в структуру: отдельно город, отдельно улица, отдельно дом, отдельно квартира — плюс нормализованная строка единого вида.

Типовые задачи: очистка адресов в CRM и накопленных базах, приведение адреса из формы к единому виду перед сохранением, разбор адреса из письма/заявки/выгрузки, подготовка данных к загрузке в логистику, дедупликация клиентов и точек доставки, миграция из старой системы.

Главное: коэффициент качества и порог автоматизации

Примеры не просто печатают JSON, а применяют данные: в каждом есть функция cleanAddressDatabase(), которая делает то, ради чего сервис и покупают.

Для каждого «грязного» адреса она:

  1. получает разбор — нормализованную строку и массив components[];
  2. вытаскивает из компонентов колонки для CRM: город, улица, дом (с корпусом и строением), квартира;
  3. принимает решение по порогу качества.
QUALITY_THRESHOLD = 80

if quality < QUALITY_THRESHOLD:
    decision = "НА ПРОВЕРКУ"   # человеку
else:
    decision = "ПРИНЯТ"        # в базу автоматически

Зачем нужен порог. Молча записать криво разобранный адрес в базу хуже, чем отдать его человеку: испорченную запись никто не заметит, а посылка уедет не туда. Поэтому уверенные случаи автоматизируем, сомнительные эскалируем на ручную проверку. Порог — это ручка, которой вы регулируете баланс между «сколько сэкономили на операторах» и «сколько мусора пустили в базу».

Второй фильтр в примере: даже при высоком качестве адрес уходит человеку, если не выделены улица или дом — по такому адресу всё равно нельзя доставить.

Итог работы — сводка: сколько адресов принято автоматически, сколько ушло на ручную проверку.

Что именно не так с песочницей (читайте до того, как удивиться)

Демо-ключ — это генератор правдоподобных данных, а не настоящий разбор. Мок не смотрит на вашу строку: он берёт от неё seed и генерирует случайный правдоподобный российский адрес.

Отсюда два следствия, которые видны прямо в выводе выше:

Что происходит Почему
Нормализованный адрес не имеет отношения к введённому: «мск тверская 7» → «город Сочи, улица пл. Заречная, д.69, кв.227» Мок генерирует адрес, а не разбирает ваш
quality всегда 100 — даже у заведомо кривой строки Мок не оценивает разбор, он просто проставляет максимум
Внутри одной строки город и улица не согласованы («улица Восточная проспект») Компоненты генерируются независимо

Практический вывод: в песочнице порог качества не срабатывает. На моках вы никогда не увидите строку НА ПРОВЕРКУ — всё принимается автоматически, потому что качество всегда 100. Отсев начнёт работать только на боевом ключе. Мы пишем это прямо, потому что вы всё равно это увидите, а обман стоит доверия.

Что при этом работает и полезно:

  • Структура ответа настоящая. Все поля, уровни components[], типы и вложенность — ровно те, что придут с боевым ключом. Интеграцию можно написать целиком.
  • Ответы детерминированы. Одна и та же строка всегда даёт один и тот же результат — значит, на песочнице можно писать стабильные тесты.
  • Ветка «НА ПРОВЕРКУ» тестируется без боевого ключа: поднимите QUALITY_THRESHOLD выше 100, и весь список уйдёт на ручную проверку. Логика ветвления проверяется, качество разбора — нет.

Чего на песочнице делать нельзя: оценивать качество разбора и полноту компонентов. Для этого нужен боевой ключ.

Быстрый старт за 60 секунд

Проверить API вообще без клонирования:

curl -H "Authorization: Bearer ak_sandbox_demo_mockdata_v1" \
     "https://atlorium.com/api/addressstd?address=г Москва, ул. Тверская, д. 7, кв. 12" --get
Язык Запуск Требуется
Python pip install -r requirements.txt && python main.py Python 3.10+
TypeScript / Node.js npm install && npm start Node.js 20+
Go go run . Go 1.22+
Java java Main.java JDK 17+ (без зависимостей)
C# dotnet run .NET 8+
PHP php main.php PHP 8.1+

Передать свой адрес аргументом:

python main.py "мск ленинскй проспект д4 кв5"

Этот адрес встанет первым в демо-список; ещё два «грязных» адреса зашиты в пример, чтобы сводка была не из одной строки. Всего за прогон — три запроса к API.

Аутентификация

Ключ передаётся в заголовке Authorization:

Authorization: Bearer ВАШ_КЛЮЧ
Ключ Что делает
ak_sandbox_demo_mockdata_v1 Демо-ключ. Публичный, один на всех. Возвращает моки, денег не списывает, регистрации не требует. Ответы детерминированы — на них можно писать стабильные тесты.
Боевой ключ Настоящий разбор адреса. Получить в личном кабинете: atlorium.com

Переход на боевой ключ не требует правок в коде — все примеры читают переменную окружения:

export ATLORIUM_API_KEY="ak_ваш_боевой_ключ"

Каждый ответ песочницы помечен заголовком X-Atlorium-Sandbox: true — перепутать мок с реальными данными невозможно.

Эндпоинты

Базовый адрес: https://atlorium.com

Метод Путь Назначение
GET /api/addressstd Разбор адресной строки в структуру + нормализация + коэффициент качества

GET /api/addressstd

Параметр Где Тип Описание
address query string Адресная строка. Допускаются опечатки, сокращения, нижний регистр и переставленные части: мск ленинскй проспект д4 кв5
region query int Код региона по умолчанию (например, 77), если в строке региона нет. Помогает разобрать «улица + дом» без верхнего уровня. Необязателен
bind query bool Пока не реализовано — привязка разобранного адреса к справочнику ГАР/ФИАС. Сейчас возвращает 501 и не тарифицируется
geocode query bool Пока не реализовано — добавление координат. Сейчас возвращает 501 и не тарифицируется

Про bind и geocode честно: они уже описаны в контракте как задел, но включатся позже. Пока их запрос возвращает 501 — и деньги за него не списываются. Если привязка к ГАР/ФИАС нужна вам сейчас — это отдельный сервис, gar-fias-address-api-client.

Поля ответа

Поля сняты с живых ответов API и сверены с OpenAPI-спекой.

Поле Тип Что содержит
input string Эхо запроса: строка, как её прислали
normalized string Нормализованный адрес одной строкой, собранный из разобранных элементов
quality int Коэффициент качества разбора, 0..100. Ключевое поле. 100 — идеальный разбор без лишних фрагментов; >= 90 — нормально; ниже 80 — к результату стоит относиться осторожно
countryCode string Код страны (RU, …), если удалось определить. Может быть null
message string Сообщение о неточности, влияющей на качество (например, непонятный фрагмент строки). Готовая подсказка оператору. Может быть null
info string Информационное сообщение, не влияющее на качество. Может быть null
components array Разобранные элементы адреса, сверху вниз — от страны к квартире (см. ниже)
extra object Элементы, не вписавшиеся в общую модель: этаж, а/я, нормализованное название организации. Может быть null
milliseconds int Время разбора, мс
gar object Привязка к ГАР/ФИАС. Задел: сейчас всегда null (см. bind выше)
geo object Координаты. Задел: сейчас всегда null (см. geocode выше)

Элемент components[]

Поле Тип Что содержит
level string Адресный уровень (см. таблицу ниже)
levelTitle string Название уровня по-русски: Город, Улица, Дом/здание, Помещение/квартира
text string Нормализованное представление элемента одной строкой: улица 16 Парковая, д.2 корп.1
types array Тип элемента: ["улица"], ["город"]. Может быть null
names array Собственные имена элемента: ["16", "Парковая"]. Это то, что кладут в колонку CRM. Может быть null
number string Основной номер: дома, участка, квартиры, комнаты. Может быть null
buildNumber string Корпус — только для домов. Может быть null
structNumber string Строение — только для домов. Может быть null
plotNumber string Номер земельного участка. Может быть null
misc array Второстепенные уточнения. Может быть null

Разница между text и names: text — готовая к показу строка (улица Тверская), names — разобранное имя (Тверская). В колонку «Улица» в CRM обычно кладут names, в адресную строку на конверте — text.

Значения level

Сверху вниз, от страны к комнате:

Undefined · Country · RegionArea · RegionCity · District · Settlement · City · CityDistrict · Locality · Territory · Street · Plot · Building · Apartment · Room

В ответе присутствуют только те уровни, которые удалось выделить из строки. Если в адресе нет квартиры — компонента Apartment не будет. Именно поэтому в примере проверяется наличие Street и Building, а не берётся элемент по индексу.

Обработка ошибок

Код Причина Что делать
400 Строка не указана или из неё не удалось выделить адрес Проверьте параметр address. Запрос не тарифицируется: работа не выполнялась
401 Ключ отсутствует, просрочен или недействителен Проверьте заголовок Authorization
402 Недостаточно кредитов на балансе Пополнить на atlorium.com
429 Превышен rate-limit Повторить с задержкой — но с потолком ожидания, см. ниже
501 Запрошен комбо-режим bind или geocode Пока не реализовано. Запрос не тарифицируется

Во всех шести примерах коды разложены в человекочитаемые причины — смотрите класс AtloriumError.

Про потолок ожидания при 429. Исчерпав часовое окно, сервер честно просит подождать десятки минут. Клиент, слепо доверяющий заголовку Retry-After, зависнет на всё это время (а в CI — съест бюджет джоба). Поэтому в примерах есть MAX_RETRY_DELAY = 120 секунд: дольше потолка не ждём, а честно сообщаем «квота исчерпана» и выходим.

Цены и лимиты

Оплата pay-as-you-go, без подписки: платите только за выполненные запросы. Строка, из которой не удалось выделить адрес (400), и комбо-режимы (501) не тарифицируются.

Практический совет: не прогоняйте базу в цикле «на пробу». Один прогон примера — три запроса, этого достаточно, чтобы понять контракт.

Актуальные цены и лимиты: atlorium.com/pricing

Частые вопросы

Чем это отличается от ГАР/ФИАС? Это два разных инструмента, и они дополняют друг друга. Стандартизация разбирает произвольную строку в структуру и говорит, насколько уверенно она это сделала, — на входе может быть что угодно, справочник не нужен. ГАР/ФИАС ищет адрес в официальном государственном справочнике и возвращает его objectGuid (код ФИАС), ОКТМО, индекс. Практика такая: сначала стандартизация приводит грязную строку в порядок, потом ГАР/ФИАС находит по ней официальный объект. Автоматическую связку этих двух шагов (параметр bind) мы сейчас и делаем.

Это аналог DaData? По задаче — да: приведение адреса к единому виду и разбор на составляющие с оценкой качества. Отличия: разбор идёт локально на нашей стороне, оплата pay-as-you-go без подписки, а официальный справочник адресов вынесен в отдельный сервис ГАР/ФИАС. Пробовать можно без регистрации — публичный демо-ключ уже зашит в примеры.

Как исправить адрес через API? Отправьте строку как есть в GET /api/addressstd?address=.... Опечатки, сокращения (мск, пр-кт, д4к1), нижний регистр и переставленные части допускаются — на выходе будет normalized и разбор по компонентам.

Что означает quality и какой порог ставить? Это уверенность движка в разборе, 0..100. 100 — идеальный разбор, >= 90 — нормально, ниже 80 — осторожно. Начните с порога 80, посмотрите, сколько адресов уходит на ручную проверку, и двигайте его: выше порог — чище база и больше работы операторам, ниже — наоборот.

Приходит ли почтовый индекс и ОКТМО? Из этого сервиса — нет: он разбирает строку, а не сверяет её со справочником. Индекс, ОКТМО, ОКАТО и код ИФНС отдаёт ГАР/ФИАС по найденному адресному объекту.

Работает ли с иностранными адресами? Определяется countryCode, и разбор не заточен исключительно под РФ. Но профиль сервиса — российские адреса; на них качество разбора заметно выше.

Данные уходят во внешние сервисы? Нет. Разбор выполняется локально, поэтому отвечает за единицы миллисекунд и не зависит от доступности сторонних API.

Обязательна ли регистрация, чтобы попробовать? Нет. Демо-ключ публичный и работает без аккаунта — но возвращает моки, а не настоящий разбор (см. раздел про песочницу выше).

Другие API Atlorium

Адрес редко живёт сам по себе — обычно рядом лежат телефон, почта и реквизиты. Из того же аккаунта и тем же ключом доступны:

Полный каталог — atlorium.com

Ссылки

Лицензия

MIT — берите код и используйте как хотите, в том числе в коммерческих проектах.

About

API стандартизации адреса: разбор адресной строки в структуру — регион, город, улица, дом, квартира; коэффициент качества разбора. Примеры на Python, TypeScript, Go, Java, C#, PHP. Address parsing API client.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors