Нормализация адресов в 1С через API DaData: таблица значений, HTTP и код qc

30.09.26

Интеграция - WEB-интеграция

Пошагово показываю, как массово привести пользовательские адреса контрагентов к структуре ФИАС через API clean DaData: ключи, HTTPЗапрос, таблица значений под JSON, пакеты до 100 строк и отбор по qc без затирания исходника.

Нормализация адресов в накопленной базе 1С:Предприятие 8.3 редко укладывается в одну функцию платформы: пользователи вводят строки с сокращениями, опечатками и полями в произвольном порядке, а десятки тысяч записей руками или цепочкой замен не выправить. Ниже - практическая схема через API clean сервиса DaData и справочники ФИАС: для каждой строки или пакета собираем НТТРЗапрос с POST на стандартизацию, разбираем JСОН-массив ответа в таблицу значений по именам полей и по коду qc отбираем то, что ещё должен проверить человек.

 

Когда адреса пора отдавать во внешний сервис

Перед первым НТТР-вызовом я решаю, где в конфигурации лежит код интеграции: иначе ключи оказываются в обработке, а из регламента их не переиспользовать без копипаста.

 

Расширение: общий модуль, константы ключей, обработка прогона

 

Расширение: общий модуль, константы ключей, обработка прогона

В типовых конфигурациях адрес контрагента, сотрудника или объекта учёта часто хранится одной текстовой строкой в контактной информации. Пока записей сотни, можно договориться о маске ввода или править вручную. Когда счёт идёт на десятки и сотни тысяч, самодельные проверки и замены подстрок превращаются в хрупкий зоопарк правил: каждое новое сокращение ломает очередной шаблон, а «Москва» и «мск» в одной базе живут параллельно.

У платформы 1С нет встроенной «серебряной пули» для произвольного русскоязычного ввода. Геокодеры вроде Яндекса решают близкую задачу, но для массового приведения к административному делению и полям КЛАДР/ФИАС мне удобнее DaData: стандартизация завязана на те же идентификаторы, с которыми дальше работают отчёты и интеграции с доставкой.

Ориентир по качеству я беру из своего прогона порядка 84 тысяч адресов: около 4 тысяч сервис пометил как кандидатов на ручную проверку (поле qc), и среди них примерно пятая часть оказалась уже корректной, а остальное чаще было изначально бессмысленным вводом (один город без улицы и дома). Это не обещание полной автоматизации, а порядок цифр, с которым можно сверить свой объём после пилота на нескольких тысячах строк.

Ограничения лучше заложить в ТЗ сразу. Стандартизация в DaData платная, в тарифах обычно фигурирует порядка 5–10 копеек за один адрес; после регистрации дают около 100 бесплатных вызовов для проверки кода. Обрабатываются только российские адреса. Документацию по методу clean и полному составу полей ответа смотрите на сайте DaData в разделе API clean (pricing и описание ответ там же).

Примеры «грязных» строк, ради которых вообще стоит звать сервис:

  • мск сухонска 11/-89 (город сокращён, дом и квартира слеплены через слэш);
  • москва Сухонская улица 11 89 (без индекса и типов в каноническом виде);
  • г. Москва, ул. Сухонская, д. 11, кв. 89 (формально близко к норме, но индекс и qc всё равно полезны для отбора);
  • Москва Сухонская 11 стр 2 оф 305 (нестандартные части здания, их разбор зависит от полноты строки).

После пилота я обычно фиксирую порог: если ручная проверка qc занимает больше времени, чем экономия на доставке или отчётах, расширяем набор колонок (fias_id, geo_lat) и не перезаписываем исходник до подписи ответственного.

Отдельный общий модуль под clean и константы под ключи проще сдать на ревью без страха, что секрет уже в diff.

 

Ключи и endpoint clean/address

Доступ к API начинается с регистрации в личном кабинете DaData. Там же выдают пару ключей: АРИ-ключ для заголовка Authorization в формате Token и секретный ключ для X-Secret. Оба участвуют в каждом вызове стандартизации; без секрета сервис отвечает отказом, и это первая вещь, которую я проверяю при «внезапно пустом» ответе на тестовой базе.

 

Контекст: Ключи и endpoint clean/address

 

Контекст: Ключи и endpoint clean/address

Рабочий путь метода: хост dadata.ru, порт 443, ресурс /api/v2/clean/address, метод POST, тело application/json в виде массива строк. Одна строка в массиве даёт массив из одного объекта в ответе; до 100 строк в одном теле допустимы по документации clean, и порядок элементов ответа совпадает с порядком адресов в запросе.

Ключи в коде не держу строками в общем модуле, который попадёт в хранилище. Варианты для типовой без снятия с поддержки: константы, доступные только администратору; регистр или настройки интеграции в расширении; защищённое хранилище платформы, если оно уже используется в проекте. Для тестового контура завожу отдельную пару ключей и отдельную константу «контур DaData», чтобы случайно не прогнать полмиллиона строк по боевому тарифу из копии базы.

 

Таблица значений под JSON ответа

Рабочая модель у меня одна: таблица значений, где есть колонка исходного адреса и набор колонок с именами, совпадающими с полями JСОН-объекта в ответе clean. Тогда после ПрочитатьJСОН достаточно ЗаполнитьЗначенияСвойств без ручного сопоставления десятков реквизитов.

 

Контекст: Таблица значений под JSON ответа

 

Контекст: Таблица значений под JSON ответа

Минимальный набор колонок, который закрывает учёт и отбор на проверку:

  • ИсходныйАдрес (ваше поле, в ответе сервиса его нет);
  • result (нормализованная одна строка);
  • postal_code, region_with_type, city_with_type, settlement_with_type;
  • city_district_with_type, street_with_type, house, flat;
  • qc (код качества для фильтра).

Если дальше нужны доставка или привязка к ФИАС, добавляю fias_id, kladr_id, geo_lat, geo_lon тем же правилом: имя колонки совпадает с именем свойства в ответе. Лишние поля из JSON просто некуда писать, пока не добавите колонку; лишние колонки без одноимённого свойства останутся пустыми после ЗаполнитьЗначенияСвойств.

Источник строк для таблицы зависит от конфигурации. Универсально: выгрузить текст адреса и ссылку на владельца запросом, не таща всю контактную информацию в память лишний раз. Запрос ниже выбирает контрагентов с непустым представлением адреса; имена таблиц и реквизитов подставьте под свою схему хранения контактов.

ВЫБРАТЬ
	КонтактнаяИнформация.Объект КАК Контрагент,
	КонтактнаяИнформация.Представление КАК АдресСтрокой
ИЗ
	РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
ГДЕ
	КонтактнаяИнформация.Тип = &ТипАдрес
	И КонтактнаяИнформация.Вид = &ВидАдресКонтрагента
	И КонтактнаяИнформация.Представление <> &ПустаяСтрока

В результате смотрите на длину представления и явные дубликаты: одинаковая строка у разных контрагентов нормализуется одинаково, но писать результат всё равно придётся в каждую строку таблицы или в регистр с измерением «владелец».

 

НТТРЗапрос и разбор JSON на 8.3.6+

На пилоте половина сбоев у меня была не в JSON, а в забытых Token или X-Secret; поэтому в модуле я держу отдельную проверку заголовков до отправки тела.

 

Контекст: НТТРЗапрос и разбор JSON на 8.3.6+

 

Контекст: НТТРЗапрос и разбор JSON на 8.3.6+

 

POST clean/address: заголовки Token и X-Secret, тело-массив

 

POST clean/address: заголовки Token и X-Secret, тело-массив

Для HTTP нужны заголовки Content-Type application/json, Authorization Token … и X-Secret. Тело - JСОН-массив строк адресов. На платформе 8.3.6 и новее я опираюсь на встроенные ЗаписьJСОН и ПрочитатьJСОН; на более старых релизах без них остаётся сторонний парсер, и это отдельная ветка сопровождения.

Главная ловушка при формировании тела вручную - кавычки и обратный слэш в исходном адресе: они ломают JSON. Сборка текста запроса конкатенацией вокруг адреса на строке с кавычкой в названии офиса даёт 400 от сервиса или пустой разбор на клиенте. Надёжнее положить адреса в массив платформы и сериализовать его через ЗаписьJСОН.

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

&НаСервере
Функция НормализоватьПакетАдресов(МассивСтрокАдресов, КлючAPI, СекретAPI) Экспорт
	
	ЗаписьJSON = Новый ЗаписьJSON;
	ЗаписьJSON.УстановитьСтроку();
	ЗаписатьJSON(ЗаписьJSON, МассивСтрокАдресов);
	ТелоЗапроса = ЗаписьJSON.Закрыть();
	
	Заголовки = Новый Соответствие;
	Заголовки.Вставить("Content-Type", "application/json");
	Заголовки.Вставить("Authorization", "Token " + КлючAPI);
	Заголовки.Вставить("X-Secret", СекретAPI);
	
	HTTPЗапрос = Новый HTTPЗапрос("/api/v2/clean/address", Заголовки);
	HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
	
	Соединение = Новый HTTPСоединение("dadata.ru", 443,,,,,
		Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено));
	HTTPОтвет = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
	
	Если HTTPОтвет.КодСостояния <> 200 Тогда
		ВызватьИсключение "DaData clean: код " + HTTPОтвет.КодСостояния + ", тело: "
			+ HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
	КонецЕсли;
	
	ТелоОтвета = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
	Если ПустаяСтрока(СокрЛП(ТелоОтвета)) Тогда
		ВызватьИсключение "DaData clean: пустое тело при коде 200";
	КонецЕсли;
	
	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(ТелоОтвета);
	МассивРезультатов = ПрочитатьJSON(ЧтениеJSON);
	ЧтениеJSON.Закрыть();
	
	Возврат МассивРезультатов;
	
КонецФункции

Ответ clean всегда приходит массивом объектов. Для одной строки контракт тот же, что и для пакета, поэтому один код чтения покрывает оба варианта.

Блок с ЗаписьJСОН отвечает за экранирование. Блок с НТТРСоединение и НТТРЗапрос не должен молча проглатывать ответы с кодом, отличным от 200: в теле часто лежит текст ошибки лимита или авторизации. После ПрочитатьJСОН для одной строки таблицы беру первый элемент массива; для пакета сопоставляю элемент ответа с тем же индексом, что и строка в пакете.

Заполнение строки таблицы для одного элемента массива:

&НаСервере
Процедура ПрименитьОтветCleanКСтроке(СтрокаТаблицы, ДанныеОтвета)
	ЗаполнитьЗначенияСвойств(СтрокаТаблицы, ДанныеОтвета);
КонецПроцедуры

Если ПрочитатьJСОН падает, сохраняю сырое тело в журнал регистрации вместе с первыми символами исходного адреса. Иначе повторный прогон по тому же месту съедает лимит впустую.

 

Цикл, пакеты и обработка сбоев

Сквозной сценарий у меня замкнут: выборка, пакет, POST, qc, запись, следующий пакет. Параметр «максимум за сеанс» разрывает цикл, когда лимит или бюджет исчерпаны, а не крутит базу до бесконечности.

 

Контекст: Цикл, пакеты и обработка сбоев

 

Контекст: Цикл, пакеты и обработка сбоев

 

От выборки адресов до записи по qc без затирания исходника

 

От выборки адресов до записи по qc без затирания исходника

Цикл «на каждую строку свой POST» понятен и работает, но на объёме порядка 84 тысяч адресов каждый вызов добавляет задержку на установку защищённого соединения. Я режу таблицу на пакеты по 100 строк, формирую массив адресов пакета, один раз вызываю процедуру нормализации пакета и в цикле по индексу переношу свойства в строки. Между пакетами добавляю паузу, если в ответе мелькнул 429 или сеть дала таймаут: повтор с тем же телом, без перехода к следующему пакету, пока текущий не отработал.

Учёт лимитов и тарификации для меня часть логики, а не комментарий в коде. Перед ночным регламентным заданием смотрю остаток на счёте и прикидываю стоимость прогона по числу строк и цене за адрес; в обработке задаю параметр «максимум адресов за сеанс», чтобы тестовый прогон не съел весь дневной лимит. После ошибки авторизации или 402 цикл останавливаю, а не шлёт миллион одинаковых запросов.

Исходные данные в базе до проверки qc не затираю. Удобная схема: регистр сведений с измерениями «объект» и «вид контакта», ресурсы «исходная строка», «result», «qc», дата обработки; перенос в контактную информацию отдельной процедурой после отбора. Так можно откатиться и сравнить diff для спорных qc.

Остановка цикла при 402 или 429 для меня нормальное завершение сеанса, а не повод удваивать нагрузку на API в надежде «прорваться».

Точки встраивания: внешняя обработка для разового массового прогона; регламентное задание для новых или изменённых адресов за период; подписка на запись контакта с постановкой в очередь, если объём небольшой. В типовой без снятия с поддержки всё это ложится в расширение с собственным общим модулем и регламентом.

 

Фильтр qc и перенос в учёт

Поле qc в ответе clean - фильтр для ручной очереди, а не декорация. Расшифровки кодов и граничные значения перечислены в официальной документации DaData к методу clean; я не переписываю таблицу целиком, а завожу в конфигурации справочник или регистр: код qc и признак «нужна проверка», плюс отчёт по строкам из подозрительного диапазона.

Практика после прогона: автоматически принимаю строки с «хорошим» qc и заполненным result, остальное уходит в список оператору. Для доставки дополнительно смотрю geo_lat, geo_lon и fias_id: если координаты пустые при заполненном доме, это сигнал перепроверить исходник, а не слать курьера вслепую.

Запись в контактную информацию делаю осознанно: либо обновляю представление и структурированные поля, если конфигурация их поддерживает, либо пишу нормализованную строку в отдельный реквизит расширения «АдресДоставкиНормализованный», пока бухгалтерия не подтвердит смену юридического адреса.

Перед первым боевым прогоном я прогоняю десяток заведомо кривых и заведомо правильных строк в тестовой базе, сверяю qc и result, затем пакет из 100 строк с повторным чтением того же пакета (должен совпасть порядок). Если на платформе ниже 8.3.6, заранее решаю вопрос с JSON, иначе половина модуля окажется мёртвым грузом.

Нормализация адресов через DaData не отменяет человека на хвосте очереди qc, зато снимает с разработчика бесконечное дописывание правил для каждого нового сокращения. Держите ключи в настройках, тело запроса через ЗаписьJСОН, ответ в таблицу по именам полей, пакеты по 100 там, где это уместно, и не перезаписывайте исходник, пока qc и выборочная проверка не подтвердят, что строка стала адресом, а не красивой догадкой сервиса.

Вступайте в нашу телеграмм-группу Инфостарт

1С 8.3 DaData HTTPЗапрос JSON интеграция контрагенты ФИАС адреса нормализация адресов 1С 8.3 API clean таблица значений qc пакетная обработка

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

WEB-интеграция Разработчик Аналитик 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Оптовая торговля, дистрибуция, логистика ИТ-компания Платные (руб)

Модуль "Экспортер" — это расширение для 1С, предназначенное для автоматизации процессов выгрузки данных. Оно позволяет эффективно извлекать, преобразовывать и передавать данные из систем 1С в интеграционную платформу Spot2D. Подсистема упрощает настройку, снижает количество ручных операций и обеспечивает удобный контроль данных.

17568 руб.

20.12.2024    7323    33    4    

34

WEB-интеграция Анализ продаж Системный администратор Разработчик Пользователь 1С:Предприятие 8 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Управленческий учет Платные (руб)

Модуль "Подсистема интеграции AmoCRM с 1С" позволяет обеспечить единое информационное пространство, в котором пользователи могут эффективно управлять клиентской базой, следить за статусами сделок и поддерживать актуальность данных как в AmoCRM, так и в 1С.

60000 руб.

07.05.2019    44361    76    45    

32

Сайты и интернет-магазины WEB-интеграция Системный администратор Разработчик Пользователь 1С:Предприятие 8 1C:Бухгалтерия 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM / LOGICSTARS. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM / LOGICSTAR разных брендов в одной информационной базе в ручном и автоматическом режиме.

42700 руб.

03.08.2020    25385    41    26    

30

WEB-интеграция Системный администратор Разработчик Пользователь 1С:Предприятие 8 1C:Бухгалтерия 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена по API между конфигурацией 1С:Альфа-Авто 6 и порталом LogicStar. Позволяет работать с несколькими обменами LogicStars разных брендов (CHERY, OMODA, JAECOO, EXEED, TENET) в одной информационной базе в ручном и автоматическом режиме. Поддерживается выгрузка заказ-нарядов, реализаций товаров и товарных остатков.

20740 руб.

13.05.2025    2825    4    0    

7

WEB-интеграция Сайты и интернет-магазины Системный администратор Разработчик Пользователь Руководитель проекта 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1C:ERP Розничная и сетевая торговля (FMCG) Россия Платные (руб)

Расширение предназначено для более гибкой и быстрой выгрузки остатков и цен на сайты под управление 1С.Битрикс. Управление сайтом(БУС). Настраиваемое гибкое сопоставление складов в 1С и складов в БУС с возможностью обеспечить связь складов один-ко-многим. Настраиваемое сопоставление видов цен в 1С и типов цен в БУС. Отчеты по сравнение остатков и цен в 1С и БУС. Возможность точечной выгрузки остатков и цен.

2278 руб.

08.07.2025    2143    1    0    

2
Для отправки сообщения требуется регистрация/авторизация