Jump to content

Zip code from IP address?


tomccabe

Recommended Posts

Unless the user logs in and you have his city(some cities have multiple zips) you are out of luck. You can get close to their city with something like geolitecities but all  you can get is the city that the ISP has for the IP, which can get to close as the local office most times.

 

 

HTH

Teamatomic

Link to comment
Share on other sites

Hey HTH,

 

This was great...gives me *almost* what I need. I've got it looking up city/state at this point, but their database doesn't actually have zip codes. They explain this as such:

 

About 56% of GeoIP City records in the United States have postal codes. In many cases we are able to identify the city, but the city has multiple postal codes, so we don't identify the postal code in that case unless we are confident that the IP address is likely to be in that postal code and not one of the others in the city.

Not being able to determine the postal code in many cases is a general limitation of geolocation services. Typically an ISP will have its users connect to a central office and assign their client an IP address from a block of IP address. The block of IP addresses will be given out to clients spanning several zip codes. For instance, if you connect to a dial-up ISP in New York City, your provider will typically have a 212 access number number that is used from any postal code in the city.

 

With a postal code database such as iBegin.com's free US Zip Codes you could lookup a US postal code using the city and state returned by the GeoIP City database. Alternatively you can use the GEO-132 Binary Format (without metro/area codes) GeoIP City, which contains postal codes for every US city-level resolution, even when we aren't confident in the accuracy of the postal code. For the CSV format, we have a location file with postal codes for every US city record.

 

The site this points to has a great csv file with zip codes that is totally fine (weather difference won't be that crazy if I'm off by 25 miles...it doesn't need to be a scientific match).

 

Throughout searching I've vaguely gotten the idea that you can run an SQL query on a csv file (maybe I'm getting that wrong). I do know you can import one into an SQL database, but as this will be an advertisement the server won't necessarily have SQL installed.

 

What are my options? I'm so close I just need to figure out how to interface these 2 pieces of data! Arrrghhhh!!!

Link to comment
Share on other sites

After a bit more digging I found the fgetcsv() function. Seems to be what I'm after. Here's the steps I think this needs to take:

 

1. Run ip search on geoip database. 

2. if {find match with zip} return zip -task complete in this case

3. else {take lat/long from geoip. Run csv query on csv file. Check each entry's lat/long. Get sum of abs value of difference between lats and abs value of difference between long. Return zip from record with lowest total difference.

 

The portions in bold which specifically deal with the csv records is where I'm stumped. The examples in the php manual are not all that helpful for my situation.

Link to comment
Share on other sites

I don't want to throw confusion in here, but it's worth noting that to reduce the time of results maxmind provides .dat files which are much, much faster with turning up results. I have, and am currently using geolitecity to to IP location and the .dat file loads significantly faster than storing all the values in a database.

I think the query time for a city database compared to the query time with the .dat is a difference of about ~=1 second. Which is quite a bit when it comes to queries.

Link to comment
Share on other sites

Yeah, porno, you are absolutely correct. Unfortunately this banner is one that will display the weather at the user's location and that API needs zip code data, not simply city. I had no problem getting the city data as soon as HTH pointed me to GeoCity. The problem is that they only have zip codes for about half their records. Not too helpful a majority of the time (for instance no zip for me in Hollywood or partner doing the Flash portion in NYC).

 

That said, I did solve my problem and will post my solution for anyone else that might come across this here or through Google (and feel free to tell me if it could be more efficient! I'm sure there are ways I might cut down on query time of the CSV). I did indeed do it by latitude and longitude and used the CSV file with zip codes/lat/lon located here (as suggested by GeoCity FAQ):

 

http://geocoder.ibegin.com/downloads.php

 

The script cuts out before using the CSV if the IP has a zip code record in the GeoCity database, so it only adds the query time if it absolutely needs to (and it is about a full second).

 

<?php

include("geoipcity.inc");
include("geoipregionvars.php");

// OPEN GEOCITY DATABASE
$gi = geoip_open("GeoLiteCity.dat",GEOIP_STANDARD);

// IP CHECKS
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip=$_SERVER['HTTP_CLIENT_IP'];
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
}
else {
$ip=$_SERVER['REMOTE_ADDR'];
}

// GET GEOCITY LOCATION DATA FROM IP
$record = geoip_record_by_addr($gi,$ip);

// IF ZIP IS LOCATED IN GEOCITY DATABASE, RETURN
if ($record->postal_code) {
return $record->postal_code;
} 

// IF NOT RESOLVE ZIP CODE BY LATITUDE/LONGITUDE & RETURN
else {
$lat = $record->latitude; // save GeoCity latitude
$lon = $record->longitude; // save GeoCity longitude
$row = 0; // start at first row of zip code file
$diff = 10; // init out of bounds difference
$open = fopen("zips.csv", "r"); // open zip code file
while (($data = fgetcsv($open, 1000, ",")) !== FALSE) { // check records
	$test = abs($data[3] - $lat) + abs($data[4] - $lon); // get total difference between this record and actual lat/lon
	if (($test < 10) && ($test < $diff)) { // if it's reasonably close and less than the current lowest
		$diff = $test; // reset lowest record
		$zip = $data[0]; // set this zip as current
	}
}
return $zip;
}

// IF NO RESULT FROM EITHER, RETURN NYC DEFAULT
if ($zip == NULL) {
$default = "10001";
return $default;
}

geoip_close($gi);

?>

 

Link to comment
Share on other sites

Well...

Since you are only using it to get a zip code... I think I may have a solution to your problem since my curiosity is peaked concerning if what I'm working on will work or not since I could use it in some of my projects as well. If it does, today may be your lucky day and I will share it! :D

Link to comment
Share on other sites

I set the first condition of the while loop for a state matching the GeoCity state (the only other field they share) and that's shaved a little bit of time off (getting about 3500 - 5500ms on firebug now), but now my interest is also peaked! This stupid banner is actually turning into a fun little project haha.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.