Giter Site home page Giter Site logo

bennylope / pygeocodio Goto Github PK

View Code? Open in Web Editor NEW
92.0 10.0 22.0 179 KB

:globe_with_meridians: A Python wrapper for the Geocodio geolocation service API

License: BSD 3-Clause "New" or "Revised" License

Python 97.70% Makefile 2.30%
python geocoding geocodio api api-client

pygeocodio's Introduction

Py-Geocodio

image

image

image

Python wrapper for Geocodio geocoding API.

Full documentation on Read the Docs.

If you are upgrading from a version prior to 0.2.0 please see the changelog in HISTORY.rst. The default coordinate ordering has changed to something a bit more sensible for most users.

Geocodio API Features

  • Geocode an individual address
  • Batch geocode up to 10,000 addresses at a time
  • Parse an address into its identifiable components
  • Reverse geocode an individual geographic point
  • Batch reverse geocode up to 10,000 points at a time
  • Perform operations using the HIPAA API URL

The service is limited to U.S. and Canada addresses for the time being.

Read the complete Geocodio documentation for service documentation.

Installation

pygeocodio requires requests 1.0.0 or greater and will ensure requests is installed:

pip install pygeocodio

Basic usage

Import the API client and ensure you have a valid API key:

>>> from geocodio import GeocodioClient
>>> client = GeocodioClient(YOUR_API_KEY)

Note that you can pass in a timeout value in seconds (the default is no timeout):

>>> client = GeocodioClient(YOUR_API_KEY, timeout=15)

Geocoding

Geocoding an individual address:

>>> geocoded_location = client.geocode("42370 Bob Hope Drive, Rancho Mirage CA")
>>> geocoded_location.coords
(33.738987255507, -116.40833849559)

Geocode a set of address components:

>>> geocoded_location = client.geocode(components_data={
  "postal_code": "02210",
  "country": "US"
})
>>> geocoded_location.coords
(42.347547, -71.040645)

Batch geocoding

You can also geocode a list of addresses:

>>> geocoded_addresses = client.geocode([
        '2 15th St NW, Washington, DC 20024',
        '3101 Patterson Ave, Richmond, VA, 23221'
    ])

Return a list of just the coordinates for the resultant geocoded addresses:

>>> geocoded_addresses.coords
[(38.890083, -76.983822), (37.560446, -77.476008)]
>>> geocoded_addresses[0].coords
(38.890083, -76.983822)

Lookup an address by the queried address:

>>> geocoded_addresses.get('2 15th St NW, Washington, DC 20024').coords
(38.879138, -76.981879))

You can also geocode a list of address component dictionaries:

>>> geocoded_addresses = client.geocode(components_data=[{
        'street': '1109 N Highland St',
        'city': 'Arlington',
        'state': 'VA'
    }, {
        'city': 'Toronto',
        'country': 'CA'
    }])

And geocode a keyed mapping of address components:

>>> gecoded_addresses = client.geocode(components_data={
        "1": {
            "street": "1109 N Highland St",
            "city": "Arlington",
            "state": "VA"
        },
        "2": {
            "city": "Toronto",
            "country": "CA"
        }})

And geocode even a keyed mapping of addresses:

>>> geocoded_addresses = client.geocode({
        "1": "3101 patterson ave, richmond, va",
        "2": "1657 W Broad St, Richmond, VA"
    })

Return a list of just the coordinates for the resultant geocoded addresses:

>>> geocoded_addresses.coords
{'1': (37.560454, -77.47601), '2': (37.555176, -77.458273)}

Lookup an address by its key:

>>> geocoded_addresses.get("1").coords
(37.560454, -77.47601)

Address parsing

And if you just want to parse an individual address into its components:

>>> client.parse('1600 Pennsylvania Ave, Washington DC')
  {
      "address_components": {
          "number": "1600",
          "street": "Pennsylvania",
          "suffix": "Ave",
          "city": "Washington",
          "state": "DC"
      },
      "formatted_address": "1600 Pennsylvania Ave, Washington DC"
  }

Reverse geocoding

Reverse geocode a point to find a matching address:

>>> location = client.reverse((33.738987, -116.4083))
>>> location.formatted_address
"42370 Bob Hope Dr, Rancho Mirage CA, 92270"

Batch reverse geocoding

And multiple points at a time:

>>> locations = client.reverse([
        (33.738987, -116.4083),
        (33.738987, -116.4083),
        (38.890083, -76.983822)
    ])

Return the list of formatted addresses:

>>> locations.formatted_addresses
["42370 Bob Hope Dr, Rancho Mirage CA, 92270",  "42370 Bob Hope Dr, Rancho Mirage CA, 92270", "2 15th St NW, Washington, DC 20024"]

Access a specific address by the queried point tuple:

>>> locations.get("38.890083,-76.983822").formatted_address
"2 15th St NW, Washington, DC 20024"

Or by the more natural key of the queried point tuple:

>>> locations.get((38.890083, -76.983822)).formatted_address
"2 15th St NW, Washington, DC 20024"

CLI usage

In the works!

Documentation

For complete documentation see the docs.

License

BSD License

pygeocodio's People

Contributors

aviv avatar bennylope avatar bruno-uy avatar cyranix avatar erictheise avatar goorzhel avatar joshgeller avatar minicodemonkey avatar mroswell avatar nickcatal avatar pedromachados avatar shea-parkes avatar snake-plissken avatar unix-code avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pygeocodio's Issues

Error while calling the GeocodioClient

Pasting the exact error here:

Traceback (most recent call last):
File "main_new.py", line 21, in
from geocodio_util import *
File "/home/ayan_chandra/services/forms-service/geocodio_util.py", line 1, in
from geocodio import GeocodioClient
File "/home/ayan_chandra/anaconda3/lib/python3.7/site-packages/geocodio/init.py", line 9, in
from client import GeocodioClient
ModuleNotFoundError: No module named 'client'

I have installed the package by

pip install pygeocodio

README errors

The README example uses the coordinate (33.738987, -116.408) and mis-states the results in various places as
'1600 Pennsylvania Ave, Washington, DC' or '100 Main St, Springfield, USA'

Someone needs to review the README pretty carefully. (I'm hoping that a careful proofing will also yield an answer to #9 )

How to extract LAT and LON separately from geocoded_location.coords?

Hopefully an easy question, but is it possible to get a separate value for LON/X AND LAT/Y from the geocoded_location.coords object?

We're testing how, using python, the output coordinates can be dumped into a PostGIS database and assembled into a geometry object.

Thanks!

Issue with Batch Reverse Geocoding

GeocodioClient.reverse() needs to be adjusted so that batch reverse geocoding can work properly. I'm using Windows-7 32-bit.

>>> from geocodio_old import GeocodioClient
>>> client = GeocodioClient(api_key)
>>> address_list = ['40.8623,-73.9239', '40.8433,-73.9421']
>>> data = client.reverse(address_list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\geocodio_old\client.py", line 21, in wrapper
  return f(*args, **kwargs)
File "C:\Python27\lib\geocodio_old\client.py", line 201, in reverse
  return self.reverse_point(args[0][0], args[0][1], fields)
File "C:\Python27\lib\geocodio_old\client.py", line 21, in wrapper
  return f(*args, **kwargs)
File "C:\Python27\lib\geocodio_old\client.py", line 176, in reverse_point
  return error_response(response)
File "C:\Python27\lib\geocodio_old\client.py", line 34, in error_response
  raise GeocodioDataError(response.json()['error'])
geocodio_old.exceptions.GeocodioDataError: Could not parse coordinate

It looks like the problem is in GeocodioClient.reverse():

def reverse(self, *args, **kwargs):

    fields = kwargs.pop("fields", [])
    if len(args) == 1:
        return self.reverse_point(args[0][0], args[0][1], fields)
    return self.batch_reverse(args, fields)

The if statement resolves to true unless more than one argument is passed. However, passing more than 1 argument will throw an error since GeocodioClient.batch_reverse() only takes 1 argument. I have submitted a pull request for this fix.

Getting more than one field to return information

In playing around with this wrapper, I tried to pull all of the fields available when geocoding an address. Heres my code:

r = '42370 Bob Hope Dr, Rancho Mirage CA'
geocoded_location = client.geocode(r, fields=['cd','school'] )

This returns the 'school' attribute of fields, but not the 'cd'. I'd like to be able to pass more than one field and this doesn't not support this capability.

I would try to fix this myself, but I am not skilled enough in python.

Thanks.

Batch geocoding omits the "query" key

It looks like the query key is omitting when performing a batch geocoding request. The key is used to match up the address again after it has been geocoded.

>>> from geocodio import GeocodioClient
>>> geocodio = GeocodioClient('API_KEY')
>>> geocoded_addresses = geocodio.geocode([
...         '1600 Pennsylvania Ave, Washington, DC',
...         '3101 Patterson Ave, Richmond, VA, 23221'
...     ])
>>> geocoded_addresses
[{u'input': {u'address_components': {u'city': u'Washington', u'state': u'DC', u'street': u'Pennsylvania', u'number': u'1600', u'suffix': u'Ave'}, u'formatted_address': u'1600 Pennsylvania Ave, Washington, DC'}, u'results': [{u'address_components': {u'city': u'Washington', u'state': u'DC', u'zip': u'20042'}, u'formatted_address': u'Washington, DC 20042', u'location': {u'lat': u'38.893311', u'lng': u'-77.014647'}, u'accuracy': 0.33}, {u'address_components': {u'city': u'Washington', u'state': u'DC', u'zip': u'20043'}, u'formatted_address': u'Washington, DC 20043', u'location': {u'lat': u'38.893311', u'lng': u'-77.014647'}, u'accuracy': 0.33}, {u'address_components': {u'city': u'Washington', u'state': u'DC', u'zip': u'20044'}, u'formatted_address': u'Washington, DC 20044', u'location': {u'lat': u'38.893311', u'lng': u'-77.014647'}, u'accuracy': 0.33}, {u'address_components': {u'city': u'Washington', u'state': u'DC', u'zip': u'20015'}, u'formatted_address': u'Washington, DC 20015', u'location': {u'lat': u'38.969260', u'lng': u'-77.070949'}, u'accuracy': 0.33}, {u'address_components': {u'city': u'Washington', u'state': u'DC', u'zip': u'20013'}, u'formatted_address': u'Washington, DC 20013', u'location': {u'lat': u'38.893311', u'lng': u'-77.014647'}, u'accuracy': 0.33}]}, {u'input': {u'address_components': {u'city': u'Richmond', u'suffix': u'Ave', u'zip': u'23221', u'number': u'3101', u'state': u'VA', u'street': u'Patterson'}, u'formatted_address': u'3101 Patterson Ave, Richmond, VA 23221'}, u'results': [{u'address_components': {u'city': u'Richmond', u'suffix': u'Ave', u'zip': u'23221', u'number': u'3101', u'county': u'Richmond city', u'state': u'VA', u'street': u'Patterson'}, u'formatted_address': u'3101 Patterson Ave, Richmond, VA 23221', u'location': {u'lat': 37.560890255102, u'lng': -77.477400571429}, u'accuracy': 0.8}]}]

See http://geocod.io/docs/?python#toc_7 where the example response shows query

Coordinate ordering

It's super unintuitive that when geocoding a single result, .coords are returned in the format (lng, lat), but when returned from a batch request they're returned (lat, lng).

UserWarning

I'm working in a Jupyter notebook.

from geocodio import GeocodioClient
client = GeocodioClient('my_api_key')

yields this UserWarning:


/Users/mroswell/anaconda/lib/python2.7/site-packages/cffi/model.py:525: UserWarning: 'point_conversion_form_t' has no values explicitly defined; guessing that it is equivalent to 'unsigned int'
  % self._get_c_name())

Is there an option to specify timeout for requests, especially for batch geocoding?

According to their documentation,

You can batch geocode up to 10,000 addresses at the time. Geocoding 10,000 addresses takes about 600 seconds, so please make sure to adjust your timeout value accordingly.

I checked the code for pygeocodio, but couldn't find an option to specify the time limit, especially in case we're requesting for several addresses.

The kwargs in batch_geocode(self, addresses, **kwargs) seems to be a good place for specifying the option.

Client fails to handle zero results

Addresses with zip+4 are returned sans geocoding data as documented in #1 (#1 (comment)).

>>> client.geocode("681 Woodchuck Pl, Hayward, CA 94544-6720")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "geocodio/client.py", line 142, in geocode
    return self.geocode_address(address_data)
  File "geocodio/client.py", line 131, in geocode_address
    return Location(response.json())
  File "geocodio/data.py", line 46, in __init__
    self.best_match = Address(self["results"][0])
IndexError: list index out of range

At the least the module should handle missing data.

Reflect Canada in the README

The README says that the service is limited to U.S. addresses. But an April 2016 email signals that the service now includes Canadian addresses.

Broken __init__.py and client.py in pip package manager

Hello there,

It looks like this commit did not make it to the pip package manager. geocodio/init.py is still using the outdated format and client.py is still using version 1 of the Geocodio API:
9631d11

I am more than happy to do any testing,
George

bash-3.2$ pip install geocodio
Collecting geocodio
Requirement already satisfied: Requests>=2.2.0 in ./anaconda/lib/python3.6/site-packages (from geocodio)
Requirement already satisfied: idna<2.7,>=2.5 in ./anaconda/lib/python3.6/site-packages (from Requests>=2.2.0->geocodio)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in ./anaconda/lib/python3.6/site-packages (from Requests>=2.2.0->geocodio)
Requirement already satisfied: urllib3<1.23,>=1.21.1 in ./anaconda/lib/python3.6/site-packages (from Requests>=2.2.0->geocodio)
Requirement already satisfied: certifi>=2017.4.17 in ./anaconda/lib/python3.6/site-packages (from Requests>=2.2.0->geocodio)
Installing collected packages: geocodio
Successfully installed geocodio-1.0.1

bash-3.2$ python3.6
Python 3.6.1 |Anaconda 4.4.0 (x86_64)| (default, May 11 2017, 13:04:09)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

from geocodio import GeocodioClient
Traceback (most recent call last):
File "", line 1, in
File "anaconda/lib/python3.6/site-packages/geocodio/init.py", line 8, in
from client import Client
ModuleNotFoundError: No module named 'client'

exit()

cat anaconda/lib/python3.6/site-packages/geocodio/init.py

!/usr/bin/env python
-*- coding: utf-8 -*-

__author__ = 'David Stanley'
__email__ = '[email protected]'
__version__ = '1.0.0'

from client import Client

__all__ = [Client]

bash-3.2$ head anaconda/lib/python3.6/site-packages/geocodio/client.py

import requests, json

class Client:
    url = 'http://api.geocod.io/v1'
    api_key = ''

    def __init__(self, api_key):
        """ Initialize the class, setting the api_key to the class property """
        self.api_key = api_key

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.