При работе над проектом с использованием API Яндекс.Карт возникает задача определения географических координат для множества точек.
Можно использовать для этого два подхода.
- Воспользоваться функцией геокодирования и каждый раз при выводе определять координаты объекта по его почтовому адресу.
У этого подхода есть два недостатка: геокодеру необходимо некоторое время на обработку запроса и ответ, еще количество обращений к сервису геокодирования ограничено 25000 запросов для одного API-Ключа в сутки.
2. Предварительно использовать сервис определения координат по адресу http://api.yandex.ru/maps/tools/getlonglat/
Если точек много, то вручную это очень утомительно.
Я предлагаю автоматизировать процесс определения координат.
Для этого мы будем использовать возможность формирования HTTP-запроса, подробнее смотри http://api.yandex.ru/maps/geocoder/doc/desc/concepts/geocode.xml
С начала мы в базе данных MySQL создадим таблицу для хранения информации об объектах.
Это можно сделать, используя утилиту PhpMyAdmin или SQL-запросом:
CREATE TABLE IF NOT EXISTS `markers_geocod` ( `id` int(11) NOT NULL auto_increment, `name` varchar(255) NOT NULL, `address` varchar(100) NOT NULL, `lat` varchar(255) NOT NULL, `lng` varchar(255) NOT NULL, `telephon` varchar(30) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; |
После этого заполняем таблицу тестовыми данными вида:
Наименование, адрес, координаты – долгота, широта (0.0, 0.0), номер телефона.
Для обработки ответа геокодера нам понадобиться работающее расширение php – библиотека curl (входит в состав php5).
Если Вы работаете на локальном компьютере необходимо убрать точку с запятой возле строки extension=php_curl.dll в файле php.ini и перезапустить сервер.
На хостинге данная библиотека, как правило, уже бывает задействовано.
Полный код примера:
<?php set_time_limit(360); require("config.php"); define("MAPS_HOST", "geocode-maps.yandex.ru"); define("KEY", "AIW0o0kBAAAAkwyUMwMAEkDz8ddCkU0UnlyLEu4ddFBXhQQAAAAAAAAAAAA1Md4ULCo5QbciEo5T26eV1lhuEQ=="); // Select all the rows in the markers table $query = "SELECT * FROM markers_geocod"; $result = mysql_query($query); if (!$result) { die("Invalid query: " . mysql_error()); } // Initialize delay in geocode speed $delay = 0; $base_url = "http://" . MAPS_HOST . "/1.x/?geocode="; // Iterate through the rows, geocoding each address while ($row = @mysql_fetch_array($result)) { $exp_str1 = explode(",", $row["address"]); $address = implode($exp_str1, ",+"); $id = $row["id"]; $request_url = $base_url . urlencode($address)."&key=" . KEY; $ch = curl_init($request_url); $fp = fopen("example_homepage.txt", "w+"); curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); curl_exec($ch); curl_close($ch); fclose($fp); $lines = file("example_homepage.txt"); if($lines[5] == '<ygeo:request>несуществующая улица</ygeo:request>'){ echo 'адрес: ', $row["address"], ' ', 'не найден', '<br><br>'; } else { foreach ($lines as $line_num => $line) { if(strpos($line, "<pos>")!= FALSE) { echo "Строка #<b>{$line_num}</b> : " . htmlspecialchars($line) . "<br>"; $line = trim ($line); $coord = substr($line, 5, -6); echo $coord; $newcoord = explode(" ", $coord); $lat1 = $newcoord[1]; $lng1 = $newcoord[0]; echo '<br><br>'; $query = sprintf("UPDATE markers_geocod " . " SET lat = '%s', lng = '%s' " . " WHERE id = '%s' LIMIT 1;", mysql_real_escape_string($lat1), mysql_real_escape_string($lng1), mysql_real_escape_string($id)); $update_result = mysql_query($query); if (!$update_result) { die("Invalid query: " . mysql_error()); } } } echo '<br><br>'; } } ?> |
С начала мы последовательно читаем из таблицы адреса объектов и формируем ссылку для запроса в формате http:// geocode-maps.yandex.ru /1.x/?geocode= строка с адресом, который требуется геокодировать в координаты &key= API-ключ Яндекс.Карт
После этого ответ геокодера мы записываем в файл example_homepage.txt и обрабатываем его, находим строку с координатами и заносим их в базу данных.
После этого мы можем сформировать из данных таблицы YMapsML-файл и вывести его на карте.
Еще одно замечание.
Если геокодер не нашел данный адрес в своей базе, он ищет ближайший по адресу.
Например, мы ищем дом по адресу Нижний Новгород, Казанское шоссе, 10/6, а геокодер определяет координаты дома по адресу Россия, Нижегородская область, Нижний Новгород, Казанское шоссе, 10.
Поэтому, после автоматического геокодирования необходимо провести проверку.
Огромное спасибо автору этого сайта за отличный материал по Картам.
Я мучился с Яндекс.картами очень долгое время и много было непонятного. На оф.сайте карт настолько запутанная документация что разобраться в ней для меня составило многих недель изучения, а вот у вас на сайте Описано и даны примеры. Я в восторге.
Еще раз спасибо!
Здравствуйте, я начал делать по вашему примеру на Денвере. Нашел в файле php.ini нужную строку, убрал точку с запятой, перезапустил сервер, но вылетает ошибка: Fatal error: Call to undefined function curl_init() in Z:homelocalhostwwwmyphpconfig_2.php. Как видно не найдена функция curl_init() …Подскажите, что делать?
Я извиняюсь, что забыл написать следующее. Поддержка функции curl_init() отсутствует в Денвере. Чтобы все нормально работало не достаточно убрать точку с запятой, нужно скачать полную версию PHP с сайта http://www.php.net/downloads.php — файл PHP 5.2.12 zip package [10,268Kb] — 17 December 2009
Разархивировать его и все содержимое папки php-5.2.12-Win32 скопировать в папку Имя диска:WebServersusrlocalphp5 Денвера, после чего перезапустить сервер.
Хорошее дополнение. Надо на локальном сделать. Спасибо всем! Особенно admin!
Здравствуйте У меня такая ошибка вылезла:
Warning: mysql_query() [function.mysql-query]: Access denied for user ‘ODBC’@’localhost’ (using password: NO) in Z:homegeo.locwwwindex.php on line 13
Warning: mysql_query() [function.mysql-query]: A link to the server could not be established in Z:homegeo.locwwwindex.php on line 13
Invalid query: Access denied for user ‘ODBC’@’localhost’ (using password: NO)
Вы в файле config.php правильно прописали параметры для соединения с базой данных: имя бд, имя пользователя и пароль?
Здравствуйте!
Ваш вариант множественного геокодирования возвращает несколько вариантов координат, по какому принципу выбирается единственный, который заносится в таблицу?
Как можно задать зону поиска, например Москву?
Спасибо заранее.
Нужно ограничить область поиска, для этого у геокодера существует параметр boundedBy, подробнее см. статью Как ограничить область поиска?. У html-геокодера, который используется в скрипте заметки, задать область поиска можно с помощью параметров ll и spn, а с помощью параметра rspn ограничить поиск только заданной областью. Подробнее о параметрах здесь
Добрый день!
Еще один вопрос по геокодеру. Если взять для примера адрес: Ленинский 53 и геокодировать его непосредственно через сайт maps.yandex.ru, то в результате выдается Россия, Москва, Ленинский проспект, 53с1 или http://maps.yandex.ru/-/CBQnuLZj . В случае использования представленного геокодера или использования сервиса — http://api.yandex.ru/maps/tools/getlonglat/ выдается: Ленинский проезд, Россия, Московская область, Юбилейный. И так по многим адресам… С чем это может быть связано?
Подскажите новичку пожалуйста. Какие строчки в коде и на что поменять, если адрес в базе состоит из нескольких полей? В примере одно поле «address», а у меня в базе из нескольких полей — «country», «admn-area», «street», «house», «house», «build».