Добавлено: Пятница, 13 Марта, 2009 16:07 Размещено в: Новости проекта
Убедительная просьба, если Вам надо прокачать большое количество адресов, просьба заключать их в один запрос (не более 4000 Ip в одном запросе). В скором времени будет выложен пример скрипта на perl для прокачки лога Apache.
Теперь мы подключили XML-сервис обработки запросов на определение местонахождения российских IP-адресов. Сервис обслуживается специальным сервером. Сервер получает запрос в формате XML через POST HTTP запрос, отдает ответ также в формате XML.
Сервер расположен по адресу 194.85.91.253, порт 8090, работает по протоколу HTTP. Метод GET сервером не поддерживается. Минимальный заголовок HTTP запроса выглядит следующим образом:
POST /geo/geo.html HTTP/1.1
Content-length: CL
,где CL - длина тела запроса
Формат тела запроса выглядит следующим образом:
<ipquery [id="123456"]>
<fields>
[<all/>]
[<inetnum/>]
[<inet-descr/>]
[<inet-status/>]
[<city/>]
[<region/>]
[<district/>]
[<lat/>]
[<lng/>]
</fields>
<ip-list>
<ip>62.5.128.0</ip>
<ip>144.206.192.23</ip>
….
<ip>85.44.33.22</ip>
</ip-list>
</ipquery>
,где id=”123456″ - необязательный параметр. Это идентификатор запроса, в кавычках - любые числа и буквы, ответ сервера будет содержать указанный вами id; тег <fields> содержит поля, которые вы хотите получить:
<inetnum/> - блок адресов, к которому относится искомый ip-адрес
<inet-descr/> - описание блока по базе RIPE (www.ripe.net)
<inet-status/> - статус блока по базе RIPE
<city/> - город, к которому относится искомый ip
<region/> - регион, к которому относится искомый ip
<district/> - федеральный округ РФ, к которому относится искомый ip
<lat/> - географическая широта города
<lng/> - географическая долгота города
<all/> - все вышеперечисленные поля
В теге <ip-list> содержится список ip, которые надо прокачать. Это может быть один ip, или несколько. Максимальное количество 4000 ip в одном запросе. Каждый ip обрамляется тегами <ip> и </ip>.
Формат ответа сервера:
<ip-answer id=”123456″>
<ip value=”62.5.128.0″>
<inetnum>62.5.128.0 - 62.5.128.15</inetnum>
<inet-descr>Subnetwork for VA159-RIPE</inet-descr>
<inet-status>ASSIGNED PA</inet-status>
<city>Москва</city>
<region>Москва</region>
<district>Центральный</district>
<lat>55.755787</lat>
<lng>37.617634</lng>
</ip>
….
</ip-answer>
По каждому адресу, мы получаем список полей, которые мы указали в <fields> в запросе. В вышеуказанном примере ответа в запросе был указан <all/>.
Для обращения к серверу с вашего сайта, можно использовать стандартную библиотеку HTTP (имеется практически во всех языках программирования). Подключаемся к 194.85.91.253:8090, отправляем POST запрос на /geo/geo.html, в котором содержится <ipquery>…</ipquery>. В скором времени будут выложены примеры на различных языках.
Для обращения к серверу через форму нужно вставить такой HTML код:
<form name = “index” action = “http://194.85.91.253:8090/geo/geo.html” method = “post”>
<textarea name=”address”></textarea>
<input type=”submit” value=”OK”>
</form>
Названия формы и поля <textarea> не важны. В поле textarea вставляется запрос в формате XML, указанный выше. Например:
|
16 Марта, 2009 в 15:55
Чет очень намудрили с запросом, нужно просто допустим через curl сделать запрос) и как это организовать в такой структуре?
16 Марта, 2009 в 16:06
Сервер расчитан на прокачку большого количества Ip-адресов, поэтому нецелесообразно передавать в URL по одному адресу. Если нужно смотреть по одному адресу, все равно придется отправлять POST-запрос. GET (передача ip в URL) не поддерживается.
16 Марта, 2009 в 16:44
Насколько понимаю, код должен быть таким?
$data = array(
‘address’ => ‘144.206.192.4′
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, “http://194.85.91.253:8090/geo/geo.html”);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$xml = curl_exec($ch);
curl_close($ch);
echo $xml;
16 Марта, 2009 в 16:47
п.с. вырезало все теги xml запроса, которые указаны в примере в textarea
16 Марта, 2009 в 16:59
Как это “вырезало”?
$data = array(
‘address’ => ‘144.206.192.4′
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, “http://194.85.91.253:8090/geo/geo.html”);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$xml = curl_exec($ch);
curl_close($ch);
echo $xml;
Вы не указали теги запроса. Должно быть что-то типа:
< ?php
$data = "<ipquery><fields><all/></fields><ip-list><ip>144.206.192.4</ip></ip-list></ipquery>”;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, “http://194.85.91.253:8090/geo/geo.html”);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$xml = curl_exec($ch);
curl_close($ch);
echo $xml;
?>
16 Марта, 2009 в 17:09
Угу, спасибо.
16 Марта, 2009 в 17:16
А можно эти данные возвращало тоже в xml формате, чтобы заюзать SimpleXMLElement на выходящую информацию и вообще всё было красиво?
16 Марта, 2009 в 17:42
Код, который получился на данный момент, без xml:
function getip($GetRIP)
{
$data = “”.$GetRIP.”";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, “http://194.85.91.253:8090/geo/geo.html”);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$xml = curl_exec($ch);
curl_close($ch);
//echo $xml;
$district=”!(.*?)!si”;
$region=”!(.*?)!si”;
$town=”!(.*?)!si”;
preg_match($district, $xml, $main_ar["district"]);
preg_match($region, $xml, $main_ar["region"]);
preg_match($town, $xml, $main_ar["city"]);
return array(”DISTRICT”=>$main_ar["district"][1], “REGION”=>$main_ar["region"][1],”TOWN”=>$main_ar["city"][1]);
}
echo “”; print_r(getip($_SERVER["REMOTE_ADDR"])); echo “”;
16 Марта, 2009 в 17:43
Жалко не запостить, вырезает теги удалите пожалуйста это и верхнее сообщение.
17 Марта, 2009 в 13:10
“А какие ограничения на количество запросов с одного IP и в каком временном интервале?” (c) Максим Месилов
17 Марта, 2009 в 15:05
Пока никаких ограничений, пользуйтесь на здоровье сколько угодно
17 Марта, 2009 в 15:08
Не ясна проблема, опишите поподробнее что и где вырезает
17 Марта, 2009 в 15:10
Я вас немного недопонимаю. Все данные забираются и отдаются в XML формате
17 Марта, 2009 в 15:23
function getip($GetRIP)
{
$data = “”.$GetRIP.””;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, “http://194.85.91.253:8090/geo/geo.html”);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$xml = curl_exec($ch);
curl_close($ch);
//echo $xml;
$district=”!(.*?)!si”;
$region=”!(.*?)!si”;
$town=”!(.*?)!si”;
preg_match($district, $xml, $main_ar["district"]);
preg_match($region, $xml, $main_ar["region"]);
preg_match($town, $xml, $main_ar["city"]);
return array(”DISTRICT”=>$main_ar["district"][1], “REGION”=>$main_ar["region"][1],”TOWN”=>$main_ar["city"][1]);
}
echo “”; print_r(getip($_SERVER["REMOTE_ADDR"])); echo “”;
Зачем все так усложнять. Ответ сервера специально сделан в XML, чтобы было легко парсить ответ. Вот пример на PERL для прокачки IP:
#!/usr/bin/perl
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
my $xml_query = “<ipquery><fields><all/></fields><ip-list><ip>144.206.192.4</ip><ip>81.176.209.240</ip></ip-list></ipquery>”;
my $response = $ua->post(’http://194.85.91.253:8090/geo/geo.html’,Content => $xml_query);
if ($response->is_success) {
print $response->content; #Эта строка контента, из нее можно парсить необходимую информацию.
}
else {
die $response->status_line;
}
18 Марта, 2009 в 8:27
спасибо за сервис!
Вот только что-то ваша собственная форма не работает - выдаёт incorrect request
18 Марта, 2009 в 14:15
Вот только что-то ваша собственная форма не работает - выдаёт incorrect request
Сервис находится в стадии тестирования, поэтому баги возможны. Какой именно запрос у Вас не работает? Напишите его пожалуйста в коментарии
18 Марта, 2009 в 15:35
Какой код на PHP нужно поставить, что-то не работаю выше описаные
18 Марта, 2009 в 16:54
Граждане программисты на PHP!!! Выкладывайте свои рабочие варианты скриптов-клиентов нашего сервера
18 Марта, 2009 в 19:08
Задача - определение города посетителя сайта. 1 запрос - 1 IP.
По хорошему, массив результирующий сделать двумерным, первый ключ - ip (именно тот, что передается в функцию в качестве параметра), второй - параметр из инфы об IP (аля город, страна, etc).
<?php
function get_ip_info($ip)
{
$xml_encoding = ‘windows-1251′;
$in_charset = ‘UTF-8′;
$out_charset = ‘windows-1251′;
$GeoIP = array();
$xml_query = ” . $ip . ”;
$xml_response = ”;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, ‘http://194.85.91.253:8090/geo/geo.html’);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_query);
$xml_response .= curl_exec($ch);
curl_close($ch);
$xml = new SimpleXMLElement($xml_response);
$GeoIP = array(
‘inetnum’ => ln_str_encode($xml->ip->inetnum, $in_charset, $out_charset),
‘inet-descr’ => ln_str_encode($xml->ip->inet-descr, $in_charset, $out_charset),
‘inet-status’ => ln_str_encode($xml->ip->inet-status, $in_charset, $out_charset),
‘city’ => ln_str_encode($xml->ip->city, $in_charset, $out_charset),
‘region’ => ln_str_encode($xml->ip->region, $in_charset, $out_charset),
‘district’ => ln_str_encode($xml->ip->district, $in_charset, $out_charset),
‘lat’ => ln_str_encode($xml->ip->lat, $in_charset, $out_charset),
‘lng’ => ln_str_encode($xml->ip->lng, $in_charset, $out_charset),
);
return $GeoIP;
}
/**
* Convert string to requested character encoding.
* This function performs a character set conversion on the string str from in_charset to out_charset.
*
* @param string $str
* @param string $in_charset
* @param string $out_charset
* @return string|false results of {@link _read_cache_file()}
*/
function ln_str_encode($str, $in_charset, $out_charset)
{
if (function_exists(’mb_convert_encoding’))
{
return mb_convert_encoding($str, $out_charset, $in_charset);
}
else
{
return iconv($in_charset, $out_charset, $str);
}
}
$ip_info = get_ip_info($_SERVER['REMOTE_ADDR']);
/*
foreach ($ip_info as $key => $val)
{
echo $key . ‘: ‘ . $val . ”;
}
*/
echo ‘Город: ‘ . $ip_info['city'] . ”;
echo ‘Регион: ‘ . $ip_info['region'] . ”;
echo ‘Округ: ‘ . $ip_info['district'] . ”;
?>
19 Марта, 2009 в 11:14
>>> Какой именно запрос у Вас не работает? Напишите его пожалуйста в коментарии
Всё очень просто
Решил попробовать Вашу же форму (она приведена в конце поста). ИП указал одного из гугловских серверов. Жму ‘Ок’ - ошибка
19 Марта, 2009 в 13:09
Всё очень просто
Решил попробовать Вашу же форму (она приведена в конце поста). ИП указал одного из гугловских серверов. Жму ‘Ок’ - ошибка
Все работает. Возможно вы забыли обрамить запрос каким-либо из обязательных XML тегов. Помимо искомых ip (их надо обрамлять тегами <ip> и </ip>, например <ip>1.2.3.4</ip>) в форму надо вбить теги <ip-list>, <fields>, <ipquery>. Формат подробно описан в посте! Если в форму ввести только ip без XML тегов, сервер выдаст ошибку “incorrect request”.
19 Марта, 2009 в 14:07
Может быть, как необязательное поле/атрибут добавить кодировку?
19 Марта, 2009 в 14:24
Хорошее предложение, возможно в скором мы реализуем данную функцию. Пока сервер отдает ответ только в windows-1251
20 Марта, 2009 в 10:57
Ктонибудь проверял код Laney ? Я плохо в php шарю и у меня ничего не выходит
20 Марта, 2009 в 19:08
Как вариант, но советую почитать комменты и добавить необходимое, в часности кеширование по IP и установки CURLOPT_CONNECTTIMEOUT.
п.с. Данный сервис просто отличный, тем кто не юзает хеш бан надо замутить, чтобы с одним и тем же запросом в день по 20 раз не обращались. Он всё равно не изменится, а точнее вероятность этого крайне мала.
Сам вариант кода: http://sunswordred.habrahabr.ru/blog/54728/.
23 Марта, 2009 в 9:35
RE: Ктонибудь проверял код Laney ? Я плохо в php шарю и у меня ничего не выходит
Проверил, работает.
Значения переменных
$xml_query и $xml_response укажите.
23 Марта, 2009 в 13:28
п.с. Данный сервис просто отличный, тем кто не юзает хеш бан надо замутить, чтобы с одним и тем же запросом в день по 20 раз не обращались. Он всё равно не изменится, а точнее вероятность этого крайне мала.
Сам вариант кода: http://sunswordred.habrahabr.ru/blog/54728/.
Если бы по 20 раз… по 20000 раз обращаются
сейчас вроде бы поубавили пыл.
Спасибо Вам за отзыв, будем работать над улучшением сервиса!
24 Марта, 2009 в 8:07
вопщем я так и не разобрался как их xml ответа вычленить нужную информацию… сделал по топорному. (мне нужны были только город и регион)
<?php
$ip=$_SERVER['REMOTE_ADDR'];
$ip_len=strlen($ip);
function get_city($ip)
{
$xml_encoding = ‘windows-1251′;
$in_charset = ‘UTF-8′;
$out_charset = ‘windows-1251′;
$xml_query = “”.$ip.”";
$xml_response = “”;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, ‘http://194.85.91.253:8090/geo/geo.html’);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_query);
$xml_response .= curl_exec($ch);
curl_close($ch);
return $xml_response;;
}
function get_region($ip)
{
$xml_encoding = ‘windows-1251′;
$in_charset = ‘UTF-8′;
$out_charset = ‘windows-1251′;
$xml_query = “”.$ip.”";
$xml_response = “”;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, ‘http://194.85.91.253:8090/geo/geo.html’);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_query);
$xml_response .= curl_exec($ch);
curl_close($ch);
return $xml_response;;
}
function ln_str_encode($str, $in_charset, $out_charset)
{
if (function_exists(’mb_convert_encoding’))
{
return mb_convert_encoding($str, $out_charset, $in_charset);
}
else
{
return iconv($in_charset, $out_charset, $str);
}
}
$city=get_city($ip);
$minus=$ip_len+102;
$length=strlen($city)-$minus;
$start=$ip_len+76;
$city=iconv_substr ($city, $start , $length);
$region=get_region($ip);
$minus=$ip_len+106;
$length=strlen($region)-$minus;
$start=$ip_len+78;
$region=iconv_substr ($region, $start , $length);
?>
на выходе: город - $city, регион - $region.
25 Марта, 2009 в 16:55
Для того чтобы получать только город и регион, запрос должен выглядеть следующим образом:
<ipquery>
<fields>
<city/>
<region/>
</fields>
<ip-list>
<ip>1.2.3.4</ip>
<ip>5.6.7.8</ip>
….
<ip>9.10.11.12</ip>
</ip-list>
25 Марта, 2009 в 16:58
2Администратор:
Спасибо огромное за сервис! Бесценная информация для анализа аудитории сайта по регионам.
Однако не помешалобы в ответе вашего шлюза еще один параметр - название провайдера (ISP)
как например выводится в ответе на запрос http://www.vline.ru/ip/?ip=x.x.x.x
(поля netname и desc или хотябы только netname)
Есть ли подобная информация в Вашей базе?
Если да, то сможете ли Вы ее возвражать в ответе на запрос?
Не планируете ли Вы создать HTTP-GET запрос по единственному IP по образцу приведенному мной выше? например чтото вроде http://194.85.91.253:8090/?ip=x.x.x.x
Планируете ли Вы ввести ограничение на кол-во запрос с одного IP за единицу времени?
Если да, то какой лимит будет установлен?