[PHP] Làm thế nào lấy được thông tin của địa chỉ IP ?

Trong bài viết trước, tôi đã giới thiệu đến các bạn cách lấy địa chỉ IP của khách viếng thăm trang web. Và trong bài viết này, tôi sẽ giúp các bạn lấy thêm thông tin liên quan đến địa chỉ IP như đất nước, vùng miền, tọa độ (kinh độ và vĩ độ)…Với những thông tin này sẽ giúp các bạn đánh giá, khảo sát và có cái nhìn tổng quát về khách viếng thăm website tốt hơn.

Thông thường sẽ có 2 cách chính để bạn lấy được những thông tin cần thiết từ địa chỉ IP. Đó là dựa vào những website có cung cấp sẵn API/service để lấy thông tin hoặc download và truy xuất từ những Database có chứa sẵn thông tin liên quan đến địa chỉ IP.

1, Giới thiệu một số website cung cấp API/service để lấy thông tin

a, hostip.info

Khi sử dụng API từ trang web này, các bạn sẽ có những sự lựa chọn sau đây để lấy thông tin

  • get_html.php: Trả về thông tin liên quan dưới định dạng HTML hoặc XML
  • get_json.php: Trả về thông tin với định dạng JSON
  • country.php: Lấy thông tin đất nước chứa địa chỉ IP
  • flag.php: Lấy quốc kỳ của đất nước chứa địa chỉ IP (thường được dùng trong thẻ <img />)

Và phương thức sử dụng của trang web này là phương thức GET. Có 2 tham số chính thường được dùng là:

  • ip: Chứa địa chỉ IP
  • position: Xác nhận có muốn lấy thông tin tọa độ (kinh độ, vĩ độ) hay không

Một đoạn code nhỏ mà tôi dùng để lấy thông tin như sau

<?php
	$ip = "12.215.42.19";

	$url = "http://api.hostip.info/get_json.php?ip=" . $ip . "&position=true";
	$json_data = array();
	$json_data = json_decode(file_get_contents($url), true);

	echo "Latitude: " . $json_data['lat'] . "<br />";		// Latitude: 33.0582
	echo "Longitude: " . $json_data['lng'] . "<br />";		// Longitude: -97.5159
?>

b, ipinfo.io

Thông tin liên quan đến địa chỉ IP được trang web này cung cấp cho người dùng dưới định dạng JSON. Cách thức để lấy thông tin cũng khá dễ dàng.

Hai đoạn code dưới đây sẽ được viết với PHP và jQuery để các bạn có thêm nhiều sự lựa chọn

<?php
	$ip = "12.215.42.19";
	$url = "http://ipinfo.io/" . $ip;
	$location = json_decode(file_get_contents($url), true);
	print_r($location);

	// Kết quả
	Array
	(
		[ip] => 12.215.42.19
		[hostname] => No Hostname
		[city] => 
		[region] => 
		[country] => US
		[loc] => 38,-97
		[org] => AS7018 AT&T Services, Inc.
	)
?>

và…

// HTML
<div id="ip"></div>
<div id="address"></div>
<div id="details"></div>

// jQuery
$.get("http://ipinfo.io", function (response) {
    $("#ip").html("IP: " + response.ip);
    $("#address").html("Location: " + response.city + ", " + response.region);
    $("#details").html(JSON.stringify(response, null, 4));
}, "jsonp");

c, freegeoip.net

Đây là một trang web cung cấp Web Service API (theo kiểu RESTful) miễn phí, mang đến các thông tin liên quan của địa chỉ IP và Hostname. Web Service được cung cấp với dạng chung sau:

freegeoip.net/{format}/{ip_or_hostname}

Trong đó,

  • format: là định dạng dữ liệu mà bạn muốn lấy về, có 3 kiểu chính là csv, xmljson.
  • ip_or_hostname: là địa chỉ IP hoặc Hostname mà bạn muốn tra cứu thông tin

Đây là đoạn code nhỏ mà tôi sử dụng để lấy thông tin từ trang web này

<?php
	$ip = "12.215.42.19";
	$url = "http://freegeoip.net/json/" . $ip;
	$location = json_decode(file_get_contents($url), true);
	print_r($location);

	// Kết quả
	Array
	(
		[ip] => 12.215.42.19
		[country_code] => US
		[country_name] => United States
		[region_code] => 
		[region_name] => 
		[city] => 
		[zipcode] => 
		[latitude] => 38
		[longitude] => -97
		[metro_code] => 
		[areacode] => 
	)
?>

 Lưu ý: Các bạn chỉ được request 10.000 query mỗi giờ, nếu vượt quá số lượng quy định thì sẽ nhận được thông báo HTTP 403 (Forbidden). Ngoài ra, các bạn có thể  download source code tại đây.

d, ipinfodb.com

Trang web này cung cấp nhiều chức năng liên quan tới địa chỉ IP như dò tìm địa chỉ IP, cung cấp Database và không thể thiếu các API (miễn phí) để truy vấn và lấy thông tin địa chỉ IP.

Mục API của trang web này cung cấp khá đầy đủ và chi tiết về các phương thức và cách lấy dữ liệu. Vì là API miễn phí nên họ chỉ cung cấp những  phương thức đơn giản, bao gồm 2 phương thức chính và 4 tham số. Cụ thể như sau:

API List

[table]
API,Precision,Timezone,Domains lookups
ip-city,City,Yes,Yes
ip-country,Country,No,Yes
[/table]

API parameters

[table]
Parameter,Required,Default,Value
key,Yes,<empty>,API key provided with your free account.
ip,No,Client IP,IP address
format,No,raw,”raw, xml, json”
callback,No,<empty>,Required when using json callback.
[/table]

Cách truy vấn như sau:

http://api.ipinfodb.com/v3/ip-city/?key=<your_api_key>&ip=<your_ip_address>

hoặc

http://api.ipinfodb.com/v3/ip-country/?key=<your_api_key>&ip=<your_ip_address>

Các bạn cần cung cấp API Key để thực hiện các truy vấn này. Muốn có API Key thì các bạn đăng kí ở đây.

Ngoài ra, trang web cũng cung cấp 1 PHP Class để lấy dữ liệu (download tại đây). Dưới đây là 1 ví dụ về các chức năng của Class đó

<?php
	include('ip2locationlite.class.php');

	//Load the class
	$ipLite = new ip2location_lite;
	$ipLite->setKey('<your_api_key>');

	//Get errors and locations
	$locations = $ipLite->getCity($_SERVER['REMOTE_ADDR']);
	$errors = $ipLite->getError();

	//Getting the result
	echo "<p>\n";
	echo "<strong>First result</strong><br />\n";
	if (!empty($locations) && is_array($locations)) {
		foreach ($locations as $field => $val) {
			echo $field . ' : ' . $val . "<br />\n";
		}
	}
	echo "</p>\n";

	//Show errors
	echo "<p>\n";
	echo "<strong>Dump of all errors</strong><br />\n";
	if (!empty($errors) && is_array($errors)) {
		foreach ($errors as $error) {
			echo var_dump($error) . "<br /><br />\n";
		}
	} else {
		echo "No errors" . "<br />\n";
	}
	echo "</p>\n";
?>

Một số ngôn ngữ và module mà trang web này hỗ trợ thêm

Khi tìm hiểu về trang web này, tôi có thấy 1 đoạn code chia sẻ về cách lấy dữ liệu của trang này. Đoạn code của tác giả SpYk3HH trên trang Stackoverflow khá đơn giản, sử dụng cURL để lấy kết quả trực tiếp mà không sử dụng API.

<?php
	function detect_location($ip = NULL, $asArray = FALSE) {
		if (empty($ip)) {
			if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; }
			else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; }
			else { $ip = $_SERVER['REMOTE_ADDR']; }
		}
		else if (!is_string($ip) || strlen($ip) < 1 || $ip == '127.0.0.1' || $ip == 'localhost') {
			$ip = '8.8.8.8';
		}

		$url = 'http://ipinfodb.com/ip_locator.php?ip=' . urlencode($ip);
		$i = 0; $content; $curl_info;

		while (empty($content) && $i < 5) {
			$ch = curl_init();
			$curl_opt = array(
				CURLOPT_FOLLOWLOCATION => 1,
				CURLOPT_HEADER => 0,
				CURLOPT_RETURNTRANSFER  => 1,
				CURLOPT_URL => $url,
				CURLOPT_TIMEOUT => 1,
				CURLOPT_REFERER => 'http://' . $_SERVER['HTTP_HOST'],
			);
			if (isset($_SERVER['HTTP_USER_AGENT'])) $curl_opt[CURLOPT_USERAGENT] = $_SERVER['HTTP_USER_AGENT'];
			curl_setopt_array($ch, $curl_opt);
			$content = curl_exec($ch);
			if (!is_null($curl_info)) $curl_info = curl_getinfo($ch);
			curl_close($ch);
		}

		$araResp = array();
		if (preg_match('{<li>City : ([^<]*)</li>}i', $content, $regs)) $araResp['city'] = trim($regs[1]);
		if (preg_match('{<li>State/Province : ([^<]*)</li>}i', $content, $regs)) $araResp['state'] = trim($regs[1]);
		if (preg_match('{<li>Country : ([^<]*)}i', $content, $regs)) $araResp['country'] = trim($regs[1]);
		if (preg_match('{<li>Zip or postal code : ([^<]*)</li>}i', $content, $regs)) $araResp['zip'] = trim($regs[1]);
		if (preg_match('{<li>Latitude : ([^<]*)</li>}i', $content, $regs)) $araResp['latitude'] = trim($regs[1]);
		if (preg_match('{<li>Longitude : ([^<]*)</li>}i', $content, $regs)) $araResp['longitude'] = trim($regs[1]);
		if (preg_match('{<li>Timezone : ([^<]*)</li>}i', $content, $regs)) $araResp['timezone'] = trim($regs[1]);
		if (preg_match('{<li>Hostname : ([^<]*)</li>}i', $content, $regs)) $araResp['hostname'] = trim($regs[1]);

		$strResp = ($araResp['city'] != '' && $araResp['state'] != '') ? ($araResp['city'] . ', ' . $araResp['state']) : 'UNKNOWN';

		return $asArray ? $araResp : $strResp;
	}
?>

Và cách sử dụng như sau

detect_location();
//  returns "CITY, STATE" based on user IP

detect_location('xxx.xxx.xxx.xxx');
//  returns "CITY, STATE" based on IP you provide

detect_location(NULL, TRUE);    //   based on user IP
//  returns array(8) { ["city"] => "CITY", ["state"] => "STATE", ["country"] => "US", ["zip"] => "xxxxx", ["latitude"] => "xx.xxxxxx", ["longitude"] => "-xx.xxxxxx", ["timezone"] => "-07:00", ["hostname"] => "xx-xx-xx-xx.host.name.net" }

detect_location('xxx.xxx.xxx.xxx', TRUE);   //   based on IP you provide
//  returns array(8) { ["city"] => "CITY", ["state"] => "STATE", ["country"] => "US", ["zip"] => "xxxxx", ["latitude"] => "xx.xxxxxx", ["longitude"] => "-xx.xxxxxx", ["timezone"] => "-07:00", ["hostname"] => "xx-xx-xx-xx.host.name.net" }

e, iptolatlng.com

Các bạn có thể request tới trang web này để lấy dữ liệu với 3 tham số cơ bản là ip, typecallback.  Có 2 kiểu dữ liệu trả về là JSON và JSONP.

Cách sử dụng hiển thị ngay trên trang web nên tôi không cần giới thiệu ở đây nữa.

f, geoplugin.com

Với trang web này, các bạn có thể sử dụng cú pháp sau lấy dữ liệu được cung cấp bởi PHP Web Service

http://www.geoplugin.net/php.gp?ip=<your_ip_address>

Sau đây là 1 ví dụ sử dụng Web Service trên

<?php
	function getIpAddress() {
		$ip = $_SERVER['REMOTE_ADDR'];

		if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
			$ip = $_SERVER['HTTP_CLIENT_IP'];
		} else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
			$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
		}

		return $ip;
	}

	$ip = getIpAddress();

	echo var_export(unserialize(file_get_contents('http://www.geoplugin.net/php.gp?ip=' . $ip)));
?>

Và kết quả trả về

array (
  'geoplugin_request' => 'xx.xx.xx.xx',
  'geoplugin_status' => 200,
  'geoplugin_credit' => 'Some of the returned data includes GeoLite data created by MaxMind, available from http://www.maxmind.com.',
  'geoplugin_city' => 'Hai Phong',
  'geoplugin_region' => 'Hải Phòng',
  'geoplugin_areaCode' => '0',
  'geoplugin_dmaCode' => '0',
  'geoplugin_countryCode' => 'VN',
  'geoplugin_countryName' => 'Vietnam',
  'geoplugin_continentCode' => 'AS',
  'geoplugin_latitude' => '20.8561',
  'geoplugin_longitude' => '106.682198',
  'geoplugin_regionCode' => '13',
  'geoplugin_regionName' => 'Hải Phòng',
  'geoplugin_currencyCode' => 'VND',
  'geoplugin_currencySymbol' => '₫',
  'geoplugin_currencySymbol_UTF8' => '₫',
  'geoplugin_currencyConverter' => '21085.1999',
)

Trang web cũng cung cấp 1 PHP Class để lấy dữ liệu (tải về). Và đoạn code sau là ví dụ để sử dụng PHP Class này.

<?php
	require_once('geoplugin.class.php');
	$geoplugin = new geoPlugin();
	// If we wanted to change the base currency, we would uncomment the following line
	// $geoplugin->currency = 'EUR';

	$geoplugin->locate();

	echo "Geolocation results for {$geoplugin->ip}: <br />\n".
		"City: {$geoplugin->city} <br />\n".
		"Region: {$geoplugin->region} <br />\n".
		"Area Code: {$geoplugin->areaCode} <br />\n".
		"DMA Code: {$geoplugin->dmaCode} <br />\n".
		"Country Name: {$geoplugin->countryName} <br />\n".
		"Country Code: {$geoplugin->countryCode} <br />\n".
		"Longitude: {$geoplugin->longitude} <br />\n".
		"Latitude: {$geoplugin->latitude} <br />\n".
		"Currency Code: {$geoplugin->currencyCode} <br />\n".
		"Currency Symbol: {$geoplugin->currencySymbol} <br />\n".
		"Exchange Rate: {$geoplugin->currencyConverter} <br />\n";

	if ( $geoplugin->currency != $geoplugin->currencyCode ) {
		//our visitor is not using the same currency as the base currency
		echo "<p>At todays rate, US$100 will cost you " . $geoplugin->convert(100) ." </p>\n";
	}

	/* find places nearby */
	$nearby = $geoplugin->nearby();
	if ( isset($nearby[0]['geoplugin_place']) ) {
		echo "<pre><p>Some places you may wish to visit near " . $geoplugin->city . ": </p>\n";
		foreach ( $nearby as $key => $array ) {

			echo ($key + 1) .":<br />";
			echo "\t Place: " . $array['geoplugin_place'] . "<br />";
			echo "\t Country Code: " . $array['geoplugin_countryCode'] . "<br />";
			echo "\t Region: " . $array['geoplugin_region'] . "<br />";
			echo "\t County: " . $array['geoplugin_county'] . "<br />";
			echo "\t Latitude: " . $array['geoplugin_latitude'] . "<br />";
			echo "\t Longitude: " . $array['geoplugin_longitude'] . "<br />";
			echo "\t Distance (miles): " . $array['geoplugin_distanceMiles'] . "<br />";
			echo "\t Distance (km): " . $array['geoplugin_distanceKilometers'] . "<br />";

		}
		echo "</pre>\n";
	}
?>

g, netip.de

Đây là 1 geo-IP-server dùng để kiểm tra và trả về thông tin IP bao gồm đất nước, bang, thành phố…

Các bạn hãy tham khảo đoạn code sau để lấy dữ liệu.

<?php
	function getIpInformationFromNetIp($ip = null) {
       	//check, if the provided ip is valid
       	if (!filter_var($ip, FILTER_VALIDATE_IP)) {
            throw new InvalidArgumentException("IP is not valid");
       	}

       	//contact ip-server
       	$response = @file_get_contents('http://www.netip.de/search?query='.$ip);
       	if (empty($response)) {
            throw new InvalidArgumentException("Error contacting Geo-IP-Server");
       	}

       	//Array containing all regex-patterns necessary to extract ip-geoinfo from page
       	$patterns = array();
		$patterns["domain"]  = '#Domain: (.*?)&nbsp;#i';
		$patterns["country"] = '#Country: (.*?)&nbsp;#i';
		$patterns["state"]   = '#State/Region: (.*?)<br#i';
		$patterns["town"]    = '#City: (.*?)<br#i';

       	//Array where results will be stored
       	$ipInfo=array();

       	//check response from ipserver for above patterns
       	foreach ($patterns as $key => $pattern) {
            //store the result in array
       		$ipInfo[$key] = preg_match($pattern,$response,$value) && !empty($value[1]) ? $value[1] : 'not found';
       	}

       	return $ipInfo;
   	}

	$ip = '113.165.48.93';
    print_r(getIpInformationFromNetIp($ip));
?>

Và dữ liệu trả về

Array
(
    [domain] => not found
    [country] => VN - Vietnam
    [state] => Hai Phong
    [town] => Hai Phong
)

2, Giới thiệu một số trang web và dịch vụ cung cấp Database để tra cứu thông tin

a, maxmind.com

Trang web này cung cấp những Database miễn phí với định dạng Binary (*.dat) và CSV (*.csv), giúp các bạn dễ dàng tra cứu thông tin liên quan của địa chỉ IP. Hiện nay có khá nhiều thư viện được dùng để đọc nội dung từ file DAT và CSV do đó các bạn tự tìm hiểu thêm phần này nhé.

Database được cung cấp tại 2 trang này:

Ngoài ra, các bạn có thể tham khảo thêm API mà trang web cung cấp tại đây.

Với bài viết “GeoIP country lookup with PHP” này thì các bạn có thể biết thêm về cách sử dụng PHP để lấy dữ liệu từ trang MaxMind này.

b, ip2nation.com

Trang web này cung cấp một MySQL database chứa số lượng lớn danh sách địa chỉ IP và thông tin liên quan. Các bạn hãy tải về tại đây.

Và dưới đây là một số đoạn code mẫu dùng để thao tác với database vừa tải về

<?php
	$ip = "12.215.42.19";

	$server   = ''; // MySQL hostname
	$username = ''; // MySQL username
	$password = ''; // MySQL password
	$dbname   = ''; // MySQL db name

	$db = mysql_connect($server, $username, $password) or die(mysql_error());
	      mysql_select_db($dbname) or die(mysql_error());

	$sql = 'SELECT 
	            country
	        FROM 
	            ip2nation
	        WHERE 
	            ip < INET_ATON("' . $ip . '") 
	        ORDER BY 
	            ip DESC 
	        LIMIT 0,1';

	list($country) = mysql_fetch_row(mysql_query($sql));

	switch ($country) {
		case 'se':
			// Get the Swedish to a Swedish newssite
			header('Location: http://www.thelocal.se/');
			exit;
		case 'us':
			// And redirect US visitors to CNN
			header('Location: http://www.cnn.com/');
			exit;
		default:
			// The rest of the world can go to BBC
			header('Location: http://www.bbc.co.uk/');
			exit;
	}
?>

và…

<?php
	$ip = "12.215.42.19";

	$server   = ''; // MySQL hostname
	$username = ''; // MySQL username
	$password = ''; // MySQL password
	$dbname   = ''; // MySQL db name

	$db = mysql_connect($server, $username, $password) or die(mysql_error());
	      mysql_select_db($dbname) or die(mysql_error());

	$sql = 'SELECT 
	            c.country 
	        FROM 
	            ip2nationCountries c,
	            ip2nation i 
	        WHERE 
	            i.ip < INET_ATON("' . $ip . '") 
	            AND 
	            c.code = i.country 
	        ORDER BY 
	            i.ip DESC 
	        LIMIT 0,1';

	list($countryName) = mysql_fetch_row(mysql_query($sql));

	// Output full country name
	echo $countryName;
?>

c, http://software77.net/geo-ip/

Khi vào trang web này, ở mục Download trong cột bên phải, các bạn sẽ tải được danh sách các IP (v4) với định dạng CSV. Với một số tutorial dưới đây, việc đọc dữ liệu từ file CSV trở nên đơn giản hơn.

 3, Tổng kết

Bài viết này khá dài vì tôi muốn giới thiệu đến các bạn tất cả những gì tôi tìm hiểu được. Nếu các bạn tìm được trang nào cung cấp API / Database về IP thì cùng chia sẻ với mọi người nhé.

Tấn Việt

Tôi lập trang web này để thỏa mãn sở thích viết cái gì đó vui vui khi rãnh rỗi và đồng thời cũng chia sẻ những gì tôi biết hoặc đọc đâu đó trên mạng về Lập trình web. Tôi hi vọng những bài viết này sẽ giúp ích cho các bạn. Thân ái!

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *