Looking for Kick Ass Zip Code Locator!!!

Hi,

I'm looking for a link to a kick ass zip code locator that comes highly recommended, preferably free/cheap,  that will function much like the 1800Dentist version  - front end here:

http://www.1800dentist.com/

Basically, the user needs to be able to search by location (zip code) AND speciaty

thanks!!!!
phillystyle123Asked:
Who is Participating?
 
Ray PaseurConnect With a Mentor Commented:
@phillystyle123: you need two things to do this task.  You need the geocode for the zip code (a latitude/longitude pair) and you need a proximity computer to find other zip codes that are nearby.  I've been working a similar project for a while and here is what I can tell you.

There are about 34,000 zip codes you need to be concerned with.  The others are APO, PO Box only, etc.  You can dump them.  A zip code is NOT a geographic location - it is a postal carrier's route.  It may overlap other zip codes, cross state lines, etc.  In other words, it's not very precise.  In a major metro area, zip codes are somewhat useful for proximity determination.  In rural areas, they are not very good at all, and you would want to geocode the street or route address.

An attempt to geocode a ZIP+4 code results in no greater accuracy than a 5-digit zip code.  You must have a street name to get better location information.  Street and number gets "address" precision - usually within a few hundred feet of what you're looking for.

You can obtain free geocoding services from Yahoo and Google.  You must get an API key.  Yahoo allows you 5,000 calls per day. Google allows you 15,000.  So don't pay for the service from ibegin unless you expect to need more than 20,000 geocode calls per day.

I have never seen a zip code data base that has 100% accuracy in the geocode information.  Be aware that you want to scrub the data, no matter where you get it!

Yahoo's geocoder returns XML.  Google can return XML (actually KML) or a very simple CSV.  

Here is a script that teaches how to call the services.  

In a moment I will post a way to compute the distance between two lat/lon pairs.
<?php // demo_geocoders.php
//
// DEMONSTRATE CALLING THE YAHOO AND GOOGLE GEOCODER SERVICES TO GET THE LAT/LON PAIR FOR AN ADDRESS OR PART OF AN ADDRESS
//
// OCTOBER 27, 2008 NOTES
//
// EXECUTIVE SUMMARY - INPUT DATA IN ORDER OF PREFERENCE
//   STREET ADDRESS, CITY, STATE, ZIP+4 LIKE 1446 COLLEEN LN, MCLEAN, VA 22101-3104 = ADDRESS PRECISION
//   STREET ADDRESS, ZIP or ZIP+4 = ADDRESS PRECISION
//   STREET NAME AND ZIP OR ZIP+4 = STREET PRECISION
//   ZIP+4 LIKE 22101-3104 OR JUST ZIP LIKE 20852 = ZIP PRECISION
//
// GOTCHAS
//   YOU MUST PRESENT ZIP+4 LIKE 20016-2375.  IF YOU USE 200162375 YAHOO CANNOT HANDLE IT
//
//
// YAHOO WILL TELL YOU IF THE STATE AND ZIP DO NOT MATCH, BUT WILL MAKE STUFF UP IF THEY ARE BOTH BLANK (4101 NEBRASKA AVE)
// GOOGLE _MAY_ RETURN CODE 602 IF STATE AND ZIP DO NOT MATCH AND NO REASONABLE MATCH ON STREET NAME
// GOOGLE WILL TRY SOUND-ALIKE MATCHING ON CITY OR STATE NAMES ("ASSTON, TX" == "AWSTWIN, TX" == "AUSTIN, TX") (STATE=XX GIVES BUDAPEST)
//
// KEY ACCURACY EQUIVALENTS
//  YAHOO!    GOOGLE
//  state       2
//  city        3
//  city        4
//  zip         5
//  street      6
//  address     8
//
 
// LOCAL FUNCTIONS
require_once('_config.php');
 
// GET A FREEFORM LOCATION STATEMENT
$loc = '';
foreach ($_GET as $k => $v) { $$k = get_clean_text_string($v); }
if ($a != '') { $loc .= $a . ', '; }
if ($c != '') { $loc .= $c . ', '; }
if ($s != '') { $loc .= $s . ', '; }
if ($z != '') { $loc .= $z . ', '; }
$loc = trim(substr($loc, 0, -2));
 
?>
<html><head><title><?=$a?> <?=$c?> <?=$s?> <?=$z?> Yahoo/Google Geocoder Query</title></head>
<body>
<form method="get">
Addr: <input type="text" name="a" autocomplete="off" value="<?=$a?>" />
City: <input type="text" name="c" autocomplete="off" value="<?=$c?>" />
ST:   <input type="text" name="s" autocomplete="off" value="<?=$s?>" size="2" />
Zip:  <input type="text" name="z" autocomplete="off" value="<?=$z?>" size="8" />
<input type="submit" name="_go" value="go" />
</form>
</body>
</html>
<?php
 
 
if (empty($_GET)) { die(); }
 
 
// YAHOO CALL
$yahoo_url	= "http://local.yahooapis.com/MapsService/V1/geocode?appid=" . YAHOO_API;
 
/* YOU CAN ASK FOR INDIVIDUAL PIECES OF AN ADDRESS
$yahoo_url	.= "&street=" .	urlencode($a);
$yahoo_url	.= "&city=" .	urlencode($c);
$yahoo_url	.= "&state=" .	urlencode($s);
$yahoo_url	.= "&zip=" .	urlencode($z);
*/
 
// YOU CAN MAKE A FREEFORM QUERY FROM THE PARTS OF AN ADDRESS
$yahoo_url	.= "&location=" . urlencode($loc);
 
// SHOW THE QUERY - DO NOT DISPLAY THE API KEY
$yahoo_no_api_url	= str_replace(YAHOO_API, "[YahooAPI]", $yahoo_url);
echo "<h2>Yahoo! Geocoder Query Returns XML</h2>\n";
echo "<h4>ManPage here: <a target=\"_ymp\" href=\"http://developer.yahoo.com/maps/rest/V1/geocode.html\">http://developer.yahoo.com/maps/rest/V1/geocode.html</a><br />\n";
echo "Accuracy Constants here: <a target=\"_ymp\" href=\"http://developer.yahoo.com/maps/rest/V1/geocode.html\">http://developer.yahoo.com/maps/rest/V1/geocode.html</a> (see Response Fields)</h4>\n";
echo "Query String: $yahoo_no_api_url <br />\n";
 
// EXECUTE YAHOO GEOCODER QUERY
// NOTE - USE ERROR SUPPRESSION OR IT WILL BARF UP THE YAHOO API - ON FAILURE RETURNS HTTP 400 BAD REQUEST
if ($fp = @fopen($yahoo_url, 'r')) {
	while (!feof($fp)) { $y_buf .= fgets($fp); }
	fclose($fp);
} else {
	echo "<br />Yahoo Query Failed\n";
}
 
// EXAMINE THE RESULT
if ($y_buf != '') { // NOT EMPTY, WE GOT DATA
	$ydata	= new SimpleXMLElement($y_buf);
 
// CHECK FOR ANY ERROR MESSAGE
	$y_err	= $ydata->Message;
	if ($y_err == '') {
		$y_qual	= $ydata->Result["precision"];
		$y_warn	= $ydata->Result["warning"];
		$y_lat	= $ydata->Result->Latitude;
		$y_lon	= $ydata->Result->Longitude;
		$y_state= $ydata->Result->State;
		$y_zip	= $ydata->Result->Zip;
 
// NO ERROR MESSAGE, SHOW THE RESULT
		echo "<br />Yahoo Geocoder Result: \n";
		echo "<a target=\"geo_Y\" href=\"http://www.google.com/maps?f=q&hl=en&geocode=&q=" . $y_lat .','. $y_lon . "&ie=UTF8&z=15&iwloc=addr\">$y_lat $y_lon</a><br />Precision=$y_qual \n";
		if ($y_warn != '') {
			echo "<br />Warning: $y_warn \n";
			if ($y_state != $s) {
				echo "<br />Input State $s does not match Yahoo State $y_state.  Google Data may be better. \n";
			}
		}
	} else {
		echo "<br />Yahoo Geocoder Error: \n";
		echo "$y_err \n";
	}
// NO RESULT - SOMETHING IS SICK AT YAHOO
} else {
	echo "<br />Yahoo! Fubar $y_buf \n";
}
 
// SHOW THE XML FROM YAHOO
$y_buf_p	= ereg_replace('>', ">\n", $y_buf);
echo "<pre>";
echo htmlentities($y_buf_p);
echo "</pre>\n";
 
 
 
// GOOGLE CALL - USE FREEFORM QUERY
$google_url	= "http://maps.google.com/maps/geo?key=" . GOOGLE_API . "&output=csv&q=";
$google_url	.= urlencode($loc);
$google_no_api_url	= str_replace(GOOGLE_API, "[GoogleAPI]", $google_url);
echo "<h2>Google Geocoder Query Returns CSV</h2>\n";
echo "<h4>ManPage here: <a target=\"_gmp\" href=\"http://code.google.com/apis/maps/documentation/services.html#Geocoding_Direct\">http://code.google.com/apis/maps/documentation/services.html#Geocoding_Direct</a> (see CSV)<br />\n";
echo "Accuracy Constants here: <a target=\"_gmp\" href=\"http://code.google.com/apis/maps/documentation/reference.html#GGeoAddressAccuracy\">http://code.google.com/apis/maps/documentation/reference.html#GGeoAddressAccuracy</a></h4>\n";
echo "Query String: $google_no_api_url <br />\n";
 
// EXECUTE THE GOOGLE GEOCODER QUERY
if ($fp = fopen($google_url, 'r')) {
	while (!feof($fp)) { $g_buf .= fgets($fp); }
	fclose($fp);
}
 
// EXTRACT THE DATA
$gdata	= explode(',',$g_buf);
$g_resp	= $gdata[0]; // RESPONSE CODE SHOULD BE '200' -- IF 602 - BAD ZIP CODE OR UNUSABLE ADDRESS
$g_qual	= $gdata[1]; // GEOCODE ACCURACY - ZIP CODE = 5, HIGHER NUMBERS ARE BETTER
$g_lat	= $gdata[2];
$g_lon	= $gdata[3];
 
if ($g_resp == '200') { // RESPONSE CODE 200, WE GOT DATA
	echo "<br />Google Geocoder Result: \n";
	echo "<a target=\"geo_G\" href=\"http://www.google.com/maps?f=q&hl=en&geocode=&q=" . $g_lat .','. $g_lon . "&ie=UTF8&z=15&iwloc=addr\">$g_lat $g_lon</a> Precision=$g_qual\n";
	echo "<pre>$g_buf</pre>\n";
 
// BAD QUERY OR SOMETHING IS SICK AT GOOGLE
} else {
	echo "<br />Google Fubar $g_buf \n";
}
 
?>

Open in new window

0
 
biztigerCommented:
Full US Zip Code Free
http://geocoder.ibegin.com/downloads.php

Postal Code for another country:
http://www.maxmind.com/app/postalcode

All are free. Available in csv format.
0
 
Ray PaseurConnect With a Mentor Commented:
When you have selected the latitude and longitude pairs for point "a" and point "b" you can use this function to find the great-circle distance.  Not the same as driving distance but usually proportional and good enough.
function compute_distance($from_lat, $from_lon, $to_lat, $to_lon) {
 
	$from_lat	= floatval($from_lat);
	$from_lon	= floatval($from_lon);
	$to_lat		= floatval($to_lat);
	$to_lon		= floatval($to_lon);
 
	$dist	= acos( sin(deg2rad($from_lat))
              * sin(deg2rad($to_lat))
              + cos(deg2rad($from_lat))
              * cos(deg2rad($to_lat))
              * cos(deg2rad($from_lon - $to_lon)) );
 
	$dist	= rad2deg($dist);
	$miles	= (float) $dist * 69.0;
return round($miles,1);
// To get kilometers, multiply miles by 1.61
// $km		= (float) $miles * 1.61;
// return round($km,2);
}

Open in new window

0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

 
Ray PaseurConnect With a Mentor Commented:
You will probably want to find out which zip codes are close to one another.  That's a new, separate question.  If you post a question about it, I'll show you the general algorithm for zip-proximity determination.

best regards, ~Ray
0
 
phillystyle123Author Commented:
thanks Ray!
0
 
Ray PaseurCommented:
Thanks for the points - it's a great question.  Good luck with your project, ~Ray
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.