Get zip code based on lat & long?

2019-02-07 03:49发布

问题:

Is there a service or API I can ping, and pass in the lat/long as parameters, where it returns the zip code that lat/long pair is within? This is US-only, so I don't have to worry about international codes, etc.

I feel like Google Maps' reverse-geocoding is too heavy for me. I'd prefer something lighter, if possible. This will be done in javascript.

回答1:

It is called Reverse Geocoding (Address Lookup). To get address for lat: 40.714224, lng: -73.961452 query http://maps.googleapis.com/maps/api/geocode/json with parameters latlng=40.714224,-73.961452&sensor=true (example) and it returns JSON object or use http://maps.googleapis.com/maps/api/geocode/xml to return XML response (example). It's from Google and it's free.



回答2:

For the Google API, you need to use it within a Google map, according to their site:

Note: the Geocoding API may only be used in conjunction with a Google map; geocoding results without displaying them on a map is prohibited.



回答3:

Please have a look on http://geonames.org. There is a webservice findNearbyPostalCodes (international).

Example: findNearbyPostalCodesJSON?lat=47&lng=9&username=demo

Shortened output:

{
  "postalCodes": [{
    "adminCode3": "1631",
    "distance": "2.2072",
    "postalCode": "8775",
    "countryCode": "CH",
    "lng": 8.998679778165283,
    "placeName": "Luchsingen",
    "lat": 46.980169648620375
  }]
}

Limit of the demo account is 2000 queries per hour.



回答4:

Google Maps API can get zip code associated with a geolocation. However if you are somewhere in middle of jungle then this API will not return anything as postal code are mapped to postal addresses. In that case you need to get zip code of nearby city.

You can use this method to do so

  //Reverse GeoCode position into Address and ZipCOde
  function getZipCodeFromPosition(geocoder, map,latlng,userLocationInfoWindow) {

   geocoder.geocode({'location': latlng}, function(result, status) {
     if (status === 'OK') {
       if (result[0]) {

            console.log("GeoCode Results Found:"+JSON.stringify(result));

            //Display Address
            document.getElementById("address").textContent  = "Address: " +result[0].formatted_address;

           //Update Info Window on Server Map
           userLocationInfoWindow.setPosition(latlng);
           userLocationInfoWindow.setContent('<IMG BORDER="0" ALIGN="Left" SRC="https://media3.giphy.com/media/IkwH4WZWgdfpu/giphy.gif" style ="width:50px; height:50px"><h6 class ="pink-text">You Are Here</h4> <p class = "purple-text" style ="margin-left:30px;">'+result[0].formatted_address+'</p>');
           userLocationInfoWindow.open(map);
           map.setCenter(latlng);

            //Try to Get Postal Code
            var postal = null;
            var city = null;
            var state = null;
            var country = null;

          for(var i=0;i<result.length;++i){
              if(result[i].types[0]=="postal_code"){
                  postal = result[i].long_name;
              }
              if(result[i].types[0]=="administrative_area_level_1"){
                  state = result[i].long_name;
              }
              if(result[i].types[0]=="locality"){
                  city = result[i].long_name;
              }
              if(result[i].types[0]=="country"){
                  country = result[i].long_name;
              }
          }
          if (!postal) {
            geocoder.geocode({ 'location': result[0].geometry.location }, function (results, status) {
              if (status == google.maps.GeocoderStatus.OK) {

                //Postal Code Not found, Try to get Postal code for City
                var result=results[0].address_components;

                for(var i=0;i<result.length;++i){
                 if(result[i].types[0]=="postal_code"){
                    postal = result[i].long_name;
                 }
                }
                  if (!postal) {

                    //Postal Code Not found
                     document.getElementById("postal").textContent  = "No Postal Code Found  for this location";
                  }else
                  {
                     //Postal Code found
                      document.getElementById("postal").textContent  = "Zip Code: "+postal;
                  }
              }
          });
          } else
              {
              //Postal Code found
              document.getElementById("postal").textContent  = "Zip Code: "+postal;
              }
          console.log("STATE: " + state);
          console.log("CITY: " + city);
          console.log("COUNTRY: " + country);

             } else {
           window.alert('No results found');
         }
       } else {
         window.alert('Geocoder failed due to: ' + status);
       }
     });
 }
</script>

Working example

https://codepen.io/hiteshsahu/pen/gxQyQE?editors=1010



回答5:

The answer from kubetz is great, but since we have to use https to get geolocation to work (Geolocation API Removed from Unsecured Origins in Chrome 50), the call to http://api.geonames.org fails because it is not over https. A local php script, called over https, that gets from geonames.org solves the problem.

//javascript function
function getZipFromLatLong() {
    var url = "getzip.php";
    var formData = new FormData();
    formData.append("lat", current_lat);
    formData.append("long", current_long);

    var r = new XMLHttpRequest();
    r.open("POST", url, true);
    r.onreadystatechange = function () {
        if (r.readyState != 4 || r.status != 200) {
            return;
        } else {
            data = r.responseText;
            var jdata = JSON.parse(data);
            document.getElementById("zip").value = jdata.postalCodes[0].postalCode;
        }
    }
    r.send(formData);
}

//getzip.php script
<?php

$lat = $_POST["lat"];
$long = $_POST["long"];

$url = "http://api.geonames.org/findNearbyPostalCodesJSON?username=demo&lat=" . $lat .  "&lng=" . $long;

$content = file_get_contents($url);

//the output is json, so just return it as-is
die($content);
?>