Блог API Яндекс.Карт

Получение координат для списка адресов

В данной статье  будет рассмотрен вариант получения координат для списка адресов с использованием PHP и MySQL. Полученные координаты можно будет использовать для отображения на карте списка ваших объектов (например, местоположение офисов компании, пользователей и пр.). Если вы хотите обрабатывать массивы адресов на клиенте, обратите внимание на статью «Множественное геокодирование».

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

Внимание. Если у вас есть таблица, содержащая адреса, которые необходимо геокодировать, то вы можете добавить в нее поле coords и перейти к настройке скрипта.

Таблица имеет три поля:

  • id – уникальный идентификатор адреса;
  • address – адрес, который необходимо геокодировать;
  • coords – координаты.
Создать таблицу можно, используя любую оболочку управления БД (например, phpMyAdmin), либо выполнив следующий sql-код:
CREATE TABLE `addresses` (
  `id` int(3) NOT NULL auto_increment,
  `address` varchar(1000) NOT NULL,
  `coords` varchar(50) NOT NULL,
  PRIMARY KEY  (`id`)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

Далее заполните таблицу адресами, например, так:

INSERT INTO `addresses` VALUES (1, 'Москва, ул. Льва Толстого, 16', '');

INSERT INTO `addresses` VALUES (2, 'Санкт-Петербург, Свердловская набережная, 44', '');

INSERT INTO `addresses` VALUES (3, 'Екатеринбург, ул. Хохрякова, 10', '');

INSERT INTO `addresses` VALUES (4, 'Новосибирск, ул. Красноярская, 35', '');

INSERT INTO `addresses` VALUES (5, 'Казань, ул. Спартаковская 6, 11', '');

INSERT INTO `addresses` VALUES (6, 'Киев, ул. Луначарского, 4', '');

INSERT INTO `addresses` VALUES (7, 'Одесса, пр. Шевченко, дом 4-Д', '');

INSERT INTO `addresses` VALUES (8, 'Симферополь, ул. Героев Аджимушкая, 6/13', '');

INSERT INTO `addresses` VALUES (9, 'абракадабра', '');

Геокодирование будем производить с помощью следующего скрипта:

<?

    // Параметры

    $config = Array(

        'host' => 'localhost',

        'user' => 'root',

        'password' => '',

        'dbname' => 'test',

        'tablename' => 'addresses',

        'apikey' => 'ВАШ API-КЛЮЧ'

    

    // Соединение с сервером СУБД

    $dp = mysql_connect($config['host'], $config['user'], $config['password']) or die('Ошибка при подключении к серверу СУБД: '.mysql_error()

    // Выбор нужной БД

    mysql_select_db($config['dbname']) or die('Невозможно выбрать БД с именем "'.$config['dbname'].'": '.mysql_error()

    // Назначение кодировки

    mysql_query('SET NAMES utf8');

    // Выборка данных из таблицы

    $addresses = mysql_query('SELECT * FROM '.$config['tablename']) or die('Ошибка при выполнении запроса к таблице "'.$config['tablename'].'": '.mysql_error()

    // Общее количество адресов и количество адресов, в обработке которых произошла ошибка

    $countGeocode = $countGeocodeFault = 0;

    // Обработка адресов

    $result = '<table style="width:600px">';

    while ($row = mysql_fetch_assoc($addresses)) {

        $countGeocode++;

        // Обращение к http-геокодеру

        $xml = simplexml_load_file('http://geocode-maps.yandex.ru/1.x/?geocode='.urlencode($row["address"]).'&key='.urlencode($config['apikey']).'&results=1');

        // Если геокодировать удалось, то записываем в БД

        $found = $xml->GeoObjectCollection->metaDataProperty->GeocoderResponseMetaData->found;

        if ($found > 0) {

            $coords = str_replace(' ', ',', $xml->GeoObjectCollection->featureMember->GeoObject->Point->pos);

            $result .= '<tr><td>'.$row['address'].'</td><td>'.$coords.'</td></tr>';

            mysql_query("UPDATE `{$config['tablename']}` SET coords = '".mysql_real_escape_string($coords)."' WHERE id = {$row['id']}") or die("Ошибка при обновлении данных в таблице: ".mysql_error()

        } else {

            $result .= '<tr style="color:red"><td>'.$row['address'].'</td><td>ошибка</td></tr>';

            $countGeocodeFault++;

        }

    };

    $result .= '</table>';

    // Вывод результата

    echo $result;

    // Закрытие соеденинения с сервером

    mysql_close($dp);

    // Вывод общего количество прогеокодированных результатов

    if ($countGeocode) {

        echo '<div style="margin-top:1em">Всего обработано адресов: '.$countGeocode.'</div>';

        if ($countGeocodeFault) {

            echo '<div style="color:red">Не удалось прогеокодировать: '.$countGeocodeFault.'</div>';

        }

    } else {

        echo '<div>Таблица с адресами пуста.</div>';

    }

?>Скачать php-файл

Перед запуском скрипта необходимо прописать ваши параметры доступа к БД, а также указать API-ключ (получить ключ можно с помощью специальной формы

$config = Array(

    'host' => 'localhost',

    'user' => 'root',

    'password' => '',

    'dbname' => 'test',

    'tablename' => 'addresses',

    'apikey' => 'ВАШ API-КЛЮЧ'

После внесения изменений выполните скрипт.

В окно браузера будет выведены найденные координаты и сообщения об ошибках, если некоторые адреса прогеокодировать не удалось. Также скрипт обновит записи в таблице, добавив найденные координаты.

Рассмотренный скрипт демонстрирует пример геокодирования списка адресов. Вы можете его модернизировать и изменять по своему усмотрению.

Если у вас возникли вопросы при использовании предложенного скрипта, то вы их всегда можете задать в нашем клубе разработчиков.

46 комментариев

Не работает..


Выдает ошибку в строке


$xml = simplexml_load_file('http://geocode-maps.yandex.ru/1.x/?geocode='.urlencode($row["address"]).'&key='.urlencode($config['apikey']).'&results=1');


все параметры под свой сервер настроил..


ошибка  http://zoovet.ru/css/php.php

Не до конца все настроили.

Ошибки  "URL file-access is disabled in the server configuration in " и "failed to open stream: no suitable wrapper could be found in" означают, что нужно включить опцию allow_url_fopen в php.ini.

Комментарий удалён
А совет twirl вам не помог?
 
Случайно удалил пост
Получилось вот так :

??????, ??. ???? ????????, 16 ошибка
?????-?????????, ???????????? ??????????, 44 ошибка
????????????, ??. ?????????, 10 ошибка
???????????, ??. ????????????, 35 ошибка
??????, ??. ????????????? 6, 11 ошибка
????, ??. ????????????, 4 ошибка
??????, ??. ????????, ??? 4-? ошибка
???????????, ??. ?????? ??????????, 6/13 ошибка
??????????? ошибка

Всего обработано адресов: 9
Не удалось прогеокодировать: 9

Какие есть мысли? ))

К сожалению нет.
Александр
28 января 2016, 06:26
кодировка ;) mysql
Евгений Язев
28 января 2016, 06:26

//mysql_query('SET NAMES utf8');

Делаю тоже самое. Только на VB.


Чтобы парсить XML документ хочу использовать функцию SelectSingleNode -


SelectSingleNode("ymaps/GeoObjectCollection/featureMember/GeoObject/Point/pos") выдаёт NULL.


Правильно ли я написал путь?


С тестовым примером функция работает.

тож что то не работает.

А в

$xml = simplexml_load_file('http://geocode-maps.yandex.ru/1.x/?geocode='.urlencode($row["address"]).'&key='.urle

ncode($config['apikey']).'&results=1');

слешеки не надо экранировать?

По каждому адресу ошибка : (

Ошибку дает.

 

Ошибка при обновлении данных в таблице: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1

 

Что не так?

You have an error in your SQL syntax

У вас ошибка в запросе. Insert не правильный.

Евгений Язев
28 января 2016, 06:26

в моем случае был не тот тип данных в инсерте

У меня код заработал после того как я убрал обработку ключа:

$xml = simplexml_load_file('http://geocode-maps.yandex.ru/1.x/?geocode='.urlencode($row["address"]).'&key='.$config['apikey'].'&results=1');

 

т.е. передал параметр &key= без urlencode()

Естественно. ApiKey содержит "==" :)

Привет, если не сложно помогите пожалуйста.
Есть список адресов и надо координаты получить.
К Сожалению не чего не понимаю в PHP =(

Пишите если все еще актуально . 

Я реализовал данную задачу имея нулевые знания в PHP. 

Либо, если необходимость разовая, скиньте список.

выложи исходник. сделал всё всеравно по каждому адресу ошибка.

Еще актуально?

Артур Ялалтдинов
18 февраля 2018, 19:17
Ibragim,
актуально)

Запрос "город, улица, дом " - возвращает координаты дома - всё верно один результат

Запрос "город, улица, абракадабра " - возвращает координаты города улицы - один результат(

<found>1found>

) типа всё ок !! - бред т.е. не учитываются опечатки в названиях улиц и домах.

Подскажите новичку пожалуйста. Какие строчки в коде и на что поменять, если адрес в базе состоит из нескольких полей? В примере одно поле "address", а у меня в базе из нескольких полей - "country", "admn-area", "street", "house", "house", "build".

вам надо склеить запрос из этих полей

// Обращение к http-геокодеру

        $xml = simplexml_load_file('http://geocode-maps.yandex.ru/1.x/?geocode='.urlencode($row["country"]). ', ' .urlencode($row["street"]). ', ' .urlencode($row["house"]).'&'

...

 

 

Спасибо большое за помощь.  Подскажите пожалуйста, а как поправить код, чтобы координаты записывались не в поле базы "coords", а разбивались и записывались в два поля - "lon" и "lat"

 

 я пхп не очень хорошо знаю

вы  какие поля имеете ввиду?

сейчас пишется в базу данных в одно поле "coords" - координаты 60.065402,42.251598,  а хотелось бы в два поля в базе данных "lon" и "lat" , соответственно координату  60.065402 в поле "lon", а координату 42.251598 в поле "lat".

 

И почемуто всем объектам присваиваются одни и теже координаты 60.065402,42.251598. (адреса в полях базы данных "country", "street", "house" абсолютно разные ).

 

 

сейчас пишется в базу данных в одно поле "coords" - координаты 60.065402,42.251598,  а хотелось бы в два поля в базе данных "lon" и "lat" , соответственно координату  60.065402 в поле "lon", а координату 42.251598 в поле "lat".

наверное надо вызвать split по запятой "," или кажется в пхп это называется explode

Василий Степанов
28 января 2016, 06:26
для записи координат в lon и lat делаем следующее:
вместо
$coords = str_replace(' ', '
', $xml->GeoObjectCollection->featureMember->GeoObject->Point->pos);

пишем
            $coords = explode(' ', $xml->GeoObjectCollection->featureMember->GeoObject->Point->pos);

а в таблицу делаем запись SET lon="'$coords[1]'", lat="'$coords[0]'"
только проверяйте где lon где lat, если неправильно написал - поменяйте [0] на [1]
Роман Макаров
28 января 2016, 06:26

Не работает.

Можно-ли как-то установить таймаут на ожидание загрузки XML-файла на случай если сервер геокодера будет недоступен и XML файл не загрузится? А то в этом случае скрипт очень долго висит и вываливаются сообщения об ошибках

И еще такой вопрос: почему http геокодер возвращает координаты не в том порядке, в каком их следует указывать при построении карты? Т.е возвращается пара долгота-широта,  ведь при построении нужно указывать широта- долгота. Неудобно же) Не сразу догадался поменять их местами). Или я что-то не так делаю?  Параметр coordorder не трогал- все по умолчанию

В версии 2.0 API мы поменяли порядок координат по-умолчанию чтобы было «как у всех». А вот геокодер у нас все еще версии 1.х. 

Ссылка на php-файл для скачивания не работает. Восстановите, пожалуйста.

Михеев Анатолий
28 января 2016, 06:26

Подскажите, а как мне получить список координат для 20 000 адресов и чтоб не вылазила 504 ошибка?

Евгений Вдовенко
28 января 2016, 06:26

Присоединяюсь к вопросу: нужно обработать 100 000 адресов. Подскажите, как?

Михеев Анатолий
28 января 2016, 06:26

Не нашли решение?

Решение не нашли !Подскажете? 89818370181@mail.ru

Записываейте состояние базы. На каком Id вылетела, с того при переконекте пусть начинает, часик и дело сделано

У меня на нескольких тысячах ни разу не вылетала ни какая ошибка, поставил время выполнения скрипта, в интерпретаторе, в десятки минут и вперёд

 

В чём проблема?

 

с помощью класса https://tech.yandex.ru/maps/doc/jsapi/2.1/dg/concepts/geocoding-docpage/#multi-geocoder тоже вылезает ошибка?

 

Здравствуйте!

В строке $xml = simplexml_load_file('http://geocode-maps.yandex.ru/1.x/?geocode='.urlencode($row["address"]).'&key='.urlencode($config['apikey']).'&results=1'); ошибка failed to open stream: HTTP request failed! HTTP/1.1 400 Bad reques. Все советы из комментариев перепробовал. Какой ключ использовать для localhost? Есть ли геокодер 2.х?

Спасибо!

Видно потому что нужно читать документацию актуальную на геокодер, где Вы там какой key нашли?

Хватит и адреса одного

я сделал чтобы координаты геокодировались в БД на сервере один раз, все координаты отлично записались в БД, но теперь другая проблема, они записаны не в той последовательности, которая нужна при построение карты, не подскажите как поменять широту с долготой местами?

В запросе поменять местами SELECT широта, долгота FROM..' на 'SELECT долгота, широта FROM...'

Если Вы гениально сохранили их обе в одну ячейку), то сперва разбейте explode - Функция PHP, если обращение к ним редкое, можно в базе прямо SQL, но так они при каждом запросе будут разбиваться заново

Можно SQL разбить. Создать новую таблицу и из существующей сперва селектить id и координаты, после раскладывать их на две ячейки в новую с записью id, затем можно их записать в вашу первую, рабочую таблицу по этим id. Теоретически SQL способен даже в ту же самую таблицу писать, но это не приветствуется

 

tswetckowa.viktoria2016
28 января 2016, 06:26

list($lo, $lu) = explode(",", $coords);

 $result .= ''.$row['address'].''.$lu.'<td>'.$lo.'';

 

перед UPDATE

         

А как увеличить точность?

Нужно чтобы левые населённые пункты не находило.

Тут, к примеру, даже для "абракадабра" найдены координаты.

Также может найти неправильно похожие сёла.

Добрый день.

 

Для себя вырезал такой код:

 

$adress = "Барнаул, ул. Зелёная роща 11";$key = "***==";        // Обращение к http-геокодеру        $xml = simplexml_load_file('http://geocode-maps.yandex.ru/1.x/?geocode='.urlencode($adress).'&key='.urlencode($key).'&results=1');        $found = $xml->GeoObjectCollection->metaDataProperty->GeocoderResponseMetaData->found;        if ($found > 0) {            $coords = str_replace(' ', ',', $xml->GeoObjectCollection->featureMember->GeoObject->Point->pos);            $result .= $adress.' - '.$coords;        } else {            $result .= $adress.' - ошибка';        }    // Вывод результата    echo $result;

 

Цель: получить координаты конкретного адреса. Ни чего ни куда записывать не нужно.

 

Локално ругается на строчку: $xml = simplexml_load_file('http://geocode-maps.yandex.ru/1.x/?geocode='.urlencode($adress).'&key='.urlencode($key).'&results=1');

 

На сервере просто печатает: Адрес - ошибка.

 

Пробовал заходить на сформированный адрес - пишет Invalid Key, без Key xml-страничка хорошо формируется.

 

Подскажите куда копать. Уже неделю бьюсь :(

Все API Карт недавно переехали на https only доступ, Вам необходимо поддержать изменения на своей стороне.

 

Узнавать обо всех изменениях на сервисе можно, подписавшись на рассылку обновлений (кнопка «Подписаться» на страницах API) или в нашем клубе по метке «обновления».

Менял, тоже ни чего хорошего. Но проблему уже решил, немного коряво, но работает.

а как исправили, подскажите?