:-[ Домашняя страница девелопера ] :( + φ = :D

Определение города пользователя по его IP на perl

Иногда нужно определить местоположение пользователя, чтобы предложить ему например, ближайший офис, если фирма имеет один сайт и несколько дилеров в регионах. Это можно сделать с помощью бесплатного сервиса http://ipgeobase.ru/ Поиск географического местонахождения IP-адреса, выделенного RIPE локальным интернет-реестрам (LIR-ам) для Российской Федерации. Поиск IP адреса осуществляется с точностью до города. База обновляется ежедневно!

Ограничений на использование сервиса практически нет.

Здесь представлено определение города пользователя на perl. Решение на php было предложено на самом сервисе в комментариях к блогу.
Буду признателен гуру перла за оптимизацию кода.

#!/usr/bin/perl

# скрипт определения региона и города пользователя по его IP через сервис http://ipgeobase.ru/

use LWP::UserAgent;
use XML::DOM;
use Encode;
use strict;

print "Content-type: text/html; charset=windows-1251\n\n";
print "<pre>";

# получаем айпишник
my $ip = $ENV{ 'REMOTE_ADDR' };
# если в этой строке окажется ipv6-адрес, то определяем как москву
if( $ip !~ m~^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$~ ) {
   $ip = '194.85.91.253';
} # End if

my %resp = get_geo_xml( $ip );
if( !$resp{ 'error' } ) {
   # from utf8 to cp1251
   print "$ip \n";
   print  Encode::encode( 'cp1251', get_city( $resp{ 'response' } ) );
   
} else {
   print 'Error: ';
   print $resp{ 'response' };
   
} # End if

print "</pre>";


################################################################################
# return hash with 2 fields:
# - response - xml from ipgeobase
# - error - error flag
# 
sub get_geo_xml {
   my ( $ip ) = @_;
   
   my %result = (
      response => '', 
      error => 0 
   );
   
   my $ua = LWP::UserAgent->new;
   my $xml_query = qq!
      <ipquery><fields><all/></fields><ip-list><ip>$ip</ip></ip-list></ipquery>
   !;

   my $response = $ua->post('http://194.85.91.253:8090/geo/geo.html',Content => $xml_query);

   if( $response->is_success ) {
      # Эта строка контента, из нее можно парсить необходимую информацию.
	  # описание формата ответа есть на сайте сервиса
      $result{ 'response' } = $response->content; 
   }
   else {
      $result{ 'error' } = 1;
      $result{ 'response' } = $response->status_line;
   }

   return %result;

} # End sub get_geo_xml


################################################################################
# return city from xml
# 
sub get_city {   
   my ( $xml_str ) = @_;
   
   my $parser = new XML::DOM::Parser;
   my $doc = $parser->parse( $xml_str );
   my $parent = $doc->getDocumentElement;   
   my $city = $parent->main::elvalue('city');
   
   return $city;
   
} # End sub get_city


################################################################################
# return element value, with specified tag-name
# 
sub elvalue {
   my ($self, $nodetag) = @_;
   my $text = '';
   foreach ($self->getElementsByTagName($nodetag)->item(0)->getChildNodes) {
      $text .= $_->getNodeValue if( 
         $_->getNodeType == TEXT_NODE ||
         $_->getNodeType == CDATA_SECTION_NODE
      );
   }
   return $text;
     
} # End sub elvalue

Вернуться к списку


В админку