Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: Zipcode search engine

by Jazz (Curate)
on Sep 10, 2001 at 04:36 UTC ( [id://111364]=note: print w/replies, xml ) Need Help??


in reply to Zipcode search engine

Update: Code updated to do reverse lookups. Now can do either city/state to zips and zip to city/state.

True, in theory, postal codes fairly closely relate to proximal cities, but where to start and stop the range?

For example, New York City, NY, a comparatively small city (in square miles) has 162 zip codes ranging from 10001 -> 10292. Meaning, within that range there are 129 unused zip code numbers.

Fayetteville, AR, much larger in area (950 sq miles) than NYC (309 sq miles), has only 4 zip codes 72701 - 72704. After NYC's 10292 zip, the next used zip is 10301, Staten Island. A short ferry ride away (or a bridge, if you're in Brooklyn), but a different island altogether and not the most convenient "closest store" from Manhattan.

So the question is what range should be associated with what region? Since the answer is difficult (if not impossible) to guess, let's defer to the USPS.

The following code will take a city and state and return all other zip codes for that city. It may not offer as broad a range as you'd like (nearby cities?), but at least you know that you're really pointing them to a location that's "nearby".

It also will let you check to see if a zip code that you're "guessing" is actually in the same area by returning the associated city/state (hint -- offer the cities and let the user select which is closest and/or most convenient to them).

#!/usr/bin/perl -w use CGI qw / :standard /; use LWP::UserAgent; use strict; print header(); # use z to enter a zip and get the city and state # use cs to enter the city, state and get all available zip codes for +the area my $query = 'z'; my $city = 'New York'; my $state = 'NY'; my $zip = '10001'; my $usps_form = 'http://www.usps.gov/cgi-bin/zip4/ctystzip2'; # prepare agent my $ua = LWP::UserAgent->new(); $ua->agent( 'AgentName/0.1 ' . $ua->agent ); # prepare request my $req = HTTP::Request->new( POST => $usps_form ); $req->content_type( 'application/x-www-form-urlencoded' ); $req->content( "ctystzip=$city $state&Submit=Process" ) if $query eq ' +cs'; $req->content( "ctystzip=$zip&Submit=Process" ) if $query eq 'z'; # process request my $res = $ua->request( $req ); # process result if ( $res->is_success ) { # city/state to zip query if ( $query eq 'cs'){ my @zips = zip_from_city_state( $res->content ); my $count = @zips; print p( "$count zip codes for $city, $state" ), blockquote ( join ( ", ", @zips ) ); } # zip to city/state query elsif ( $query eq 'z' ){ my $cs_aref = city_state_from_zip( $res->content ); print p( "Cities listed for $zip:" ), '<BLOCKQUOTE>'; print "$_->{'c'}, $_->{'s'}", br() foreach @$cs_aref; print '</BLOCKQUOTE>'; } else { die 'Bad query.'; } } else { warn 'USPS down, bad request, or no results.'; } sub zip_from_city_state { my @zips; # there has to be a more efficient way to do this :) foreach ( split( /<BR>/i, ( split( m|</?PRE>|i, $_[0] ) )[1] ) ){ my $zip = substr( $_, 0, 5 ); push @zips, $zip if $zip =~ /^\d{5,5}/; } return @zips; } sub city_state_from_zip { my ( $res, $cs_aref ) = ( shift, () ); $res =~ s/<BR>/\n/gi; # there has to be a more efficient way to do this :) my @lines = split( "\n", ( split( /--+/, ( split( m|</?PRE>|i, $res ) )[1] + ) )[1] ); for my $line ( @lines ){ my ( $city, $state ) = unpack( 'A27A2', $line ); push @$cs_aref, { 'c' => $city, 's' => $state } if $city and $ +state; } return $cs_aref; }

The above should be pretty self-explanatory, but if you have any questions, just holler.

Any optimizations or suggestions (both desired) would be most welcome :)

Jasmine

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://111364]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (7)
As of 2024-03-28 18:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found