generated from mwc/lab_weather
I was just checking that everything was submitted but I guess this wasn't.
This commit is contained in:
parent
2313bcfbff
commit
66f67710f0
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
"""
|
||||
Geocoder
|
||||
~~~~~~~~
|
||||
|
||||
Simple and consistent geocoding library written in Python.
|
||||
|
||||
Many online providers such as Google & Bing have geocoding services,
|
||||
these providers do not include Python libraries and have different
|
||||
JSON responses between each other.
|
||||
|
||||
Consistant JSON responses from various providers.
|
||||
|
||||
>>> g = geocoder.google('New York City')
|
||||
>>> g.latlng
|
||||
[40.7127837, -74.0059413]
|
||||
>>> g.state
|
||||
'New York'
|
||||
>>> g.json
|
||||
...
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'geocoder'
|
||||
__author__ = 'Denis Carriere'
|
||||
__author_email__ = 'carriere.denis@gmail.com'
|
||||
__version__ = '1.38.1'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2013-2016 Denis Carriere'
|
||||
|
||||
# CORE
|
||||
from geocoder.api import get, yahoo, bing, geonames, mapquest, google, mapbox # noqa
|
||||
from geocoder.api import nokia, osm, tomtom, geolytica, arcgis, opencage, locationiq # noqa
|
||||
from geocoder.api import maxmind, ipinfo, freegeoip, ottawa, here, baidu, gaode, w3w # noqa
|
||||
from geocoder.api import yandex, mapzen, komoot, tamu, geocodefarm, tgos, uscensus # noqa
|
||||
from geocoder.api import gisgraphy # noqa
|
||||
|
||||
# EXTRAS
|
||||
from geocoder.api import timezone, elevation, places, ip, canadapost, reverse, distance, location # noqa
|
||||
|
||||
# CLI
|
||||
from geocoder.cli import cli # noqa
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
"""
|
||||
Geocoder
|
||||
~~~~~~~~
|
||||
|
||||
Simple and consistent geocoding library written in Python.
|
||||
|
||||
Many online providers such as Google & Bing have geocoding services,
|
||||
these providers do not include Python libraries and have different
|
||||
JSON responses between each other.
|
||||
|
||||
Consistant JSON responses from various providers.
|
||||
|
||||
>>> g = geocoder.google('New York City')
|
||||
>>> g.latlng
|
||||
[40.7127837, -74.0059413]
|
||||
>>> g.state
|
||||
'New York'
|
||||
>>> g.json
|
||||
...
|
||||
|
||||
"""
|
||||
|
||||
__title__ = 'geocoder'
|
||||
__author__ = 'Denis Carriere'
|
||||
__author_email__ = 'carriere.denis@gmail.com'
|
||||
__version__ = '1.38.1'
|
||||
__license__ = 'MIT'
|
||||
__copyright__ = 'Copyright (c) 2013-2016 Denis Carriere'
|
||||
|
||||
# CORE
|
||||
from geocoder.api import get, yahoo, bing, geonames, mapquest, google, mapbox # noqa
|
||||
from geocoder.api import nokia, osm, tomtom, geolytica, arcgis, opencage, locationiq # noqa
|
||||
from geocoder.api import maxmind, ipinfo, freegeoip, ottawa, here, baidu, gaode, w3w # noqa
|
||||
from geocoder.api import yandex, mapzen, komoot, tamu, geocodefarm, tgos, uscensus # noqa
|
||||
from geocoder.api import gisgraphy # noqa
|
||||
|
||||
# EXTRAS
|
||||
from geocoder.api import timezone, elevation, places, ip, canadapost, reverse, distance, location # noqa
|
||||
|
||||
# CLI
|
||||
from geocoder.cli import cli # noqa
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,661 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from geocoder.distance import Distance
|
||||
from geocoder.location import Location
|
||||
|
||||
from geocoder.arcgis import ArcgisQuery
|
||||
from geocoder.baidu import BaiduQuery
|
||||
from geocoder.bing import BingQuery, BingQueryDetail
|
||||
from geocoder.canadapost import CanadapostQuery
|
||||
from geocoder.freegeoip import FreeGeoIPQuery
|
||||
from geocoder.gaode import GaodeQuery
|
||||
from geocoder.geocodefarm import GeocodeFarmQuery
|
||||
from geocoder.geolytica import GeolyticaQuery
|
||||
from geocoder.gisgraphy import GisgraphyQuery
|
||||
from geocoder.here import HereQuery
|
||||
from geocoder.ipinfo import IpinfoQuery
|
||||
from geocoder.komoot import KomootQuery
|
||||
from geocoder.locationiq import LocationIQQuery
|
||||
from geocoder.mapbox import MapboxQuery
|
||||
from geocoder.mapquest import MapquestQuery
|
||||
from geocoder.mapzen import MapzenQuery
|
||||
from geocoder.maxmind import MaxmindQuery
|
||||
from geocoder.opencage import OpenCageQuery
|
||||
from geocoder.osm import OsmQuery, OsmQueryDetail
|
||||
from geocoder.ottawa import OttawaQuery
|
||||
from geocoder.tamu import TamuQuery
|
||||
from geocoder.tomtom import TomtomQuery
|
||||
from geocoder.tgos import TgosQuery
|
||||
from geocoder.uscensus import USCensusQuery
|
||||
from geocoder.yahoo import YahooQuery
|
||||
from geocoder.yandex import YandexQuery
|
||||
from geocoder.w3w import W3WQuery
|
||||
|
||||
from geocoder.arcgis_reverse import ArcgisReverse
|
||||
from geocoder.baidu_reverse import BaiduReverse
|
||||
from geocoder.bing_reverse import BingReverse
|
||||
from geocoder.gaode_reverse import GaodeReverse
|
||||
from geocoder.geocodefarm_reverse import GeocodeFarmReverse
|
||||
from geocoder.gisgraphy_reverse import GisgraphyReverse
|
||||
from geocoder.here_reverse import HereReverse
|
||||
from geocoder.locationiq_reverse import LocationIQReverse
|
||||
from geocoder.komoot_reverse import KomootReverse
|
||||
from geocoder.mapbox_reverse import MapboxReverse
|
||||
from geocoder.mapquest_reverse import MapquestReverse
|
||||
from geocoder.mapzen_reverse import MapzenReverse
|
||||
from geocoder.opencage_reverse import OpenCageReverse
|
||||
from geocoder.osm_reverse import OsmReverse
|
||||
from geocoder.uscensus_reverse import USCensusReverse
|
||||
from geocoder.w3w_reverse import W3WReverse
|
||||
from geocoder.yandex_reverse import YandexReverse
|
||||
|
||||
from geocoder.mapquest_batch import MapquestBatch
|
||||
from geocoder.bing_batch_forward import BingBatchForward
|
||||
from geocoder.bing_batch_reverse import BingBatchReverse
|
||||
from geocoder.uscensus_batch import USCensusBatch
|
||||
|
||||
# Geonames Services
|
||||
from geocoder.geonames import GeonamesQuery
|
||||
from geocoder.geonames_details import GeonamesDetails
|
||||
from geocoder.geonames_children import GeonamesChildren
|
||||
from geocoder.geonames_hierarchy import GeonamesHierarchy
|
||||
|
||||
# Google Services
|
||||
from geocoder.google import GoogleQuery
|
||||
from geocoder.google_timezone import TimezoneQuery
|
||||
from geocoder.google_reverse import GoogleReverse
|
||||
from geocoder.google_elevation import ElevationQuery
|
||||
from geocoder.google_places import PlacesQuery
|
||||
|
||||
options = {
|
||||
'osm': {
|
||||
'geocode': OsmQuery,
|
||||
'details': OsmQueryDetail,
|
||||
'reverse': OsmReverse,
|
||||
},
|
||||
'tgos': {
|
||||
'geocode': TgosQuery
|
||||
},
|
||||
'here': {
|
||||
'geocode': HereQuery,
|
||||
'reverse': HereReverse,
|
||||
},
|
||||
'baidu': {
|
||||
'geocode': BaiduQuery,
|
||||
'reverse': BaiduReverse
|
||||
},
|
||||
'gaode': {
|
||||
'geocode': GaodeQuery,
|
||||
'reverse': GaodeReverse
|
||||
},
|
||||
'yahoo': {'geocode': YahooQuery},
|
||||
'tomtom': {'geocode': TomtomQuery},
|
||||
'arcgis': {
|
||||
'geocode': ArcgisQuery,
|
||||
'reverse': ArcgisReverse
|
||||
},
|
||||
'ottawa': {'geocode': OttawaQuery},
|
||||
'mapbox': {
|
||||
'geocode': MapboxQuery,
|
||||
'reverse': MapboxReverse,
|
||||
},
|
||||
'maxmind': {'geocode': MaxmindQuery},
|
||||
'ipinfo': {'geocode': IpinfoQuery},
|
||||
'geonames': {
|
||||
'geocode': GeonamesQuery,
|
||||
'details': GeonamesDetails,
|
||||
'timezone': GeonamesDetails,
|
||||
'children': GeonamesChildren,
|
||||
'hierarchy': GeonamesHierarchy
|
||||
},
|
||||
'freegeoip': {'geocode': FreeGeoIPQuery},
|
||||
'w3w': {
|
||||
'geocode': W3WQuery,
|
||||
'reverse': W3WReverse,
|
||||
},
|
||||
'yandex': {
|
||||
'geocode': YandexQuery,
|
||||
'reverse': YandexReverse
|
||||
},
|
||||
'mapquest': {
|
||||
'geocode': MapquestQuery,
|
||||
'reverse': MapquestReverse,
|
||||
'batch': MapquestBatch
|
||||
},
|
||||
'geolytica': {'geocode': GeolyticaQuery},
|
||||
'canadapost': {'geocode': CanadapostQuery},
|
||||
'opencage': {
|
||||
'geocode': OpenCageQuery,
|
||||
'reverse': OpenCageReverse,
|
||||
},
|
||||
'bing': {
|
||||
'geocode': BingQuery,
|
||||
'details': BingQueryDetail,
|
||||
'reverse': BingReverse,
|
||||
'batch': BingBatchForward,
|
||||
'batch_reverse': BingBatchReverse
|
||||
},
|
||||
'google': {
|
||||
'geocode': GoogleQuery,
|
||||
'reverse': GoogleReverse,
|
||||
'timezone': TimezoneQuery,
|
||||
'elevation': ElevationQuery,
|
||||
'places': PlacesQuery,
|
||||
},
|
||||
'mapzen': {
|
||||
'geocode': MapzenQuery,
|
||||
'reverse': MapzenReverse,
|
||||
},
|
||||
'komoot': {
|
||||
'geocode': KomootQuery,
|
||||
'reverse': KomootReverse,
|
||||
},
|
||||
'tamu': {
|
||||
'geocode': TamuQuery
|
||||
},
|
||||
'geocodefarm': {
|
||||
'geocode': GeocodeFarmQuery,
|
||||
'reverse': GeocodeFarmReverse,
|
||||
},
|
||||
'uscensus': {
|
||||
'geocode': USCensusQuery,
|
||||
'reverse': USCensusReverse,
|
||||
'batch': USCensusBatch
|
||||
},
|
||||
'locationiq': {
|
||||
'geocode': LocationIQQuery,
|
||||
'reverse': LocationIQReverse,
|
||||
},
|
||||
'gisgraphy': {
|
||||
'geocode': GisgraphyQuery,
|
||||
'reverse': GisgraphyReverse,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def get(location, **kwargs):
|
||||
"""Get Geocode
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``provider``: The geocoding engine you want to use.
|
||||
|
||||
:param ``method``: Define the method (geocode, method).
|
||||
"""
|
||||
provider = kwargs.get('provider', 'bing').lower().strip()
|
||||
method = kwargs.get('method', 'geocode').lower().strip()
|
||||
if isinstance(location, (list, dict)) and method == 'geocode':
|
||||
raise ValueError("Location should be a string")
|
||||
|
||||
if provider not in options:
|
||||
raise ValueError("Invalid provider")
|
||||
|
||||
else:
|
||||
if method not in options[provider]:
|
||||
raise ValueError("Invalid method")
|
||||
return options[provider][method](location, **kwargs)
|
||||
|
||||
|
||||
def distance(*args, **kwargs):
|
||||
"""Distance tool measures the distance between two or multiple points.
|
||||
|
||||
:param ``location``: (min 2x locations) Your search location you want geocoded.
|
||||
:param ``units``: (default=kilometers) Unit of measurement.
|
||||
> kilometers
|
||||
> miles
|
||||
> feet
|
||||
> meters
|
||||
"""
|
||||
return Distance(*args, **kwargs)
|
||||
|
||||
|
||||
def location(location, **kwargs):
|
||||
"""Parser for different location formats
|
||||
"""
|
||||
return Location(location, **kwargs)
|
||||
|
||||
|
||||
def google(location, **kwargs):
|
||||
"""Google Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``method``: (default=geocode) Use the following:
|
||||
> geocode
|
||||
> places
|
||||
> reverse
|
||||
> batch
|
||||
> timezone
|
||||
> elevation
|
||||
"""
|
||||
return get(location, provider='google', **kwargs)
|
||||
|
||||
|
||||
def mapbox(location, **kwargs):
|
||||
"""Mapbox Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``proximity``: Search nearby [lat, lng]
|
||||
:param ``method``: (default=geocode) Use the following:
|
||||
> geocode
|
||||
> reverse
|
||||
> batch
|
||||
"""
|
||||
return get(location, provider='mapbox', **kwargs)
|
||||
|
||||
|
||||
def yandex(location, **kwargs):
|
||||
"""Yandex Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``maxRows``: (default=1) Max number of results to fetch
|
||||
:param ``lang``: Chose the following language:
|
||||
> ru-RU — Russian (by default)
|
||||
> uk-UA — Ukrainian
|
||||
> be-BY — Belarusian
|
||||
> en-US — American English
|
||||
> en-BR — British English
|
||||
> tr-TR — Turkish (only for maps of Turkey)
|
||||
:param ``kind``: Type of toponym (only for reverse geocoding):
|
||||
> house - house or building
|
||||
> street - street
|
||||
> metro - subway station
|
||||
> district - city district
|
||||
> locality - locality (city, town, village, etc.)
|
||||
"""
|
||||
return get(location, provider='yandex', **kwargs)
|
||||
|
||||
|
||||
def w3w(location, **kwargs):
|
||||
"""what3words Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``key``: W3W API key.
|
||||
:param ``method``: Chose a method (geocode, method)
|
||||
"""
|
||||
return get(location, provider='w3w', **kwargs)
|
||||
|
||||
|
||||
def baidu(location, **kwargs):
|
||||
"""Baidu Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``key``: Baidu API key.
|
||||
:param ``referer``: Baidu API referer website.
|
||||
"""
|
||||
return get(location, provider='baidu', **kwargs)
|
||||
|
||||
|
||||
def gaode(location, **kwargs):
|
||||
"""Gaode Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``key``: Gaode API key.
|
||||
:param ``referer``: Gaode API referer website.
|
||||
"""
|
||||
return get(location, provider='gaode', **kwargs)
|
||||
|
||||
|
||||
def komoot(location, **kwargs):
|
||||
"""Ottawa Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
"""
|
||||
return get(location, provider='komoot', **kwargs)
|
||||
|
||||
|
||||
def ottawa(location, **kwargs):
|
||||
"""Ottawa Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``maxRows``: (default=1) Max number of results to fetch
|
||||
"""
|
||||
return get(location, provider='ottawa', **kwargs)
|
||||
|
||||
|
||||
def elevation(location, **kwargs):
|
||||
"""Elevation - Google Provider
|
||||
|
||||
:param ``location``: Your search location you want to retrieve elevation data.
|
||||
"""
|
||||
return get(location, method='elevation', provider='google', **kwargs)
|
||||
|
||||
|
||||
def places(location, **kwargs):
|
||||
"""Places - Google Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``proximity``: Search within given area (bbox, bounds, or around latlng)
|
||||
"""
|
||||
return get(location, method='places', provider='google', **kwargs)
|
||||
|
||||
|
||||
def timezone(location, **kwargs):
|
||||
"""Timezone - Google Provider
|
||||
|
||||
:param ``location``: Your search location you want to retrieve timezone data.
|
||||
:param ``timestamp``: Define your own specified time to calculate timezone.
|
||||
"""
|
||||
return get(location, method='timezone', provider='google', **kwargs)
|
||||
|
||||
|
||||
def reverse(location, provider="google", **kwargs):
|
||||
"""Reverse Geocoding
|
||||
|
||||
:param ``location``: Your search location you want to reverse geocode.
|
||||
:param ``key``: (optional) use your own API Key from Bing.
|
||||
:param ``provider``: (default=google) Use the following:
|
||||
> google
|
||||
> bing
|
||||
"""
|
||||
return get(location, method='reverse', provider=provider, **kwargs)
|
||||
|
||||
|
||||
def bing(location, **kwargs):
|
||||
"""Bing Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``key``: (optional) use your own API Key from Bing.
|
||||
:param ``maxRows``: (default=1) Max number of results to fetch
|
||||
:param ``method``: (default=geocode) Use the following:
|
||||
> geocode
|
||||
> reverse
|
||||
"""
|
||||
return get(location, provider='bing', **kwargs)
|
||||
|
||||
|
||||
def yahoo(location, **kwargs):
|
||||
"""Yahoo Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
"""
|
||||
return get(location, provider='yahoo', **kwargs)
|
||||
|
||||
|
||||
def geolytica(location, **kwargs):
|
||||
"""Geolytica (Geocoder.ca) Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
"""
|
||||
return get(location, provider='geolytica', **kwargs)
|
||||
|
||||
|
||||
def opencage(location, **kwargs):
|
||||
"""Opencage Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``key``: (optional) use your own API Key from OpenCage.
|
||||
"""
|
||||
return get(location, provider='opencage', **kwargs)
|
||||
|
||||
|
||||
def arcgis(location, **kwargs):
|
||||
"""ArcGIS Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
"""
|
||||
return get(location, provider='arcgis', **kwargs)
|
||||
|
||||
|
||||
def here(location, **kwargs):
|
||||
"""HERE Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``app_code``: (optional) use your own Application Code from HERE.
|
||||
:param ``app_id``: (optional) use your own Application ID from HERE.
|
||||
:param ``maxRows``: (default=1) Max number of results to fetch
|
||||
:param ``method``: (default=geocode) Use the following:
|
||||
> geocode
|
||||
> reverse
|
||||
"""
|
||||
return get(location, provider='here', **kwargs)
|
||||
|
||||
|
||||
def nokia(location, **kwargs):
|
||||
"""HERE Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``app_code``: (optional) use your own Application Code from HERE.
|
||||
:param ``app_id``: (optional) use your own Application ID from HERE.
|
||||
:param ``method``: (default=geocode) Use the following:
|
||||
> geocode
|
||||
> reverse
|
||||
"""
|
||||
return get(location, provider='here', **kwargs)
|
||||
|
||||
|
||||
def tomtom(location, **kwargs):
|
||||
"""TomTom Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``key``: (optional) use your own API Key from TomTom.
|
||||
:param ``maxRows``: (default=1) Max number of results to fetch
|
||||
"""
|
||||
return get(location, provider='tomtom', **kwargs)
|
||||
|
||||
|
||||
def mapquest(location, **kwargs):
|
||||
"""MapQuest Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``key``: (optional) use your own API Key from MapQuest.
|
||||
:param ``maxRows``: (default=1) Max number of results to fetch
|
||||
:param ``method``: (default=geocode) Use the following:
|
||||
> geocode
|
||||
> reverse
|
||||
"""
|
||||
return get(location, provider='mapquest', **kwargs)
|
||||
|
||||
|
||||
def osm(location, **kwargs):
|
||||
"""OSM Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``url``: Custom OSM Server URL location
|
||||
(ex: http://nominatim.openstreetmap.org/search)
|
||||
"""
|
||||
return get(location, provider='osm', **kwargs)
|
||||
|
||||
|
||||
def maxmind(location='me', **kwargs):
|
||||
"""MaxMind Provider
|
||||
|
||||
:param ``location``: Your search IP Address you want geocoded.
|
||||
:param ``location``: (optional) if left blank will return your
|
||||
current IP address's location.
|
||||
"""
|
||||
return get(location, provider='maxmind', **kwargs)
|
||||
|
||||
|
||||
def ipinfo(location='', **kwargs):
|
||||
"""IP Info.io Provider
|
||||
|
||||
:param ``location``: Your search IP Address you want geocoded.
|
||||
:param ``location``: (optional) if left blank will return your
|
||||
current IP address's location.
|
||||
"""
|
||||
return get(location, provider='ipinfo', **kwargs)
|
||||
|
||||
|
||||
def freegeoip(location, **kwargs):
|
||||
"""FreeGeoIP Provider
|
||||
|
||||
:param ``location``: Your search IP Address you want geocoded.
|
||||
:param ``location``: (optional) if left blank will return your
|
||||
current IP address's location.
|
||||
"""
|
||||
return get(location, provider='freegeoip', **kwargs)
|
||||
|
||||
|
||||
def ip(location, **kwargs):
|
||||
"""IP Address lookup
|
||||
|
||||
:param ``location``: Your search IP Address you want geocoded.
|
||||
:param ``location``: (optional) if left blank will return your
|
||||
current IP address's location.
|
||||
"""
|
||||
return get(location, provider='ipinfo', **kwargs)
|
||||
|
||||
|
||||
def canadapost(location, **kwargs):
|
||||
"""CanadaPost Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``key``: (optional) API Key from CanadaPost Address Complete.
|
||||
:param ``language``: (default=en) Output language preference.
|
||||
:param ``country``: (default=ca) Geofenced query by country.
|
||||
:param ``maxRows``: (default=1) Max number of results to fetch
|
||||
"""
|
||||
return get(location, provider='canadapost', **kwargs)
|
||||
|
||||
|
||||
def postal(location, **kwargs):
|
||||
"""CanadaPost Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``key``: (optional) use your own API Key from
|
||||
CanadaPost Address Complete.
|
||||
"""
|
||||
return get(location, provider='canadapost', **kwargs)
|
||||
|
||||
|
||||
def geonames(location, **kwargs):
|
||||
"""GeoNames Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``geonameid``: The place you want children / hierarchy for.
|
||||
:param ``key``: (required) geonames *username*: needs to be passed with each request.
|
||||
:param ``maxRows``: (default=1) Max number of results to fetch
|
||||
:param ``proximity``: Search within given area (bbox, bounds, or around latlng)
|
||||
:param ``method``: (default=geocode) Use the following:
|
||||
> geocode
|
||||
> details (mainly for administrive data and timezone)
|
||||
> timezone (alias for details)
|
||||
> children
|
||||
> hierarchy
|
||||
"""
|
||||
return get(location, provider='geonames', **kwargs)
|
||||
|
||||
|
||||
def mapzen(location, **kwargs):
|
||||
"""Mapzen Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``maxRows``: (default=1) Max number of results to fetch
|
||||
"""
|
||||
return get(location, provider='mapzen', **kwargs)
|
||||
|
||||
|
||||
def tamu(location, **kwargs):
|
||||
"""TAMU Provider
|
||||
|
||||
Params
|
||||
------
|
||||
:param ``location``: The street address of the location you want geocoded.
|
||||
:param ``city``: The city of the location to geocode.
|
||||
:param ``state``: The state of the location to geocode.
|
||||
:param ``zipcode``: The zipcode of the location to geocode.
|
||||
:param ``key``: The API key (use API key "demo" for testing).
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://geoservices.tamu.edu/Services/Geocode/WebService
|
||||
"""
|
||||
return get(location, provider='tamu', **kwargs)
|
||||
|
||||
|
||||
def geocodefarm(location, **kwargs):
|
||||
"""GeocodeFarm Provider
|
||||
|
||||
Params
|
||||
------
|
||||
:param ``location``: The string to search for. Usually a street address.
|
||||
:param ``key``: (optional) API Key. Only Required for Paid Users.
|
||||
:param ``lang``: (optional) 2 digit language code to return results in. Currently only "en"(English) or "de"(German) supported.
|
||||
:param ``country``: (optional) The country to return results in. Used for biasing purposes and may not fully filter results to this specific country.
|
||||
:param ``maxRows``: (default=1) Max number of results to fetch
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://geocode.farm/geocoding/free-api-documentation/
|
||||
"""
|
||||
return get(location, provider='geocodefarm', **kwargs)
|
||||
|
||||
|
||||
def tgos(location, **kwargs):
|
||||
"""TGOS Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``language``: (default=taiwan) Use the following:
|
||||
> taiwan
|
||||
> english
|
||||
> chinese
|
||||
:param ``method``: (default=geocode) Use the following:
|
||||
> geocode
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://api.tgos.nat.gov.tw/TGOS_MAP_API/Web/Default.aspx
|
||||
"""
|
||||
return get(location, provider='tgos', **kwargs)
|
||||
|
||||
|
||||
def uscensus(location, **kwargs):
|
||||
"""US Census Provider
|
||||
|
||||
Params
|
||||
------
|
||||
:param ``location``: Your search location(s) you want geocoded.
|
||||
:param ``benchmark``: (default=4) Use the following:
|
||||
> Public_AR_Current or 4
|
||||
> Public_AR_ACSYYYY or 8
|
||||
> Public_AR_Census2010 or 9
|
||||
:param ``vintage``: (default=4, not available with batch method) Use the following:
|
||||
> Current_Current or 4
|
||||
> Census2010_Current or 410
|
||||
> ACS2013_Current or 413
|
||||
> ACS2014_Current or 414
|
||||
> ACS2015_Current or 415
|
||||
> Current_ACS2015 or 8
|
||||
> Census2010_ACS2015 or 810
|
||||
> ACS2013_ACS2015 or 813
|
||||
> ACS2014_ACS2015 or 814
|
||||
> ACS2015_ACS2015 or 815
|
||||
> Census2010_Census2010 or 910
|
||||
> Census2000_Census2010 or 900
|
||||
:param ``method``: (default=geocode) Use the following:
|
||||
> geocode
|
||||
> reverse
|
||||
> batch
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://geocoding.geo.census.gov/geocoder/Geocoding_Services_API.pdf
|
||||
"""
|
||||
return get(location, provider='uscensus', **kwargs)
|
||||
|
||||
|
||||
def locationiq(location, **kwargs):
|
||||
"""LocationIQ Provider
|
||||
|
||||
Params
|
||||
------
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``method``: (default=geocode) Use the following:
|
||||
> geocode
|
||||
> reverse
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://locationiq.org/
|
||||
"""
|
||||
return get(location, provider='locationiq', **kwargs)
|
||||
|
||||
|
||||
def gisgraphy(location, **kwargs):
|
||||
"""Gisgraphy Provider
|
||||
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
"""
|
||||
return get(location, provider='gisgraphy', **kwargs)
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import json
|
||||
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
|
||||
|
||||
class ArcgisResult(OneResult):
|
||||
|
||||
def __init__(self, json_content):
|
||||
# create safe shortcuts
|
||||
self._feature = json_content.get('feature', {})
|
||||
|
||||
# proceed with super.__init__
|
||||
super(ArcgisResult, self).__init__(json_content)
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw.get('name', '')
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self._feature.get('geometry', {}).get('y')
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self._feature.get('geometry', {}).get('x')
|
||||
|
||||
@property
|
||||
def score(self):
|
||||
return self._feature.get('attributes', {}).get('Score', '')
|
||||
|
||||
@property
|
||||
def quality(self):
|
||||
return self._feature.get('attributes', {}).get('Addr_Type', '')
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
_extent = self.raw.get('extent')
|
||||
if _extent:
|
||||
south = _extent.get('ymin')
|
||||
west = _extent.get('xmin')
|
||||
north = _extent.get('ymax')
|
||||
east = _extent.get('xmax')
|
||||
return self._get_bbox(south, west, north, east)
|
||||
|
||||
|
||||
class ArcgisQuery(MultipleResultsQuery):
|
||||
"""
|
||||
ArcGIS REST API
|
||||
=======================
|
||||
The World Geocoding Service finds addresses and places in all supported countries
|
||||
from a single endpoint. The service can find point locations of addresses,
|
||||
business names, and so on. The output points can be visualized on a map,
|
||||
inserted as stops for a route, or loaded as input for a spatial analysis.
|
||||
an address, retrieving imagery metadata, or creating a route.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://developers.arcgis.com/rest/geocode/api-reference/geocoding-find.htm
|
||||
"""
|
||||
provider = 'arcgis'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find'
|
||||
_RESULT_CLASS = ArcgisResult
|
||||
_KEY_MANDATORY = False
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
# backward compatitibility for 'limit' (now maxRows)
|
||||
if 'limit' in kwargs:
|
||||
logging.warning(
|
||||
"argument 'limit' in OSM is deprecated and should be replaced with maxRows")
|
||||
kwargs['maxRows'] = kwargs['limit']
|
||||
# build params
|
||||
return {
|
||||
'f': 'json',
|
||||
'text': location,
|
||||
'maxLocations': kwargs.get('maxRows', 1),
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return json_response['locations']
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
status = json_response.get('error')
|
||||
if status:
|
||||
self.error = status.get('code')
|
||||
self.message = status.get('message')
|
||||
self.details = status.get('details')
|
||||
|
||||
return self.error
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = ArcgisQuery('Toronto')
|
||||
g.debug()
|
||||
g = ArcgisQuery('Ottawa, Ontario', maxRows=5)
|
||||
print(json.dumps(g.geojson, indent=4))
|
||||
print([result.address for result in g][:3])
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,98 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.base import OneResult
|
||||
from geocoder.arcgis import ArcgisQuery
|
||||
from geocoder.location import Location
|
||||
|
||||
|
||||
class ArcgisReverseResult(OneResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.address)
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self.raw['location'].get('y')
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self.raw['location'].get('x')
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw['address'].get('Match_addr')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.raw['address'].get('City')
|
||||
|
||||
@property
|
||||
def neighborhood(self):
|
||||
return self.raw['address'].get('Neighbourhood')
|
||||
|
||||
@property
|
||||
def region(self):
|
||||
return self.raw['address'].get('Region')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw['address'].get('CountryCode')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self.raw['address'].get('Postal')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw['address'].get('Region')
|
||||
|
||||
|
||||
class ArcgisReverse(ArcgisQuery):
|
||||
"""
|
||||
ArcGIS REST API
|
||||
=======================
|
||||
The World Geocoding Service finds addresses and places in all supported countries
|
||||
from a single endpoint. The service can find point locations of addresses,
|
||||
business names, and so on. The output points can be visualized on a map,
|
||||
inserted as stops for a route, or loaded as input for a spatial analysis.
|
||||
an address, retrieving imagery metadata, or creating a route.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://developers.arcgis.com/rest/geocode/api-reference/geocoding-reverse-geocode.htm
|
||||
"""
|
||||
provider = 'arcgis'
|
||||
method = 'reverse'
|
||||
|
||||
_URL = 'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode'
|
||||
_RESULT_CLASS = ArcgisReverseResult
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
location = Location(location)
|
||||
return {
|
||||
'location': u'{}, {}'.format(location.lng, location.lat),
|
||||
'f': 'pjson',
|
||||
'distance': kwargs.get('distance', 50000),
|
||||
'outSR': kwargs.get('outSR', '')
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return [json_response]
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
error = json_response.get('error', None)
|
||||
if error:
|
||||
self.error = error['message']
|
||||
|
||||
return self.error
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = ArcgisReverse("45.404702, -75.704150")
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,135 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from collections import OrderedDict
|
||||
import logging
|
||||
import re
|
||||
import six
|
||||
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import baidu_key, baidu_security_key
|
||||
|
||||
|
||||
class BaiduResult(OneResult):
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self.raw.get('location', {}).get('lat')
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self.raw.get('location', {}).get('lng')
|
||||
|
||||
@property
|
||||
def quality(self):
|
||||
return self.raw.get('level')
|
||||
|
||||
@property
|
||||
def confidence(self):
|
||||
return self.raw.get('confidence')
|
||||
|
||||
|
||||
class BaiduQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Baidu Geocoding API
|
||||
===================
|
||||
Baidu Maps Geocoding API is a free open the API, the default quota
|
||||
one million times / day.
|
||||
|
||||
Params
|
||||
------
|
||||
:param location: Your search location you want geocoded.
|
||||
:param key: Baidu API key.
|
||||
:param referer: Baidu API referer website.
|
||||
|
||||
References
|
||||
----------
|
||||
API Documentation: http://developer.baidu.com/map
|
||||
Get Baidu Key: http://lbsyun.baidu.com/apiconsole/key
|
||||
"""
|
||||
provider = 'baidu'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'http://api.map.baidu.com/geocoder/v2/'
|
||||
_RESULT_CLASS = BaiduResult
|
||||
_KEY = baidu_key
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
coordtype = kwargs.get('coordtype', 'wgs84ll')
|
||||
params = {
|
||||
'address': re.sub('[ ,]', '%', location),
|
||||
'output': 'json',
|
||||
'ret_coordtype': coordtype,
|
||||
'ak': provider_key,
|
||||
}
|
||||
|
||||
# adapt params to authentication method
|
||||
self.security_key = kwargs.get('sk', baidu_security_key)
|
||||
if self.security_key:
|
||||
return self._encode_params(params)
|
||||
else:
|
||||
return params
|
||||
|
||||
def _encode_params(self, params):
|
||||
# maintain the order of the parameters during signature creation when returning the results
|
||||
# signature is added to the end of the parameters
|
||||
ordered_params = sorted([(k, v)
|
||||
for (k, v) in params.items() if v])
|
||||
|
||||
params = OrderedDict(ordered_params)
|
||||
|
||||
# urlencode with Chinese symbols sabotage the query
|
||||
params['sn'] = self._sign_url(
|
||||
'/geocoder/v2/',
|
||||
params,
|
||||
self.security_key
|
||||
)
|
||||
|
||||
return params
|
||||
|
||||
def _sign_url(self, base_url, params, security_key):
|
||||
"""
|
||||
Signs a request url with a security key.
|
||||
"""
|
||||
import hashlib
|
||||
|
||||
if six.PY3:
|
||||
from urllib.parse import urlencode, quote, quote_plus
|
||||
else:
|
||||
from urllib import urlencode, quote, quote_plus
|
||||
|
||||
if not base_url or not self.security_key:
|
||||
return None
|
||||
|
||||
params = params.copy()
|
||||
address = params.pop('address')
|
||||
|
||||
url = base_url + '?address=' + address + '&' + urlencode(params)
|
||||
encoded_url = quote(url, safe="/:=&?#+!$,;'@()*[]")
|
||||
|
||||
signature = quote_plus(encoded_url + self.security_key).encode('utf-8')
|
||||
encoded_signature = hashlib.md5(signature).hexdigest()
|
||||
|
||||
return encoded_signature
|
||||
|
||||
def _build_headers(self, provider_key, **kwargs):
|
||||
return {'Referer': kwargs.get('referer', 'http://developer.baidu.com')}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return [json_response['result']]
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
status_code = json_response.get('status')
|
||||
if status_code != 0:
|
||||
self.status_code = status_code
|
||||
self.error = json_response.get('message')
|
||||
|
||||
return self.error
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = BaiduQuery('将台路', key='')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.location import Location
|
||||
from geocoder.base import OneResult
|
||||
from geocoder.baidu import BaiduQuery
|
||||
|
||||
|
||||
class BaiduReverseResult(OneResult):
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.address)
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw['formatted_address']
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw['addressComponent']['country']
|
||||
|
||||
@property
|
||||
def province(self):
|
||||
return self.raw['addressComponent']['province']
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw['addressComponent']['province']
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.raw['addressComponent']['city']
|
||||
|
||||
@property
|
||||
def district(self):
|
||||
return self.raw['addressComponent']['district']
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self.raw['addressComponent']['street']
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self.raw['addressComponent']['street_number']
|
||||
|
||||
|
||||
class BaiduReverse(BaiduQuery):
|
||||
"""
|
||||
Baidu Geocoding API
|
||||
===================
|
||||
Baidu Maps Geocoding API is a free open the API, the default quota
|
||||
one million times / day.
|
||||
|
||||
Params
|
||||
------
|
||||
:param location: Your search location you want geocoded.
|
||||
:param key: Baidu API key.
|
||||
:param referer: Baidu API referer website.
|
||||
|
||||
References
|
||||
----------
|
||||
API Documentation: http://developer.baidu.com/map
|
||||
Get Baidu Key: http://lbsyun.baidu.com/apiconsole/key
|
||||
"""
|
||||
provider = 'baidu'
|
||||
method = 'reverse'
|
||||
|
||||
_URL = 'http://api.map.baidu.com/geocoder/v2/'
|
||||
_RESULT_CLASS = BaiduReverseResult
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
location = Location(location)
|
||||
params = {
|
||||
'location': str(location),
|
||||
'ret_coordtype': kwargs.get('coordtype', 'wgs84ll'),
|
||||
'output': 'json',
|
||||
'ak': provider_key
|
||||
}
|
||||
if ('lang_code' in kwargs):
|
||||
params['accept-language'] = kwargs['lang_code']
|
||||
|
||||
return params
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = BaiduReverse("39.983424,116.32298", key='')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,606 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
from __future__ import absolute_import, print_function
|
||||
from builtins import str
|
||||
|
||||
import requests
|
||||
import sys
|
||||
import json
|
||||
import six
|
||||
import logging
|
||||
from io import StringIO
|
||||
from collections import OrderedDict
|
||||
|
||||
is_python2 = sys.version_info < (3, 0)
|
||||
|
||||
if is_python2:
|
||||
# python 2.7
|
||||
from urlparse import urlparse
|
||||
|
||||
class MutableSequence(object):
|
||||
def index(self, v, **kwargs): return self._list.index(v, **kwargs) # noqa
|
||||
def count(self, v): return self._list.count(v) # noqa
|
||||
def pop(self, i=-1): return self._list.pop(i) # noqa
|
||||
def remove(self, v): self._list.remove(v) # noqa
|
||||
def __iter__(self): return iter(self._list) # noqa
|
||||
def __contains__(self, v): return self._list.__contains__(v) # noqa
|
||||
def __eq__(self, other): return self._list == other # noqa
|
||||
else:
|
||||
# python >3.3
|
||||
from collections.abc import MutableSequence
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from geocoder.distance import Distance # noqa
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OneResult(object):
|
||||
""" Container for one (JSON) object returned by the various web services"""
|
||||
|
||||
_TO_EXCLUDE = ['parse', 'json', 'url', 'fieldnames', 'help', 'debug',
|
||||
'short_name', 'api', 'content', 'params',
|
||||
'street_number', 'api_key', 'key', 'id', 'x', 'y',
|
||||
'latlng', 'headers', 'timeout', 'wkt', 'locality',
|
||||
'province', 'rate_limited_get', 'osm', 'route', 'schema',
|
||||
'properties', 'geojson', 'tree', 'error', 'proxies', 'road',
|
||||
'xy', 'northeast', 'northwest', 'southeast', 'southwest',
|
||||
'road_long', 'city_long', 'state_long', 'country_long',
|
||||
'postal_town_long', 'province_long', 'road_long',
|
||||
'street_long', 'interpolated', 'method', 'geometry', 'session']
|
||||
|
||||
def __init__(self, json_content):
|
||||
|
||||
self.raw = json_content
|
||||
|
||||
# attributes required to compute bbox
|
||||
self.northeast = []
|
||||
self.northwest = []
|
||||
self.southeast = []
|
||||
self.southwest = []
|
||||
|
||||
# attributes returned in JSON format
|
||||
self.fieldnames = []
|
||||
self.json = {}
|
||||
self._parse_json_with_fieldnames()
|
||||
|
||||
# Essential attributes for Quality Control
|
||||
@property # noqa
|
||||
def lat(self): return '' # noqa
|
||||
|
||||
@property # noqa
|
||||
def lng(self): return '' # noqa
|
||||
|
||||
@property # noqa
|
||||
def accuracy(self): return '' # noqa
|
||||
|
||||
@property # noqa
|
||||
def quality(self): return '' # noqa
|
||||
|
||||
# Bounding Box attributes
|
||||
@property # noqa
|
||||
def bbox(self): return {} # noqa
|
||||
|
||||
# Essential attributes for Street Address
|
||||
@property # noqa
|
||||
def address(self): return '' # noqa
|
||||
|
||||
@property # noqa
|
||||
def housenumber(self): return '' # noqa
|
||||
|
||||
@property # noqa
|
||||
def street(self): return '' # noqa
|
||||
|
||||
@property # noqa
|
||||
def city(self): return '' # noqa
|
||||
|
||||
@property # noqa
|
||||
def state(self): return '' # noqa
|
||||
|
||||
@property # noqa
|
||||
def country(self): return '' # noqa
|
||||
|
||||
@property # noqa
|
||||
def postal(self): return '' # noqa
|
||||
|
||||
def __repr__(self):
|
||||
""" Display [address] if available; [lat,lng] otherwise"""
|
||||
if self.address:
|
||||
return u'[{0}]'.format(six.text_type(self.address))
|
||||
else:
|
||||
return u'[{0},{1}]'.format(self.lat, self.lng)
|
||||
|
||||
def _parse_json_with_fieldnames(self):
|
||||
""" Parse the raw JSON with all attributes/methods defined in the class, except for the
|
||||
ones defined starting with '_' or flagged in cls._TO_EXCLUDE.
|
||||
|
||||
The final result is stored in self.json
|
||||
"""
|
||||
for key in dir(self):
|
||||
if not key.startswith('_') and key not in self._TO_EXCLUDE:
|
||||
self.fieldnames.append(key)
|
||||
value = getattr(self, key)
|
||||
if value:
|
||||
self.json[key] = value
|
||||
# Add OK attribute even if value is "False"
|
||||
self.json['ok'] = self.ok
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.lng and self.lat)
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
if self.ok:
|
||||
return 'OK'
|
||||
if not self.address:
|
||||
return 'ERROR - No results found'
|
||||
return 'ERROR - No Geometry'
|
||||
|
||||
def debug(self, verbose=True):
|
||||
with StringIO() as output:
|
||||
print(u'\n', file=output)
|
||||
print(u'From provider\n', file=output)
|
||||
print(u'-----------\n', file=output)
|
||||
print(str(json.dumps(self.raw, indent=4)), file=output)
|
||||
print(u'\n', file=output)
|
||||
print(u'Cleaned json\n', file=output)
|
||||
print(u'-----------\n', file=output)
|
||||
print(str(json.dumps(self.json, indent=4)), file=output)
|
||||
print(u'\n', file=output)
|
||||
print(u'OSM Quality\n', file=output)
|
||||
print(u'-----------\n', file=output)
|
||||
osm_count = 0
|
||||
for key in self.osm:
|
||||
if 'addr:' in key:
|
||||
if self.json.get(key.replace('addr:', '')):
|
||||
print(u'- [x] {0}\n'.format(key), file=output)
|
||||
osm_count += 1
|
||||
else:
|
||||
print(u'- [ ] {0}\n'.format(key), file=output)
|
||||
print(u'({0}/{1})\n'.format(osm_count, len(self.osm) - 2), file=output)
|
||||
print(u'\n', file=output)
|
||||
print(u'Fieldnames\n', file=output)
|
||||
print(u'----------\n', file=output)
|
||||
fields_count = 0
|
||||
for fieldname in self.fieldnames:
|
||||
if self.json.get(fieldname):
|
||||
print(u'- [x] {0}\n'.format(fieldname), file=output)
|
||||
fields_count += 1
|
||||
else:
|
||||
print(u'- [ ] {0}\n'.format(fieldname), file=output)
|
||||
print(u'({0}/{1})\n'.format(fields_count, len(self.fieldnames)), file=output)
|
||||
|
||||
# print in verbose mode
|
||||
if verbose:
|
||||
print(output.getvalue())
|
||||
|
||||
# return stats
|
||||
return [osm_count, fields_count]
|
||||
|
||||
def _get_bbox(self, south, west, north, east):
|
||||
if all([south, east, north, west]):
|
||||
# South Latitude, West Longitude, North Latitude, East Longitude
|
||||
self.south = float(south)
|
||||
self.west = float(west)
|
||||
self.north = float(north)
|
||||
self.east = float(east)
|
||||
|
||||
# Bounding Box Corners
|
||||
self.northeast = [self.north, self.east]
|
||||
self.northwest = [self.north, self.west]
|
||||
self.southwest = [self.south, self.west]
|
||||
self.southeast = [self.south, self.east]
|
||||
|
||||
# GeoJSON bbox
|
||||
self.westsouth = [self.west, self.south]
|
||||
self.eastnorth = [self.east, self.north]
|
||||
|
||||
return dict(northeast=self.northeast, southwest=self.southwest)
|
||||
return {}
|
||||
|
||||
@property
|
||||
def confidence(self):
|
||||
if self.bbox:
|
||||
# Units are measured in Kilometers
|
||||
distance = Distance(self.northeast, self.southwest, units='km')
|
||||
for score, maximum in [(10, 0.25),
|
||||
(9, 0.5),
|
||||
(8, 1),
|
||||
(7, 5),
|
||||
(6, 7.5),
|
||||
(5, 10),
|
||||
(4, 15),
|
||||
(3, 20),
|
||||
(2, 25)]:
|
||||
if distance < maximum:
|
||||
return score
|
||||
if distance >= 25:
|
||||
return 1
|
||||
# Cannot determine score
|
||||
return 0
|
||||
|
||||
@property
|
||||
def geometry(self):
|
||||
if self.ok:
|
||||
return {
|
||||
'type': 'Point',
|
||||
'coordinates': [self.x, self.y]}
|
||||
return {}
|
||||
|
||||
@property
|
||||
def osm(self):
|
||||
osm = dict()
|
||||
if self.ok:
|
||||
osm['x'] = self.x
|
||||
osm['y'] = self.y
|
||||
if self.housenumber:
|
||||
osm['addr:housenumber'] = self.housenumber
|
||||
if self.road:
|
||||
osm['addr:street'] = self.road
|
||||
if self.city:
|
||||
osm['addr:city'] = self.city
|
||||
if self.state:
|
||||
osm['addr:state'] = self.state
|
||||
if self.country:
|
||||
osm['addr:country'] = self.country
|
||||
if self.postal:
|
||||
osm['addr:postal'] = self.postal
|
||||
if hasattr(self, 'population'):
|
||||
if self.population:
|
||||
osm['population'] = self.population
|
||||
return osm
|
||||
|
||||
@property
|
||||
def geojson(self):
|
||||
feature = {
|
||||
'type': 'Feature',
|
||||
'properties': self.json,
|
||||
}
|
||||
if self.bbox:
|
||||
feature['bbox'] = [self.west, self.south, self.east, self.north]
|
||||
feature['properties']['bbox'] = feature['bbox']
|
||||
if self.geometry:
|
||||
feature['geometry'] = self.geometry
|
||||
return feature
|
||||
|
||||
@property
|
||||
def wkt(self):
|
||||
if self.ok:
|
||||
return 'POINT({x} {y})'.format(x=self.x, y=self.y)
|
||||
return ''
|
||||
|
||||
@property
|
||||
def xy(self):
|
||||
if self.ok:
|
||||
return [self.lng, self.lat]
|
||||
return []
|
||||
|
||||
@property
|
||||
def latlng(self):
|
||||
if self.ok:
|
||||
return [self.lat, self.lng]
|
||||
return []
|
||||
|
||||
@property
|
||||
def y(self):
|
||||
return self.lat
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return self.lng
|
||||
|
||||
@property
|
||||
def locality(self):
|
||||
return self.city
|
||||
|
||||
@property
|
||||
def province(self):
|
||||
return self.state
|
||||
|
||||
@property
|
||||
def street_number(self):
|
||||
return self.housenumber
|
||||
|
||||
@property
|
||||
def road(self):
|
||||
return self.street
|
||||
|
||||
@property
|
||||
def route(self):
|
||||
return self.street
|
||||
|
||||
|
||||
class MultipleResultsQuery(MutableSequence):
|
||||
""" Will replace the Base class to support multiple results, with the following differences :
|
||||
|
||||
- split class into 2 parts :
|
||||
- OneResult to actually store a (JSON) object from provider
|
||||
- MultipleResultsQuery to manage the query
|
||||
|
||||
- class variables moved into instance
|
||||
- remaining class variables are names with convention: _CAPITALS
|
||||
- self.url derived from class var cls.URL, which must be a valid URL
|
||||
- self.timeout has default value from class var cls.TIMEOUT
|
||||
"""
|
||||
|
||||
_URL = None
|
||||
_RESULT_CLASS = None
|
||||
_KEY = None
|
||||
_KEY_MANDATORY = True
|
||||
_TIMEOUT = 5.0
|
||||
|
||||
@staticmethod
|
||||
def _is_valid_url(url):
|
||||
""" Helper function to validate that URLs are well formed, i.e that it contains a valid
|
||||
protocol and a valid domain. It does not actually check if the URL exists
|
||||
"""
|
||||
try:
|
||||
parsed = urlparse(url)
|
||||
mandatory_parts = [parsed.scheme, parsed.netloc]
|
||||
return all(mandatory_parts)
|
||||
except:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def _is_valid_result_class(cls):
|
||||
return issubclass(cls._RESULT_CLASS, OneResult)
|
||||
|
||||
@classmethod
|
||||
def _get_api_key(cls, key=None):
|
||||
# Retrieves API Key from method argument first, then from Environment variables
|
||||
key = key or cls._KEY
|
||||
|
||||
# raise exception if not valid key found
|
||||
if not key and cls._KEY_MANDATORY:
|
||||
raise ValueError('Provide API Key')
|
||||
|
||||
return key
|
||||
|
||||
def __init__(self, location, **kwargs):
|
||||
super(MultipleResultsQuery, self).__init__()
|
||||
self._list = []
|
||||
|
||||
# check validity of _URL
|
||||
if not self._is_valid_url(self._URL):
|
||||
raise ValueError("Subclass must define a valid URL. Got %s", self._URL)
|
||||
# override with kwargs IF given AND not empty string
|
||||
self.url = kwargs.get('url', self._URL) or self._URL
|
||||
# double check url, just in case it has been overwritten by kwargs
|
||||
if not self._is_valid_url(self.url):
|
||||
raise ValueError("url not valid. Got %s", self.url)
|
||||
|
||||
# check validity of Result class
|
||||
if not self._is_valid_result_class():
|
||||
raise ValueError(
|
||||
"Subclass must define _RESULT_CLASS from 'OneResult'. Got %s", self._RESULT_CLASS)
|
||||
self.one_result = self._RESULT_CLASS
|
||||
|
||||
# check validity of provider key
|
||||
provider_key = self._get_api_key(kwargs.pop('key', ''))
|
||||
|
||||
# point to geocode, as a string or coordinates
|
||||
self.location = location
|
||||
|
||||
# set attributes to manage query
|
||||
self.encoding = kwargs.get('encoding', 'utf-8')
|
||||
self.timeout = kwargs.get('timeout', self._TIMEOUT)
|
||||
self.proxies = kwargs.get('proxies', '')
|
||||
self.session = kwargs.get('session', requests.Session())
|
||||
# headers can be overriden in _build_headers
|
||||
self.headers = self._build_headers(provider_key, **kwargs).copy()
|
||||
self.headers.update(kwargs.get('headers', {}))
|
||||
# params can be overriden in _build_params
|
||||
# it is an OrderedDict in order to preserve the order of the url query parameters
|
||||
self.params = OrderedDict(self._build_params(location, provider_key, **kwargs))
|
||||
self.params.update(kwargs.get('params', {}))
|
||||
|
||||
# results of query (set by _connect)
|
||||
self.status_code = None
|
||||
self.response = None
|
||||
self.error = False
|
||||
|
||||
# pointer to result where to delegates calls
|
||||
self.current_result = None
|
||||
|
||||
# hook for children class to finalize their setup before the query
|
||||
self._before_initialize(location, **kwargs)
|
||||
|
||||
# query and parse results
|
||||
self._initialize()
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self._list[key]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self._list[key] = value
|
||||
|
||||
def __delitem__(self, key):
|
||||
del self._list[key]
|
||||
|
||||
def __len__(self):
|
||||
return len(self._list)
|
||||
|
||||
def insert(self, index, value):
|
||||
self._list.insert(index, value)
|
||||
|
||||
def add(self, value):
|
||||
self._list.append(value)
|
||||
|
||||
def __repr__(self):
|
||||
base_repr = u'<[{0}] {1} - {2} {{0}}>'.format(
|
||||
self.status,
|
||||
self.provider.title(),
|
||||
self.method.title()
|
||||
)
|
||||
if len(self) == 0:
|
||||
return base_repr.format(u'[empty]')
|
||||
elif len(self) == 1:
|
||||
return base_repr.format(repr(self[0]))
|
||||
else:
|
||||
return base_repr.format(u'#%s results' % len(self))
|
||||
|
||||
def _build_headers(self, provider_key, **kwargs):
|
||||
"""Will be overridden according to the targetted web service"""
|
||||
return {}
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
"""Will be overridden according to the targetted web service"""
|
||||
return {}
|
||||
|
||||
def _before_initialize(self, location, **kwargs):
|
||||
"""Can be overridden to finalize setup before the query"""
|
||||
pass
|
||||
|
||||
def _initialize(self):
|
||||
# query URL and get valid JSON (also stored in self.json)
|
||||
json_response = self._connect()
|
||||
|
||||
# catch errors
|
||||
has_error = self._catch_errors(
|
||||
json_response) if json_response else True
|
||||
|
||||
# creates instances for results
|
||||
if not has_error:
|
||||
self._parse_results(json_response)
|
||||
|
||||
def _connect(self):
|
||||
""" - Query self.url (validated cls._URL)
|
||||
- Analyse reponse and set status, errors accordingly
|
||||
- On success:
|
||||
|
||||
returns the content of the response as a JSON object
|
||||
This object will be passed to self._parse_json_response
|
||||
"""
|
||||
self.status_code = 'Unknown'
|
||||
|
||||
try:
|
||||
# make request and get response
|
||||
self.response = response = self.rate_limited_get(
|
||||
self.url,
|
||||
params=self.params,
|
||||
headers=self.headers,
|
||||
timeout=self.timeout,
|
||||
proxies=self.proxies
|
||||
)
|
||||
|
||||
# check that response is ok
|
||||
self.status_code = response.status_code
|
||||
response.raise_for_status()
|
||||
|
||||
# rely on json method to get non-empty well formatted JSON
|
||||
json_response = response.json()
|
||||
self.url = response.url
|
||||
LOGGER.info("Requested %s", self.url)
|
||||
|
||||
except requests.exceptions.RequestException as err:
|
||||
# store real status code and error
|
||||
self.error = u'ERROR - {}'.format(str(err))
|
||||
LOGGER.error("Status code %s from %s: %s",
|
||||
self.status_code, self.url, self.error)
|
||||
|
||||
# return False
|
||||
return False
|
||||
|
||||
# return response within its JSON format
|
||||
return json_response
|
||||
|
||||
def rate_limited_get(self, url, **kwargs):
|
||||
""" By default, simply wraps a session.get request"""
|
||||
return self.session.get(url, **kwargs)
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
""" Allow children classes to format json_response into an array of objects
|
||||
OVERRIDE TO FETCH the correct array of objects when necessary
|
||||
"""
|
||||
return json_response
|
||||
|
||||
def _parse_results(self, json_response):
|
||||
""" Creates instances of self.one_result (validated cls._RESULT_CLASS)
|
||||
from JSON results retrieved by self._connect
|
||||
|
||||
params: array of objects (dictionnaries)
|
||||
"""
|
||||
for json_dict in self._adapt_results(json_response):
|
||||
self.add(self.one_result(json_dict))
|
||||
|
||||
# set default result to use for delegation
|
||||
self.current_result = len(self) > 0 and self[0]
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
""" Checks the JSON returned from the provider and flag errors if necessary"""
|
||||
return self.error
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return len(self) > 0
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
if self.ok:
|
||||
return 'OK'
|
||||
elif self.error:
|
||||
return self.error
|
||||
elif len(self) == 0:
|
||||
return 'ERROR - No results found'
|
||||
else:
|
||||
return 'ERROR - Unhandled Exception'
|
||||
|
||||
@property
|
||||
def geojson(self):
|
||||
geojson_results = [result.geojson for result in self]
|
||||
features = {
|
||||
'type': 'FeatureCollection',
|
||||
'features': geojson_results
|
||||
}
|
||||
return features
|
||||
|
||||
def debug(self, verbose=True):
|
||||
with StringIO() as output:
|
||||
print(u'===\n', file=output)
|
||||
print(str(repr(self)), file=output)
|
||||
print(u'===\n', file=output)
|
||||
print(u'\n', file=output)
|
||||
print(u'#res: {}\n'.format(len(self)), file=output)
|
||||
print(u'code: {}\n'.format(self.status_code), file=output)
|
||||
print(u'url: {}\n'.format(self.url), file=output)
|
||||
|
||||
stats = []
|
||||
|
||||
if self.ok:
|
||||
for index, result in enumerate(self):
|
||||
print(u'\n', file=output)
|
||||
print(u'Details for result #{}\n'.format(index + 1), file=output)
|
||||
print(u'---\n', file=output)
|
||||
stats.append(result.debug())
|
||||
else:
|
||||
print(self.status, file=output)
|
||||
|
||||
if verbose:
|
||||
print(output.getvalue())
|
||||
|
||||
return stats
|
||||
|
||||
# Delegation to current result
|
||||
def set_default_result(self, index):
|
||||
""" change the result used to delegate the calls to. The provided index should be in the
|
||||
range of results, otherwise it will raise an exception
|
||||
"""
|
||||
self.current_result = self[index]
|
||||
|
||||
def __getattr__(self, name):
|
||||
""" Called when an attribute lookup has not found the attribute in the usual places (i.e.
|
||||
it is not an instance attribute nor is it found in the class tree for self). name is
|
||||
the attribute name. This method should return the (computed) attribute value or raise
|
||||
an AttributeError exception.
|
||||
|
||||
Note that if the attribute is found through the normal mechanism, __getattr__() is not called.
|
||||
"""
|
||||
if not self.ok:
|
||||
return None
|
||||
|
||||
if self.current_result is None:
|
||||
raise AttributeError("%s not found on %s, and current_result is None".format(
|
||||
name, self.__class__.__name__
|
||||
))
|
||||
return getattr(self.current_result, name)
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,180 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import bing_key
|
||||
import re
|
||||
|
||||
|
||||
class BingResult(OneResult):
|
||||
|
||||
def __init__(self, json_content):
|
||||
# create safe shortcuts
|
||||
self._point = json_content.get('point', {})
|
||||
self._address = json_content.get('address', {})
|
||||
|
||||
# proceed with super.__init__
|
||||
super(BingResult, self).__init__(json_content)
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
coord = self._point['coordinates']
|
||||
if coord:
|
||||
return coord[0]
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
coord = self._point['coordinates']
|
||||
if coord:
|
||||
return coord[1]
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self._address.get('formattedAddress')
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
if self.street:
|
||||
expression = r'\d+'
|
||||
pattern = re.compile(expression)
|
||||
match = pattern.search(self.street, re.UNICODE)
|
||||
if match:
|
||||
return match.group(0)
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self._address.get('addressLine')
|
||||
|
||||
@property
|
||||
def neighborhood(self):
|
||||
return self._address.get('neighborhood')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self._address.get('locality')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self._address.get('adminDistrict')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self._address.get('countryRegion')
|
||||
|
||||
@property
|
||||
def quality(self):
|
||||
return self.raw.get('entityType')
|
||||
|
||||
@property
|
||||
def accuracy(self):
|
||||
return self.raw.get('calculationMethod')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self._address.get('postalCode')
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
_bbox = self.raw.get('bbox')
|
||||
if _bbox:
|
||||
south = _bbox[0]
|
||||
north = _bbox[2]
|
||||
west = _bbox[1]
|
||||
east = _bbox[3]
|
||||
return self._get_bbox(south, west, north, east)
|
||||
|
||||
|
||||
class BingQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Bing Maps REST Services
|
||||
=======================
|
||||
The Bing™ Maps REST Services Application Programming Interface (API)
|
||||
provides a Representational State Transfer (REST) interface to
|
||||
perform tasks such as creating a static map with pushpins, geocoding
|
||||
an address, retrieving imagery metadata, or creating a route.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://msdn.microsoft.com/en-us/library/ff701714.aspx
|
||||
|
||||
Get Bing key
|
||||
------------
|
||||
https://www.bingmapsportal.com/
|
||||
"""
|
||||
provider = 'bing'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'http://dev.virtualearth.net/REST/v1/Locations'
|
||||
_RESULT_CLASS = BingResult
|
||||
_KEY = bing_key
|
||||
|
||||
def _build_headers(self, provider_key, **kwargs):
|
||||
return {
|
||||
'Referer': "http://addxy.com/",
|
||||
'User-agent': 'Mozilla/5.0'
|
||||
}
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'q': location,
|
||||
'o': 'json',
|
||||
'inclnb': 1,
|
||||
'key': provider_key,
|
||||
'maxResults': kwargs.get('maxRows', 1)
|
||||
}
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
status = json_response['statusDescription']
|
||||
if not status == 'OK':
|
||||
self.error = status
|
||||
|
||||
return self.error
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
# extract the array of JSON objects
|
||||
sets = json_response['resourceSets']
|
||||
if sets:
|
||||
return sets[0]['resources']
|
||||
return []
|
||||
|
||||
|
||||
class BingQueryDetail(MultipleResultsQuery):
|
||||
provider = 'bing'
|
||||
method = 'details'
|
||||
|
||||
_URL = 'http://dev.virtualearth.net/REST/v1/Locations'
|
||||
_RESULT_CLASS = BingResult
|
||||
_KEY = bing_key
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'adminDistrict': kwargs.get('adminDistrict'),
|
||||
'countryRegion': kwargs.get('countryRegion'),
|
||||
'locality': kwargs.get('locality'),
|
||||
'postalCode': kwargs.get('countryRegion'),
|
||||
'addressLine': kwargs.get('addressLine', location),
|
||||
'o': 'json',
|
||||
'inclnb': 1,
|
||||
'key': provider_key,
|
||||
'maxResults': kwargs.get('maxRows', 1)
|
||||
}
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
status = json_response['statusDescription']
|
||||
if not status == 'OK':
|
||||
self.error = status
|
||||
|
||||
return self.error
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
# extract the array of JSON objects
|
||||
sets = json_response['resourceSets']
|
||||
if sets:
|
||||
return sets[0]['resources']
|
||||
return []
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = BingQuery('453 Booth Street, Ottawa Ontario')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,179 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import, print_function
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import bing_key
|
||||
|
||||
import time
|
||||
import io
|
||||
import requests
|
||||
import logging
|
||||
import sys
|
||||
|
||||
PY2 = sys.version_info < (3, 0)
|
||||
csv_io = io.BytesIO if PY2 else io.StringIO
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BingBatchResult(OneResult):
|
||||
|
||||
def __init__(self, content):
|
||||
self._content = content
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
coord = self._content
|
||||
if coord:
|
||||
return coord[0]
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
coord = self._content
|
||||
if coord:
|
||||
return coord[1]
|
||||
|
||||
def debug(self, verbose=True):
|
||||
with csv_io() as output:
|
||||
print('\n', file=output)
|
||||
print('{} result\n'.format(self.__class__.__name__), file=output)
|
||||
print('-----------\n', file=output)
|
||||
print(self._content, file=output)
|
||||
|
||||
if verbose:
|
||||
print(output.getvalue())
|
||||
|
||||
return [None, None]
|
||||
|
||||
|
||||
class BingBatch(MultipleResultsQuery):
|
||||
"""
|
||||
Bing Maps REST Services
|
||||
=======================
|
||||
The Bing™ Maps REST Services Application Programming Interface (API)
|
||||
provides a Representational State Transfer (REST) interface to
|
||||
perform tasks such as creating a static map with pushpins, geocoding
|
||||
an address, retrieving imagery metadata, or creating a route.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://msdn.microsoft.com/en-us/library/ff701714.aspx
|
||||
|
||||
Dataflow Reference
|
||||
------------------
|
||||
https://msdn.microsoft.com/en-us/library/ff701733.aspx
|
||||
|
||||
"""
|
||||
provider = 'bing'
|
||||
|
||||
_URL = u'http://spatial.virtualearth.net/REST/v1/Dataflows/Geocode'
|
||||
_BATCH_TIMEOUT = 60
|
||||
_BATCH_WAIT = 5
|
||||
|
||||
_RESULT_CLASS = BingBatchResult
|
||||
_KEY = bing_key
|
||||
|
||||
def extract_resource_id(self, response):
|
||||
for rs in response['resourceSets']:
|
||||
for resource in rs['resources']:
|
||||
if 'id' in resource:
|
||||
return resource['id']
|
||||
|
||||
raise LookupError('No job ID returned from Bing batch call')
|
||||
|
||||
def is_job_done(self, job_id):
|
||||
url = u'http://spatial.virtualearth.net/REST/v1/Dataflows/Geocode/{}'.format(job_id)
|
||||
response = self.session.get(
|
||||
url,
|
||||
params={'key': self.provider_key},
|
||||
timeout=self.timeout,
|
||||
proxies=self.proxies
|
||||
)
|
||||
|
||||
for rs in response.json()['resourceSets']:
|
||||
for resource in rs['resources']:
|
||||
if resource['id'] == job_id:
|
||||
if resource['status'] == 'Aborted':
|
||||
raise LookupError('Bing job aborted')
|
||||
return resource['status'] == 'Completed'
|
||||
|
||||
raise LookupError('Job ID not found in Bing answer - something is wrong')
|
||||
|
||||
def get_job_result(self, job_id):
|
||||
url = u'http://spatial.virtualearth.net/REST/v1/Dataflows/Geocode/{}/output/succeeded'.format(job_id)
|
||||
response = self.session.get(
|
||||
url,
|
||||
params={'key': self.provider_key},
|
||||
timeout=self.timeout,
|
||||
proxies=self.proxies
|
||||
)
|
||||
|
||||
return response.content
|
||||
|
||||
def _build_params(self, locations, provider_key, **kwargs):
|
||||
self.batch = self.generate_batch(locations)
|
||||
self.locations_length = len(locations)
|
||||
self.provider_key = provider_key
|
||||
self._BATCH_TIMEOUT = kwargs.get('timeout', 60)
|
||||
|
||||
return {
|
||||
'input': 'csv',
|
||||
'key': provider_key
|
||||
}
|
||||
|
||||
def _build_headers(self, provider_key, **kwargs):
|
||||
return {'Content-Type': 'text/plain'}
|
||||
|
||||
def _connect(self):
|
||||
self.status_code = 'Unknown'
|
||||
|
||||
try:
|
||||
self.response = response = self.session.post(
|
||||
self.url,
|
||||
data=self.batch,
|
||||
params=self.params,
|
||||
headers=self.headers,
|
||||
timeout=self.timeout,
|
||||
proxies=self.proxies
|
||||
)
|
||||
|
||||
# check that response is ok
|
||||
self.status_code = response.status_code
|
||||
response.raise_for_status()
|
||||
|
||||
# rely on json method to get non-empty well formatted JSON
|
||||
json_response = response.json()
|
||||
self.url = response.url
|
||||
LOGGER.info("Requested %s", self.url)
|
||||
|
||||
# get the resource/job id
|
||||
resource_id = self.extract_resource_id(json_response)
|
||||
elapsed = 0
|
||||
|
||||
# try for _BATCH_TIMEOUT seconds to retrieve the results of that job
|
||||
while (elapsed < self._BATCH_TIMEOUT):
|
||||
if self.is_job_done(resource_id):
|
||||
return self.get_job_result(resource_id)
|
||||
|
||||
elapsed = elapsed + self._BATCH_WAIT
|
||||
time.sleep(self._BATCH_WAIT)
|
||||
|
||||
LOGGER.error("Job was not finished in time.")
|
||||
|
||||
except (requests.exceptions.RequestException, LookupError) as err:
|
||||
# store real status code and error
|
||||
self.error = u'ERROR - {}'.format(str(err))
|
||||
LOGGER.error("Status code %s from %s: %s",
|
||||
self.status_code, self.url, self.error)
|
||||
|
||||
return False
|
||||
|
||||
def _parse_results(self, response):
|
||||
rows = self._adapt_results(response)
|
||||
|
||||
# re looping through the results to give them back in their original order
|
||||
for idx in range(0, self.locations_length):
|
||||
self.add(self.one_result(rows.get(str(idx), None)))
|
||||
|
||||
self.current_result = len(self) > 0 and self[0]
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,81 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import, print_function
|
||||
from geocoder.bing_batch import BingBatch, BingBatchResult
|
||||
|
||||
import io
|
||||
import csv
|
||||
import sys
|
||||
|
||||
PY2 = sys.version_info < (3, 0)
|
||||
csv_io = io.BytesIO if PY2 else io.StringIO
|
||||
csv_encode = (lambda input: input) if PY2 else (lambda input: input.encode('utf-8'))
|
||||
csv_decode = (lambda input: input) if PY2 else (lambda input: input.decode('utf-8'))
|
||||
|
||||
|
||||
class BingBatchForwardResult(BingBatchResult):
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
coord = self._content
|
||||
if coord:
|
||||
return float(coord[0])
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
coord = self._content
|
||||
if coord:
|
||||
return float(coord[1])
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self._content)
|
||||
|
||||
def debug(self, verbose=True):
|
||||
with csv_io() as output:
|
||||
print('\n', file=output)
|
||||
print('Bing Batch result\n', file=output)
|
||||
print('-----------\n', file=output)
|
||||
print(self._content, file=output)
|
||||
|
||||
if verbose:
|
||||
print(output.getvalue())
|
||||
|
||||
return [None, None]
|
||||
|
||||
|
||||
class BingBatchForward(BingBatch):
|
||||
method = 'batch'
|
||||
_RESULT_CLASS = BingBatchForwardResult
|
||||
|
||||
def generate_batch(self, addresses):
|
||||
out = csv_io()
|
||||
writer = csv.writer(out)
|
||||
writer.writerow([
|
||||
'Id',
|
||||
'GeocodeRequest/Query',
|
||||
'GeocodeResponse/Point/Latitude',
|
||||
'GeocodeResponse/Point/Longitude'
|
||||
])
|
||||
|
||||
for idx, address in enumerate(addresses):
|
||||
writer.writerow([idx, address, None, None])
|
||||
|
||||
return csv_encode("Bing Spatial Data Services, 2.0\n{}".format(out.getvalue()))
|
||||
|
||||
def _adapt_results(self, response):
|
||||
result = csv_io(csv_decode(response))
|
||||
# Skipping first line with Bing header
|
||||
next(result)
|
||||
|
||||
rows = {}
|
||||
for row in csv.DictReader(result):
|
||||
rows[row['Id']] = [row['GeocodeResponse/Point/Latitude'], row['GeocodeResponse/Point/Longitude']]
|
||||
|
||||
return rows
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = BingBatchForward(['Denver,CO', 'Boulder,CO'], key=None)
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,111 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import, print_function
|
||||
from geocoder.bing_batch import BingBatch, BingBatchResult
|
||||
|
||||
import io
|
||||
import csv
|
||||
import sys
|
||||
|
||||
PY2 = sys.version_info < (3, 0)
|
||||
csv_io = io.BytesIO if PY2 else io.StringIO
|
||||
csv_encode = (lambda input: input) if PY2 else (lambda input: input.encode('utf-8'))
|
||||
csv_decode = (lambda input: input) if PY2 else (lambda input: input.decode('utf-8'))
|
||||
|
||||
|
||||
class BingBatchReverseResult(BingBatchResult):
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
address = self._content
|
||||
if address:
|
||||
return address[0]
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
city = self._content
|
||||
if city:
|
||||
return city[1]
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
postal = self._content
|
||||
if postal:
|
||||
return postal[2]
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
state = self._content
|
||||
if state:
|
||||
return state[3]
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
country = self._content
|
||||
if country:
|
||||
return country[4]
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self._content)
|
||||
|
||||
def debug(self, verbose=True):
|
||||
with csv_io() as output:
|
||||
print('\n', file=output)
|
||||
print('Bing Batch result\n', file=output)
|
||||
print('-----------\n', file=output)
|
||||
print(self._content, file=output)
|
||||
|
||||
if verbose:
|
||||
print(output.getvalue())
|
||||
|
||||
return [None, None]
|
||||
|
||||
|
||||
class BingBatchReverse(BingBatch):
|
||||
|
||||
method = 'batch_reverse'
|
||||
_RESULT_CLASS = BingBatchReverseResult
|
||||
|
||||
def generate_batch(self, locations):
|
||||
out = csv_io()
|
||||
writer = csv.writer(out)
|
||||
writer.writerow([
|
||||
'Id',
|
||||
'ReverseGeocodeRequest/Location/Latitude',
|
||||
'ReverseGeocodeRequest/Location/Longitude',
|
||||
'GeocodeResponse/Address/FormattedAddress',
|
||||
'GeocodeResponse/Address/Locality',
|
||||
'GeocodeResponse/Address/PostalCode',
|
||||
'GeocodeResponse/Address/AdminDistrict',
|
||||
'GeocodeResponse/Address/CountryRegion'
|
||||
])
|
||||
|
||||
for idx, location in enumerate(locations):
|
||||
writer.writerow([idx, location[0], location[1], None, None, None, None, None])
|
||||
|
||||
return csv_encode("Bing Spatial Data Services, 2.0\n{}".format(out.getvalue()))
|
||||
|
||||
def _adapt_results(self, response):
|
||||
# print(type(response))
|
||||
result = csv_io(csv_decode(response))
|
||||
# Skipping first line with Bing header
|
||||
next(result)
|
||||
|
||||
rows = {}
|
||||
for row in csv.DictReader(result):
|
||||
rows[row['Id']] = [
|
||||
row['GeocodeResponse/Address/FormattedAddress'],
|
||||
row['GeocodeResponse/Address/Locality'],
|
||||
row['GeocodeResponse/Address/PostalCode'],
|
||||
row['GeocodeResponse/Address/AdminDistrict'],
|
||||
row['GeocodeResponse/Address/CountryRegion']
|
||||
]
|
||||
|
||||
return rows
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = BingBatchReverse([(40.7943, -73.970859), (48.845580, 2.321807)], key=None)
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from geocoder.bing import BingResult, BingQuery
|
||||
from geocoder.location import Location
|
||||
|
||||
|
||||
class BingReverseResult(BingResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.address)
|
||||
|
||||
|
||||
class BingReverse(BingQuery):
|
||||
"""
|
||||
Bing Maps REST Services
|
||||
=======================
|
||||
The Bing™ Maps REST Services Application Programming Interface (API)
|
||||
provides a Representational State Transfer (REST) interface to
|
||||
perform tasks such as creating a static map with pushpins, geocoding
|
||||
an address, retrieving imagery metadata, or creating a route.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://msdn.microsoft.com/en-us/library/ff701714.aspx
|
||||
|
||||
"""
|
||||
provider = 'bing'
|
||||
method = 'reverse'
|
||||
|
||||
_URL = u'http://dev.virtualearth.net/REST/v1/Locations/{0}'
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'o': 'json',
|
||||
'key': provider_key,
|
||||
'maxResults': 1,
|
||||
}
|
||||
|
||||
def _before_initialize(self, location, **kwargs):
|
||||
self.url = self.url.format(str(Location(location)))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = BingReverse([45.4049053, -75.7077965], key=None)
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,170 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import canadapost_key_getter
|
||||
|
||||
|
||||
class CanadapostIdResult(OneResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.item_id)
|
||||
|
||||
@property
|
||||
def item_id(self):
|
||||
return self.raw.get('Id')
|
||||
|
||||
@property
|
||||
def next_action(self):
|
||||
return self.raw.get('Next')
|
||||
|
||||
|
||||
class CanadapostIdQuery(MultipleResultsQuery):
|
||||
|
||||
provider = 'canadapost'
|
||||
method = 'id'
|
||||
|
||||
_URL = 'https://ws1.postescanada-canadapost.ca/AddressComplete/Interactive/Find/v2.10/json3ex.ws'
|
||||
_RESULT_CLASS = CanadapostIdResult
|
||||
_KEY_MANDATORY = False
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
if not provider_key:
|
||||
provider_key = canadapost_key_getter(**kwargs)
|
||||
|
||||
return {
|
||||
'Key': provider_key,
|
||||
'LastId': kwargs.get('last_id', ''),
|
||||
'Country': kwargs.get('country', 'ca'),
|
||||
'SearchFor': 'Everything',
|
||||
'SearchTerm': location,
|
||||
'LanguagePreference': kwargs.get('language', 'en'),
|
||||
'$cache': 'true'
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return json_response['Items']
|
||||
|
||||
|
||||
class CanadapostResult(OneResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.postal)
|
||||
|
||||
@property
|
||||
def quality(self):
|
||||
return self.raw.get('Type')
|
||||
|
||||
@property
|
||||
def accuracy(self):
|
||||
return self.raw.get('DataLevel')
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw.get('Line1')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self.raw.get('PostalCode')
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self.raw.get('BuildingNumber')
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self.raw.get('Street')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.raw.get('City')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw.get('ProvinceName')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw.get('CountryName')
|
||||
|
||||
@property
|
||||
def unit(self):
|
||||
return self.raw.get('SubBuilding')
|
||||
|
||||
@property
|
||||
def domesticId(self):
|
||||
return self.raw.get('DomesticId')
|
||||
|
||||
@property
|
||||
def label(self):
|
||||
return self.raw.get('Label')
|
||||
|
||||
|
||||
class CanadapostQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Addres Complete API
|
||||
=======================
|
||||
The next generation of address finders, AddressComplete uses
|
||||
intelligent, fast searching to improve data accuracy and relevancy.
|
||||
Simply start typing a business name, address or Postal Code
|
||||
and AddressComplete will suggest results as you go.
|
||||
|
||||
Params
|
||||
------
|
||||
:param ``location``: Your search location you want geocoded.
|
||||
:param ``key``: (optional) API Key from CanadaPost Address Complete.
|
||||
:param ``language``: (default=en) Output language preference.
|
||||
:param ``country``: (default=ca) Geofenced query by country.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://www.canadapost.ca/pca/
|
||||
"""
|
||||
provider = 'canadapost'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'https://ws1.postescanada-canadapost.ca/AddressComplete/Interactive/RetrieveFormatted/v2.10/json3ex.ws'
|
||||
_RESULT_CLASS = CanadapostResult
|
||||
_KEY_MANDATORY = False
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
if not provider_key:
|
||||
provider_key = canadapost_key_getter(**kwargs)
|
||||
|
||||
self.key = provider_key
|
||||
|
||||
last_id = ''
|
||||
next_action = 'Find'
|
||||
while next_action == 'Find':
|
||||
ids = CanadapostIdQuery(location, key=provider_key, last_id=last_id, **kwargs)
|
||||
next_action = ids.next_action
|
||||
last_id = ids.item_id
|
||||
|
||||
if not ids.item_id:
|
||||
raise ValueError("Could not get any Id for given location")
|
||||
|
||||
return {
|
||||
'Key': provider_key,
|
||||
'Id': ids.item_id,
|
||||
'Source': '',
|
||||
'MaxResults': kwargs.get('maxRows', 1),
|
||||
'cache': 'true'
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return json_response['Items']
|
||||
|
||||
@property
|
||||
def canadapost_api_key(self):
|
||||
return self.key
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = CanadapostQuery("453 Booth Street, ON")
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import click
|
||||
import json
|
||||
import geocoder
|
||||
import os
|
||||
import fileinput
|
||||
|
||||
from geocoder.api import options
|
||||
|
||||
|
||||
providers = sorted(options.keys())
|
||||
methods = ['geocode', 'reverse', 'elevation', 'timezone', 'places']
|
||||
outputs = ['json', 'osm', 'geojson', 'wkt']
|
||||
units = ['kilometers', 'miles', 'feet', 'meters']
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument('location', nargs=-1)
|
||||
@click.option('--provider', '-p', default='osm', type=click.Choice(providers))
|
||||
@click.option('--method', '-m', default='geocode', type=click.Choice(methods))
|
||||
@click.option('--output', '-o', default='json', type=click.Choice(outputs))
|
||||
@click.option('--units', '-u', default='kilometers', type=click.Choice(units))
|
||||
@click.option('--timeout', '-t', default=5.0)
|
||||
@click.option('--distance', is_flag=True)
|
||||
@click.option('--language', default='')
|
||||
@click.option('--url', default='')
|
||||
@click.option('--proxies')
|
||||
@click.option('--key')
|
||||
# following are for Tamu provider
|
||||
@click.option('--city', '-c', default='')
|
||||
@click.option('--state', '-s', default='')
|
||||
@click.option('--zipcode', '-z', default='')
|
||||
def cli(location, **kwargs):
|
||||
"""Geocode an arbitrary number of strings from Command Line."""
|
||||
|
||||
locations = []
|
||||
|
||||
# Read Standard Input
|
||||
# $ cat foo.txt | geocode
|
||||
try:
|
||||
for line in fileinput.input():
|
||||
locations.append(line.strip())
|
||||
except:
|
||||
pass
|
||||
|
||||
# Read multiple files & user input location
|
||||
for item in location:
|
||||
if os.path.exists(item):
|
||||
with open(item, 'rb') as f:
|
||||
locations += f.read().splitlines()
|
||||
else:
|
||||
locations.append(item)
|
||||
|
||||
# Distance calculation
|
||||
if kwargs['distance']:
|
||||
d = geocoder.distance(locations, **kwargs)
|
||||
click.echo(d)
|
||||
return
|
||||
|
||||
# Geocode results from user input
|
||||
for location in locations:
|
||||
g = geocoder.get(location.strip(), **kwargs)
|
||||
try:
|
||||
click.echo(json.dumps(getattr(g, kwargs['output'])))
|
||||
except IOError:
|
||||
# When invalid command is entered a broken pipe error occurs
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
cli()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from math import radians, cos, sin, asin, sqrt
|
||||
from geocoder.location import Location
|
||||
|
||||
AVG_EARTH_RADIUS = 6371 # in km
|
||||
|
||||
|
||||
def Distance(*args, **kwargs):
|
||||
total = 0.0
|
||||
last = None
|
||||
|
||||
if len(args) == 1 and isinstance(args, (list, tuple)):
|
||||
args = args[0]
|
||||
|
||||
if len(args) <= 1:
|
||||
raise ValueError("Distance needs at least two locations")
|
||||
|
||||
for location in args:
|
||||
if last:
|
||||
distance = haversine(Location(last), Location(location), **kwargs)
|
||||
if distance:
|
||||
total += distance
|
||||
last = location
|
||||
|
||||
return total
|
||||
|
||||
|
||||
def haversine(point1, point2, **kwargs):
|
||||
""" Calculate the great-circle distance bewteen two points on the Earth surface.
|
||||
|
||||
:input: two 2-tuples, containing the latitude and longitude of each point
|
||||
in decimal degrees.
|
||||
|
||||
Example: haversine((45.7597, 4.8422), (48.8567, 2.3508))
|
||||
|
||||
:output: Returns the distance bewteen the two points.
|
||||
The default unit is kilometers. Miles can be returned
|
||||
if the ``miles`` parameter is set to True.
|
||||
|
||||
"""
|
||||
|
||||
lookup_units = {
|
||||
'miles': 'miles',
|
||||
'mile': 'miles',
|
||||
'mi': 'miles',
|
||||
'ml': 'miles',
|
||||
'kilometers': 'kilometers',
|
||||
'kilometres': 'kilometers',
|
||||
'kilometer': 'kilometers',
|
||||
'kilometre': 'kilometers',
|
||||
'km': 'kilometers',
|
||||
'meters': 'meters',
|
||||
'metres': 'meters',
|
||||
'meter': 'meters',
|
||||
'metre': 'meters',
|
||||
'm': 'meters',
|
||||
'feet': 'feet',
|
||||
'f': 'feet',
|
||||
'ft': 'feet',
|
||||
}
|
||||
|
||||
if point1.ok and point2.ok:
|
||||
# convert all latitudes/longitudes from decimal degrees to radians
|
||||
lat1, lng1, lat2, lng2 = list(map(radians, point1.latlng + point2.latlng))
|
||||
|
||||
# calculate haversine
|
||||
lat = lat2 - lat1
|
||||
lng = lng2 - lng1
|
||||
d = sin(lat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(lng / 2) ** 2
|
||||
h = 2 * AVG_EARTH_RADIUS * asin(sqrt(d))
|
||||
|
||||
# Measurements
|
||||
units = kwargs.get('units', 'kilometers').lower()
|
||||
units_calculation = {
|
||||
'miles': h * 0.621371,
|
||||
'feet': h * 0.621371 * 5280,
|
||||
'meters': h * 1000,
|
||||
'kilometers': h,
|
||||
}
|
||||
|
||||
if units in lookup_units:
|
||||
return units_calculation[lookup_units[units]]
|
||||
else:
|
||||
raise ValueError("Unknown units of measurement")
|
||||
|
||||
else:
|
||||
print(u'[WARNING] Error calculating the following two locations.\n'
|
||||
'Points: {0} to {1}'.format(point1.location, point2.location))
|
||||
|
||||
if __name__ == '__main__':
|
||||
d = Distance('Ottawa, ON', 'Toronto, ON', 'Montreal, QC')
|
||||
print(d)
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,133 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import requests
|
||||
import ratelim
|
||||
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
|
||||
|
||||
class FreeGeoIPResult(OneResult):
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self.raw.get('latitude')
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self.raw.get('longitude')
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
if self.city:
|
||||
return u'{0}, {1} {2}'.format(self.city, self.state, self.country)
|
||||
elif self.state:
|
||||
return u'{0}, {1}'.format(self.state, self.country)
|
||||
elif self.country:
|
||||
return u'{0}'.format(self.country)
|
||||
return u''
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
zip_code = self.raw.get('zip_code')
|
||||
postal_code = self.raw.get('postal_code')
|
||||
if zip_code:
|
||||
return zip_code
|
||||
if postal_code:
|
||||
return postal_code
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.raw.get('city')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw.get('region')
|
||||
|
||||
@property
|
||||
def region_code(self):
|
||||
return self.raw.get('region_code')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw.get('country_name')
|
||||
|
||||
@property
|
||||
def country_code3(self):
|
||||
return self.raw.get('country_code3')
|
||||
|
||||
@property
|
||||
def continent(self):
|
||||
return self.raw.get('continent')
|
||||
|
||||
@property
|
||||
def timezone(self):
|
||||
return self.raw.get('timezone')
|
||||
|
||||
@property
|
||||
def area_code(self):
|
||||
return self.raw.get('area_code')
|
||||
|
||||
@property
|
||||
def dma_code(self):
|
||||
return self.raw.get('dma_code')
|
||||
|
||||
@property
|
||||
def offset(self):
|
||||
return self.raw.get('offset')
|
||||
|
||||
@property
|
||||
def organization(self):
|
||||
return self.raw.get('organization')
|
||||
|
||||
@property
|
||||
def ip(self):
|
||||
return self.raw.get('ip')
|
||||
|
||||
@property
|
||||
def time_zone(self):
|
||||
return self.raw.get('time_zone')
|
||||
|
||||
|
||||
class FreeGeoIPQuery(MultipleResultsQuery):
|
||||
"""
|
||||
FreeGeoIP.net
|
||||
=============
|
||||
freegeoip.net provides a public HTTP API for software developers to
|
||||
search the geolocation of IP addresses. It uses a database of IP addresses
|
||||
that are associated to cities along with other relevant information like
|
||||
time zone, latitude and longitude.
|
||||
|
||||
You're allowed up to 10,000 queries per hour by default. Once this
|
||||
limit is reached, all of your requests will result in HTTP 403,
|
||||
forbidden, until your quota is cleared.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://freegeoip.net/
|
||||
"""
|
||||
provider = 'freegeoip'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'https://freegeoip.net/json/'
|
||||
_RESULT_CLASS = FreeGeoIPResult
|
||||
_KEY_MANDATORY = False
|
||||
|
||||
def _before_initialize(self, location, **kwargs):
|
||||
self.url += location
|
||||
|
||||
@staticmethod
|
||||
@ratelim.greedy(10000, 60 * 60)
|
||||
def rate_limited_get(*args, **kwargs):
|
||||
return requests.get(*args, **kwargs)
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return [json_response]
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = FreeGeoIPQuery('99.240.181.199')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import gaode_key
|
||||
|
||||
|
||||
class GaodeResult(OneResult):
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return float(self.raw.get('location', '0,0').replace("'", '').split(',')[1])
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return float(self.raw.get('location', '0,0').replace("'", '').split(',')[0])
|
||||
|
||||
@property
|
||||
def quality(self):
|
||||
return self.raw.get('level')
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw.get('formatted_address')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return '中国'
|
||||
|
||||
@property
|
||||
def province(self):
|
||||
return self.raw.get('province')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw.get('province')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.raw.get('city')
|
||||
|
||||
@property
|
||||
def district(self):
|
||||
return self.raw.get('district')
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self.raw.get('street')
|
||||
|
||||
@property
|
||||
def adcode(self):
|
||||
return self.raw.get('adcode')
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self.raw.get('number')
|
||||
|
||||
|
||||
class GaodeQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Gaode AMap Geocoding API
|
||||
===================
|
||||
Gaode Maps Geocoding API is a free open the API, the default quota
|
||||
2000 times / day.
|
||||
|
||||
Params
|
||||
------
|
||||
:param location: Your search location you want geocoded.
|
||||
:param key: Gaode API key.
|
||||
|
||||
References
|
||||
----------
|
||||
API Documentation: http://lbs.amap.com/api/webservice/guide/api/georegeo
|
||||
Get AMap Key: http://lbs.amap.com/dev/
|
||||
"""
|
||||
provider = 'gaode'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'http://restapi.amap.com/v3/geocode/geo'
|
||||
_RESULT_CLASS = GaodeResult
|
||||
_KEY = gaode_key
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'address': location,
|
||||
'output': 'JSON',
|
||||
'key': provider_key,
|
||||
}
|
||||
|
||||
def _build_headers(self, provider_key, **kwargs):
|
||||
return {'Referer': kwargs.get('referer', '')}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return json_response['geocodes']
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = GaodeQuery('将台路')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.location import Location
|
||||
from geocoder.base import OneResult
|
||||
from geocoder.gaode import GaodeQuery
|
||||
|
||||
|
||||
class GaodeReverseResult(OneResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.address)
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw['formatted_address']
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw['addressComponent']['country']
|
||||
|
||||
@property
|
||||
def province(self):
|
||||
return self.raw['addressComponent']['province']
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw['addressComponent']['province']
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
if len(self.raw['addressComponent']['city']) == 0:
|
||||
return self.raw['addressComponent']['province']
|
||||
else:
|
||||
return self.raw['addressComponent']['city']
|
||||
|
||||
@property
|
||||
def district(self):
|
||||
return self.raw['addressComponent']['district']
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self.raw['addressComponent']['streetNumber']['street']
|
||||
|
||||
@property
|
||||
def adcode(self):
|
||||
return self.raw['addressComponent']['adcode']
|
||||
|
||||
@property
|
||||
def township(self):
|
||||
return self.raw['addressComponent']['township']
|
||||
|
||||
@property
|
||||
def towncode(self):
|
||||
return self.raw['addressComponent']['towncode']
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self.raw['addressComponent']['streetNumber']['number']
|
||||
|
||||
|
||||
class GaodeReverse(GaodeQuery):
|
||||
"""
|
||||
Gaode GeoReverse API
|
||||
===================
|
||||
Gaode Maps GeoReverse API is a free open the API, the default quota
|
||||
2000 times / day.
|
||||
|
||||
Params
|
||||
------
|
||||
:param location: Your search location you want geocoded.
|
||||
:param key: Gaode API key.
|
||||
:param referer: Gaode API referer website.
|
||||
|
||||
References
|
||||
----------
|
||||
API Documentation: http://lbs.amap.com/api/webservice/guide/api/georegeo
|
||||
Get Gaode AMap Key: http://lbs.amap.com/dev/
|
||||
"""
|
||||
provider = 'gaode'
|
||||
method = 'reverse'
|
||||
|
||||
_URL = 'http://restapi.amap.com/v3/geocode/regeo'
|
||||
_RESULT_CLASS = GaodeReverseResult
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
location = Location(location)
|
||||
return {
|
||||
'location': str(location.lng) + ',' + str(location.lat),
|
||||
'output': 'json',
|
||||
'key': provider_key,
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return [json_response['regeocode']]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = GaodeReverse("39.971577, 116.506142")
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,202 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import geocodefarm_key
|
||||
|
||||
|
||||
class GeocodeFarmResult(OneResult):
|
||||
|
||||
def __init__(self, json_content):
|
||||
# create safe shortcuts
|
||||
self._coordinates = json_content.get('COORDINATES', {})
|
||||
self._boundaries = json_content.get('BOUNDARIES', {})
|
||||
self._address = json_content.get('ADDRESS', {})
|
||||
self._location_details = json_content.get('LOCATION_DETAILS', {})
|
||||
|
||||
# proceed with super.__init__
|
||||
super(GeocodeFarmResult, self).__init__(json_content)
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
lat = self._coordinates.get('latitude')
|
||||
if lat:
|
||||
return float(lat)
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
lng = self._coordinates.get('longitude')
|
||||
if lng:
|
||||
return float(lng)
|
||||
|
||||
@property
|
||||
def accuracy(self):
|
||||
return self.raw.get('accuracy')
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
south = self._boundaries.get('southwest_latitude')
|
||||
west = self._boundaries.get('southwest_longitude')
|
||||
north = self._boundaries.get('northeast_latitude')
|
||||
east = self._boundaries.get('northeast_longitude')
|
||||
return self._get_bbox(south, west, north, east)
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw.get('formatted_address')
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self._address.get('street_number')
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self._address.get('street_name')
|
||||
|
||||
@property
|
||||
def neighborhood(self):
|
||||
return self._address.get('neighborhood')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self._address.get('locality')
|
||||
|
||||
@property
|
||||
def county(self):
|
||||
return self._address.get('admin_2')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self._address.get('admin_1')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self._address.get('country')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self._address.get('postal_code')
|
||||
|
||||
@property
|
||||
def elevation(self):
|
||||
return self._location_details.get('elevation')
|
||||
|
||||
@property
|
||||
def timezone_long(self):
|
||||
return self._location_details.get('timezone_long')
|
||||
|
||||
@property
|
||||
def timezone_short(self):
|
||||
return self._location_details.get('timezone_short')
|
||||
|
||||
|
||||
class GeocodeFarmQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Geocode.Farm
|
||||
============
|
||||
Geocode.Farm is one of the few providers that provide this highly
|
||||
specialized service for free. We also have affordable paid plans, of
|
||||
course, but our free services are of the same quality and provide the same
|
||||
results. The major difference between our affordable paid plans and our
|
||||
free API service is the limitations. On one of our affordable paid plans
|
||||
your limit is set based on the plan you signed up for, starting at 25,000
|
||||
query requests per day (API calls). On our free API offering, you are
|
||||
limited to 250 query requests per day (API calls).
|
||||
|
||||
Params
|
||||
------
|
||||
:param location: The string to search for. Usually a street address.
|
||||
:param key: (optional) API Key. Only Required for Paid Users.
|
||||
:param lang: (optional) 2 digit lanuage code to return results in. Currently only "en"(English) or "de"(German) supported.
|
||||
:param country: (optional) The country to return results in. Used for biasing purposes and may not fully filter results to this specific country.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://geocode.farm/geocoding/free-api-documentation/
|
||||
"""
|
||||
provider = 'geocodefarm'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'https://www.geocode.farm/v3/json/forward/'
|
||||
_RESULT_CLASS = GeocodeFarmResult
|
||||
_KEY = geocodefarm_key
|
||||
_KEY_MANDATORY = False
|
||||
|
||||
def __init__(self, location, **kwargs):
|
||||
super(GeocodeFarmQuery, self).__init__(location, **kwargs)
|
||||
|
||||
self.api_status = {}
|
||||
self.api_account = {}
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'addr': location,
|
||||
'key': provider_key,
|
||||
'lang': kwargs.get('lang', ''),
|
||||
'country': kwargs.get('country', ''),
|
||||
'count': kwargs.get('maxRows', 1),
|
||||
}
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
status = json_response['geocoding_results']['STATUS'].get('status')
|
||||
if not status == 'SUCCESS':
|
||||
self.error = status
|
||||
|
||||
return self.error
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return json_response['geocoding_results']['RESULTS']
|
||||
|
||||
def _parse_results(self, json_response):
|
||||
super(GeocodeFarmQuery, self)._parse_results(json_response)
|
||||
|
||||
# store status and account details
|
||||
self.api_status = json_response['geocoding_results']['STATUS']
|
||||
self.api_account = json_response['geocoding_results']['ACCOUNT']
|
||||
|
||||
@property
|
||||
def access(self):
|
||||
return self.api_status.get('access')
|
||||
|
||||
@property
|
||||
def address_provided(self):
|
||||
return self.api_status.get('address_provided')
|
||||
|
||||
@property
|
||||
def ip_address(self):
|
||||
return self.api_account.get('ip_address')
|
||||
|
||||
@property
|
||||
def distribution_license(self):
|
||||
return self.api_account.get('distribution_license')
|
||||
|
||||
@property
|
||||
def usage_limit(self):
|
||||
usage_limit = self.api_account.get('usage_limit')
|
||||
if usage_limit:
|
||||
return int(usage_limit)
|
||||
|
||||
@property
|
||||
def used_today(self):
|
||||
used_today = self.api_account.get('used_today')
|
||||
if used_today:
|
||||
return int(used_today)
|
||||
|
||||
@property
|
||||
def used_total(self):
|
||||
used_total = self.api_account.get('used_total')
|
||||
if used_total:
|
||||
return int(used_total)
|
||||
|
||||
@property
|
||||
def first_used(self):
|
||||
return self.api_account.get('first_used')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = GeocodeFarmQuery("New York City")
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.location import Location
|
||||
from geocoder.geocodefarm import GeocodeFarmQuery
|
||||
|
||||
|
||||
class GeocodeFarmReverse(GeocodeFarmQuery):
|
||||
"""
|
||||
Geocode.Farm
|
||||
=======================
|
||||
Geocode.Farm is one of the few providers that provide this highly
|
||||
specialized service for free. We also have affordable paid plans, of
|
||||
course, but our free services are of the same quality and provide the same
|
||||
results. The major difference between our affordable paid plans and our
|
||||
free API service is the limitations. On one of our affordable paid plans
|
||||
your limit is set based on the plan you signed up for, starting at 25,000
|
||||
query requests per day (API calls). On our free API offering, you are
|
||||
limited to 250 query requests per day (API calls).
|
||||
|
||||
Params
|
||||
------
|
||||
:param lat: The numerical latitude value for which you wish to obtain the closest, human-readable address.
|
||||
:param lon: The numerical longitude value for which you wish to obtain the closest, human-readable address.
|
||||
:param key: (optional) API Key. Only Required for Paid Users.
|
||||
:param lang: (optional) 2 digit lanuage code to return results in. Currently only "en"(English) or "de"(German) supported.
|
||||
:param country: (optional) The country to return results in. Used for biasing purposes and may not fully filter results to this specific country.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://geocode.farm/geocoding/free-api-documentation/
|
||||
"""
|
||||
provider = 'geocodefarm'
|
||||
method = 'reverse'
|
||||
|
||||
_URL = 'https://www.geocode.farm/v3/json/reverse/'
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
location = Location(location)
|
||||
return {
|
||||
'lat': location.latitude,
|
||||
'lon': location.longitude,
|
||||
'key': provider_key,
|
||||
'lang': kwargs.get('lang', ''),
|
||||
'country': kwargs.get('country', ''),
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = GeocodeFarmReverse([45.3, -75.4])
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,98 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
|
||||
|
||||
class GeolyticaResult(OneResult):
|
||||
|
||||
def __init__(self, json_content):
|
||||
# create safe shortcuts
|
||||
self._standard = json_content.get('standard', {})
|
||||
|
||||
# proceed with super.__init__
|
||||
super(GeolyticaResult, self).__init__(json_content)
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
lat = self.raw.get('latt', '').strip()
|
||||
if lat:
|
||||
return float(lat)
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
lng = self.raw.get('longt', '').strip()
|
||||
if lng:
|
||||
return float(lng)
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self.raw.get('postal', '').strip()
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self._standard.get('stnumber', '').strip()
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self._standard.get('staddress', '').strip()
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self._standard.get('city', '').strip()
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self._standard.get('prov', '').strip()
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
if self.street_number:
|
||||
return u'{0} {1}, {2}'.format(self.street_number, self.route, self.locality)
|
||||
elif self.route and self.route != 'un-known':
|
||||
return u'{0}, {1}'.format(self.route, self.locality)
|
||||
else:
|
||||
return self.locality
|
||||
|
||||
|
||||
class GeolyticaQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Geocoder.ca
|
||||
===========
|
||||
A Canadian and US location geocoder.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://geocoder.ca/?api=1
|
||||
"""
|
||||
provider = 'geolytica'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'http://geocoder.ca'
|
||||
_RESULT_CLASS = GeolyticaResult
|
||||
_KEY_MANDATORY = False
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
params = {
|
||||
'json': 1,
|
||||
'locate': location,
|
||||
'geoit': 'xml'
|
||||
}
|
||||
if 'strictmode' in kwargs:
|
||||
params.update({'strictmode': kwargs.pop('strictmode')})
|
||||
if 'strict' in kwargs:
|
||||
params.update({'strict': kwargs.pop('strict')})
|
||||
if 'auth' in kwargs:
|
||||
params.update({'auth': kwargs.pop('auth')})
|
||||
return params
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return [json_response]
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = GeolyticaQuery('1552 Payette dr., Ottawa')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,151 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
from geocoder.base import MultipleResultsQuery, OneResult
|
||||
from geocoder.keys import geonames_username
|
||||
from geocoder.location import BBox
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GeonamesResult(OneResult):
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self.raw.get('lat')
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self.raw.get('lng')
|
||||
|
||||
@property
|
||||
def geonames_id(self):
|
||||
return self.raw.get('geonameId')
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw.get('name')
|
||||
|
||||
@property
|
||||
def feature_class(self):
|
||||
return self.raw.get('fcl')
|
||||
|
||||
@property
|
||||
def class_description(self):
|
||||
return self.raw.get('fclName')
|
||||
|
||||
@property
|
||||
def code(self):
|
||||
return self.raw.get('fcode')
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return self.raw.get('fcodeName')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw.get('adminName1')
|
||||
|
||||
@property
|
||||
def state_code(self):
|
||||
return self.raw.get('adminCode1')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw.get('countryName')
|
||||
|
||||
@property
|
||||
def country_code(self):
|
||||
return self.raw.get('countryCode')
|
||||
|
||||
@property
|
||||
def population(self):
|
||||
return self.raw.get('population')
|
||||
|
||||
|
||||
class GeonamesQuery(MultipleResultsQuery):
|
||||
"""
|
||||
GeoNames REST Web Services
|
||||
==========================
|
||||
GeoNames is mainly using REST webservices. Find nearby postal codes / reverse geocoding
|
||||
This service comes in two flavors.You can either pass the lat/long or a postalcode/placename.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://www.geonames.org/export/web-services.html
|
||||
"""
|
||||
provider = 'geonames'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'http://api.geonames.org/searchJSON'
|
||||
_RESULT_CLASS = GeonamesResult
|
||||
_KEY = geonames_username
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
"""Will be overridden according to the targetted web service"""
|
||||
base_kwargs = {
|
||||
'q': location,
|
||||
'fuzzy': kwargs.get('fuzzy', 1.0),
|
||||
'username': provider_key,
|
||||
'maxRows': kwargs.get('maxRows', 1),
|
||||
}
|
||||
# check out for bbox in kwargs
|
||||
bbox = kwargs.pop('proximity', None)
|
||||
if bbox is not None:
|
||||
bbox = BBox.factory(bbox)
|
||||
base_kwargs.update(
|
||||
{'east': bbox.east, 'west': bbox.west,
|
||||
'north': bbox.north, 'south': bbox.south})
|
||||
|
||||
# look out for valid extra kwargs
|
||||
supported_kwargs = set((
|
||||
'name', 'name_equals', 'name_startsWith', 'startRow',
|
||||
'country', 'countryBias', 'continentCode',
|
||||
'adminCode1', 'adminCode2', 'adminCode3', 'cities',
|
||||
'featureClass', 'featureCode',
|
||||
'lang', 'type', 'style',
|
||||
'isNameRequired', 'tag', 'operator', 'charset',
|
||||
'east', 'west', 'north', 'south',
|
||||
'orderby', 'inclBbox',
|
||||
))
|
||||
found_kwargs = supported_kwargs & set(kwargs.keys())
|
||||
LOGGER.debug("Adding extra kwargs %s", found_kwargs)
|
||||
|
||||
# update base kwargs with extra ones
|
||||
base_kwargs.update(dict(
|
||||
[(extra, kwargs[extra]) for extra in found_kwargs]
|
||||
))
|
||||
return base_kwargs
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
""" Changed: removed check on number of elements:
|
||||
- totalResultsCount not sytematically returned (e.g in hierarchy)
|
||||
- done in base.py
|
||||
"""
|
||||
status = json_response.get('status')
|
||||
if status:
|
||||
message = status.get('message')
|
||||
value = status.get('value')
|
||||
custom_messages = {
|
||||
10: 'Invalid credentials',
|
||||
18: 'Do not use the demo account for your application',
|
||||
}
|
||||
self.error = custom_messages.get(value, message)
|
||||
LOGGER.error("Error %s from JSON %s", self.error, json_response)
|
||||
|
||||
return self.error
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
# extract the array of JSON objects
|
||||
return json_response['geonames']
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = GeonamesQuery('Ottawa, Ontario', maxRows=1)
|
||||
print(json.dumps(g.geojson, indent=4))
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,30 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from geocoder.geonames import GeonamesQuery
|
||||
|
||||
|
||||
class GeonamesChildren(GeonamesQuery):
|
||||
""" Children:
|
||||
http://api.geonames.org/childrenJSON?formatted=true&geonameId=6094817
|
||||
"""
|
||||
|
||||
provider = 'geonames'
|
||||
method = 'children'
|
||||
|
||||
_URL = 'http://api.geonames.org/childrenJSON'
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
"""Will be overridden according to the targetted web service"""
|
||||
return {
|
||||
'geonameId': location,
|
||||
'username': provider_key,
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Searching Ottawa...")
|
||||
g = GeonamesQuery('Ottawa, Ontario')
|
||||
g.debug()
|
||||
print("Searching its children...")
|
||||
c = GeonamesChildren(g.pop().geonames_id)
|
||||
c.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,122 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from geocoder.geonames import GeonamesQuery, GeonamesResult
|
||||
|
||||
|
||||
class GeonamesFullResult(GeonamesResult):
|
||||
""" Get more information for given geonames_id, e.g timzone and administrative hierarchy"""
|
||||
|
||||
@property
|
||||
def continent(self):
|
||||
return self.raw.get('continentCode', "")
|
||||
|
||||
@property
|
||||
def country_geonames_id(self):
|
||||
return self.raw.get('countryId', 0)
|
||||
|
||||
@property
|
||||
def state_geonames_id(self):
|
||||
return self.raw.get('adminId1', 0)
|
||||
|
||||
@property
|
||||
def admin2(self):
|
||||
return self.raw.get('adminName2', "")
|
||||
|
||||
@property
|
||||
def admin2_geonames_id(self):
|
||||
return self.raw.get('adminId2', "")
|
||||
|
||||
@property
|
||||
def admin3(self):
|
||||
return self.raw.get('adminName3', "")
|
||||
|
||||
@property
|
||||
def admin3_geonames_id(self):
|
||||
return self.raw.get('adminId3', "")
|
||||
|
||||
@property
|
||||
def admin4(self):
|
||||
return self.raw.get('adminName4', "")
|
||||
|
||||
@property
|
||||
def admin4_geonames_id(self):
|
||||
return self.raw.get('adminId4', "")
|
||||
|
||||
@property
|
||||
def admin5(self):
|
||||
return self.raw.get('adminName5', "")
|
||||
|
||||
@property
|
||||
def admin5_geonames_id(self):
|
||||
return self.raw.get('adminId5', "")
|
||||
|
||||
@property
|
||||
def srtm3(self):
|
||||
return self.raw.get('srtm3', 0)
|
||||
|
||||
@property
|
||||
def wikipedia(self):
|
||||
return self.raw.get('wikipediaURL', "")
|
||||
|
||||
@property
|
||||
def timeZoneId(self):
|
||||
timezone = self.raw.get('timezone')
|
||||
if timezone:
|
||||
return timezone.get('timeZoneId')
|
||||
|
||||
@property
|
||||
def timeZoneName(self):
|
||||
timezone = self.raw.get('timezone')
|
||||
if timezone:
|
||||
return timezone.get('timeZoneId')
|
||||
|
||||
@property
|
||||
def rawOffset(self):
|
||||
timezone = self.raw.get('timezone')
|
||||
if timezone:
|
||||
return timezone.get('gmtOffset')
|
||||
|
||||
@property
|
||||
def dstOffset(self):
|
||||
timezone = self.raw.get('timezone')
|
||||
if timezone:
|
||||
return timezone.get('dstOffset')
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
bbox = self.raw.get('bbox', {})
|
||||
south = bbox.get('south')
|
||||
west = bbox.get('west')
|
||||
north = bbox.get('north')
|
||||
east = bbox.get('east')
|
||||
return self._get_bbox(south, west, north, east)
|
||||
|
||||
|
||||
class GeonamesDetails(GeonamesQuery):
|
||||
""" Details:
|
||||
http://api.geonames.org/getJSON?geonameId=6094817&style=full
|
||||
"""
|
||||
|
||||
provider = 'geonames'
|
||||
method = 'details'
|
||||
|
||||
_URL = 'http://api.geonames.org/getJSON'
|
||||
_RESULT_CLASS = GeonamesFullResult
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
"""Will be overridden according to the targetted web service"""
|
||||
return {
|
||||
'geonameId': location,
|
||||
'username': provider_key,
|
||||
'style': 'full'
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
# the returned JSON contains the object.
|
||||
# Need to wrap it into an array
|
||||
return [json_response]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
c = GeonamesDetails(6094817)
|
||||
c.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,20 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from geocoder.geonames_children import GeonamesChildren
|
||||
|
||||
|
||||
class GeonamesHierarchy(GeonamesChildren):
|
||||
""" Hierarchy:
|
||||
http://api.geonames.org/hierarchyJSON?formatted=true&geonameId=6094817
|
||||
"""
|
||||
|
||||
provider = 'geonames'
|
||||
method = 'hierarchy'
|
||||
|
||||
_URL = 'http://api.geonames.org/hierarchyJSON'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Searching Ottawa's hierarchy...")
|
||||
c = GeonamesHierarchy(6094817)
|
||||
c.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
|
||||
|
||||
class GisgraphyResult(OneResult):
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self.raw.get('lat')
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self.raw.get('lng')
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw.get('formatedFull', '')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw.get('countryCode', '')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw.get('state', '')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.raw.get('city', '')
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self.raw.get('streetName', '')
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self.raw.get('houseNumber', '')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self.raw.get('zipCode', '')
|
||||
|
||||
|
||||
class GisgraphyQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Gisgraphy REST API
|
||||
=======================
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://www.gisgraphy.com/documentation/user-guide.php
|
||||
"""
|
||||
provider = 'gisgraphy'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'https://services.gisgraphy.com/geocoding/'
|
||||
_RESULT_CLASS = GisgraphyResult
|
||||
_KEY_MANDATORY = False
|
||||
|
||||
def _build_headers(self, provider_key, **kwargs):
|
||||
return {
|
||||
'Referer': "https://services.gisgraphy.com",
|
||||
'User-agent': 'geocoder-converter'
|
||||
}
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'address': location,
|
||||
'limitnbresult': kwargs.get('maxRows', 1),
|
||||
'format': 'json',
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return json_response['result']
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = GisgraphyQuery('Ottawa Ontario', maxRows=3)
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.location import Location
|
||||
from geocoder.gisgraphy import GisgraphyResult, GisgraphyQuery
|
||||
|
||||
|
||||
class GisgraphyReverseResult(GisgraphyResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.address)
|
||||
|
||||
|
||||
class GisgraphyReverse(GisgraphyQuery):
|
||||
"""
|
||||
Gisgraphy REST API
|
||||
=======================
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://www.gisgraphy.com/documentation/user-guide.php
|
||||
"""
|
||||
provider = 'gisgraphy'
|
||||
method = 'reverse'
|
||||
|
||||
_URL = 'https://services.gisgraphy.com/reversegeocoding/'
|
||||
_RESULT_CLASS = GisgraphyReverseResult
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
location = Location(location)
|
||||
return {
|
||||
'lat': location.lat,
|
||||
'lng': location.lng,
|
||||
'format': 'json',
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = GisgraphyReverse("45.4 -75.7")
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,294 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
import six
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import google_key, google_client, google_client_secret
|
||||
from collections import OrderedDict
|
||||
import ratelim
|
||||
|
||||
|
||||
class GoogleResult(OneResult):
|
||||
|
||||
def __init__(self, json_content):
|
||||
# flatten geometry
|
||||
geometry = json_content.get('geometry', {})
|
||||
self._location = geometry.get('location', {})
|
||||
self._location_type = geometry.get('location_type', {})
|
||||
self._viewport = geometry.get('viewport', {})
|
||||
|
||||
# Parse address components with short & long names
|
||||
for item in json_content['address_components']:
|
||||
for category in item['types']:
|
||||
json_content.setdefault(category, {})
|
||||
json_content[category]['long_name'] = item['long_name']
|
||||
json_content[category]['short_name'] = item['short_name']
|
||||
|
||||
# proceed with super.__init__
|
||||
super(GoogleResult, self).__init__(json_content)
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self._location.get('lat')
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self._location.get('lng')
|
||||
|
||||
@property
|
||||
def place(self):
|
||||
return self.raw.get('place_id')
|
||||
|
||||
@property
|
||||
def quality(self):
|
||||
quality = self.raw.get('types')
|
||||
if quality:
|
||||
return quality[0]
|
||||
|
||||
@property
|
||||
def accuracy(self):
|
||||
return self._location_type
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
south = self._viewport.get('southwest', {}).get('lat')
|
||||
west = self._viewport.get('southwest', {}).get('lng')
|
||||
north = self._viewport.get('northeast', {}).get('lat')
|
||||
east = self._viewport.get('northeast', {}).get('lng')
|
||||
return self._get_bbox(south, west, north, east)
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw.get('formatted_address')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self.raw.get('postal_code', {}).get('short_name')
|
||||
|
||||
@property
|
||||
def subpremise(self):
|
||||
return self.raw.get('subpremise', {}).get('short_name')
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self.raw.get('street_number', {}).get('short_name')
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self.raw.get('route', {}).get('short_name')
|
||||
|
||||
@property
|
||||
def street_long(self):
|
||||
return self.raw.get('route', {}).get('long_name')
|
||||
|
||||
@property
|
||||
def road_long(self):
|
||||
return self.street_long
|
||||
|
||||
@property
|
||||
def neighborhood(self):
|
||||
return self.raw.get('neighborhood', {}).get('short_name')
|
||||
|
||||
@property
|
||||
def sublocality(self):
|
||||
return self.raw.get('sublocality', {}).get('short_name')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.raw.get('locality', {}).get('short_name') or self.postal_town
|
||||
|
||||
@property
|
||||
def city_long(self):
|
||||
return self.raw.get('locality', {}).get('long_name') or self.postal_town_long
|
||||
|
||||
@property
|
||||
def postal_town(self):
|
||||
return self.raw.get('postal_town', {}).get('short_name')
|
||||
|
||||
@property
|
||||
def postal_town_long(self):
|
||||
return self.raw.get('postal_town', {}).get('long_name')
|
||||
|
||||
@property
|
||||
def county(self):
|
||||
return self.raw.get('administrative_area_level_2', {}).get('short_name')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw.get('administrative_area_level_1', {}).get('short_name')
|
||||
|
||||
@property
|
||||
def state_long(self):
|
||||
return self.raw.get('administrative_area_level_1', {}).get('long_name')
|
||||
|
||||
@property
|
||||
def province_long(self):
|
||||
return self.state_long
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw.get('country', {}).get('short_name')
|
||||
|
||||
@property
|
||||
def country_long(self):
|
||||
return self.raw.get('country', {}).get('long_name')
|
||||
|
||||
|
||||
class GoogleQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Google Geocoding API
|
||||
====================
|
||||
Geocoding is the process of converting addresses into geographic
|
||||
coordinates (like latitude 37.423021 and longitude -122.083739),
|
||||
which you can use to place markers or position the map.
|
||||
API Reference
|
||||
-------------
|
||||
https://developers.google.com/maps/documentation/geocoding
|
||||
|
||||
For ambiguous queries or 'nearby' type queries, use the Places Text Search instead.
|
||||
https://developers.google.com/maps/documentation/geocoding/best-practices#automated-system
|
||||
|
||||
Parameters
|
||||
----------
|
||||
:param location: Your search location you want geocoded.
|
||||
:param components: Component Filtering
|
||||
:param method: (default=geocode) Use the following:
|
||||
> geocode
|
||||
> places
|
||||
> reverse
|
||||
> timezone
|
||||
> elevation
|
||||
:param key: Your Google developers free key.
|
||||
:param language: 2-letter code of preferred language of returned address elements.
|
||||
:param client: Google for Work client ID. Use with client_secret. Cannot use with key parameter
|
||||
:param client_secret: Google for Work client secret. Use with client.
|
||||
"""
|
||||
provider = 'google'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'https://maps.googleapis.com/maps/api/geocode/json'
|
||||
_RESULT_CLASS = GoogleResult
|
||||
_KEY = google_key
|
||||
_KEY_MANDATORY = False
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
params = self._location_init(location, **kwargs)
|
||||
params['language'] = kwargs.get('language', '')
|
||||
self.rate_limit = kwargs.get('rate_limit', True)
|
||||
|
||||
# adapt params to authentication method
|
||||
# either with client / secret
|
||||
self.client = kwargs.get('client', google_client)
|
||||
self.client_secret = kwargs.get('client_secret', google_client_secret)
|
||||
|
||||
if self.client and self.client_secret:
|
||||
params['client'] = self.client
|
||||
return self._encode_params(params)
|
||||
# or API key
|
||||
else:
|
||||
# provider_key is computed in base.py:
|
||||
# either cls._KEY (google_key) or kwargs['key'] if provided
|
||||
params['key'] = provider_key
|
||||
return params
|
||||
|
||||
def _location_init(self, location, **kwargs):
|
||||
return {
|
||||
'address': location,
|
||||
'bounds': kwargs.get('bounds', ''),
|
||||
'components': kwargs.get('components', ''),
|
||||
'region': kwargs.get('region', ''),
|
||||
}
|
||||
|
||||
def _encode_params(self, params):
|
||||
# turn non-empty params into sorted list in order to maintain signature validity.
|
||||
# Requests will honor the order.
|
||||
ordered_params = sorted([(k, v)
|
||||
for (k, v) in params.items() if v])
|
||||
params = OrderedDict(ordered_params)
|
||||
|
||||
# the signature parameter needs to come in the end of the url
|
||||
params['signature'] = self._sign_url(
|
||||
self.url, ordered_params, self.client_secret)
|
||||
|
||||
return params
|
||||
|
||||
def _sign_url(self, base_url=None, params=None, client_secret=None):
|
||||
""" Sign a request URL with a Crypto Key.
|
||||
Usage:
|
||||
from urlsigner import sign_url
|
||||
signed_url = sign_url(base_url=my_url,
|
||||
params=url_params,
|
||||
client_secret=CLIENT_SECRET)
|
||||
Args:
|
||||
base_url - The trunk of the URL to sign. E.g. https://maps.googleapis.com/maps/api/geocode/json
|
||||
params - List of tuples of URL parameters INCLUDING YOUR CLIENT ID ('client','gme-...')
|
||||
client_secret - Your Crypto Key from Google for Work
|
||||
Returns:
|
||||
The signature as a dictionary #signed request URL
|
||||
"""
|
||||
import hashlib
|
||||
import hmac
|
||||
import base64
|
||||
if six.PY3:
|
||||
from urllib.parse import urlparse, urlencode
|
||||
else:
|
||||
from urllib import urlencode
|
||||
from urlparse import urlparse
|
||||
|
||||
# Return if any parameters aren't given
|
||||
if not base_url or not self.client_secret or not self.client:
|
||||
return None
|
||||
|
||||
# assuming parameters will be submitted to Requests in identical order!
|
||||
url = urlparse(base_url + "?" + urlencode(params))
|
||||
|
||||
# We only need to sign the path+query part of the string
|
||||
url_to_sign = (url.path + "?" + url.query).encode('utf-8')
|
||||
|
||||
# Decode the private key into its binary format
|
||||
# We need to decode the URL-encoded private key
|
||||
decoded_key = base64.urlsafe_b64decode(client_secret)
|
||||
|
||||
# Create a signature using the private key and the URL-encoded
|
||||
# string using HMAC SHA1. This signature will be binary.
|
||||
signature = hmac.new(decoded_key, url_to_sign, hashlib.sha1)
|
||||
|
||||
# Encode the binary signature into base64 for use within a URL
|
||||
encoded_signature = base64.urlsafe_b64encode(signature.digest())
|
||||
|
||||
# Return signature (to be appended as a 'signature' in params)
|
||||
return encoded_signature
|
||||
|
||||
def rate_limited_get(self, *args, **kwargs):
|
||||
if not self.rate_limit:
|
||||
return super(GoogleQuery, self).rate_limited_get(*args, **kwargs)
|
||||
elif self.client and self.client_secret:
|
||||
return self.rate_limited_get_for_work(*args, **kwargs)
|
||||
else:
|
||||
return self.rate_limited_get_for_dev(*args, **kwargs)
|
||||
|
||||
@ratelim.greedy(2500, 60 * 60 * 24)
|
||||
@ratelim.greedy(10, 1)
|
||||
def rate_limited_get_for_dev(self, *args, **kwargs):
|
||||
return super(GoogleQuery, self).rate_limited_get(*args, **kwargs)
|
||||
|
||||
@ratelim.greedy(100000, 60 * 60 * 24) # Google for Work daily limit
|
||||
@ratelim.greedy(50, 1) # Google for Work limit per second
|
||||
def rate_limited_get_for_work(self, *args, **kwargs):
|
||||
return super(GoogleQuery, self).rate_limited_get(*args, **kwargs)
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
status = json_response.get('status')
|
||||
if not status == 'OK':
|
||||
self.error = status
|
||||
|
||||
return self.error
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return json_response.get('results', [])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = GoogleQuery('11 Wall Street, New York')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import google_key
|
||||
from geocoder.location import Location
|
||||
|
||||
|
||||
class ElevationResult(OneResult):
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
if self.elevation:
|
||||
return 'OK'
|
||||
else:
|
||||
return 'ERROR - No Elevation found'
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.elevation)
|
||||
|
||||
@property
|
||||
def meters(self):
|
||||
if self.elevation:
|
||||
return round(self.elevation, 1)
|
||||
|
||||
@property
|
||||
def feet(self):
|
||||
if self.elevation:
|
||||
return round(self.elevation * 3.28084, 1)
|
||||
|
||||
@property
|
||||
def elevation(self):
|
||||
return self.raw.get('elevation')
|
||||
|
||||
@property
|
||||
def resolution(self):
|
||||
return self.raw.get('resolution')
|
||||
|
||||
|
||||
class ElevationQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Google Elevation API
|
||||
====================
|
||||
The Elevation API provides elevation data for all locations on the surface of the
|
||||
earth, including depth locations on the ocean floor (which return negative values).
|
||||
In those cases where Google does not possess exact elevation measurements at the
|
||||
precise location you request, the service will interpolate and return an averaged
|
||||
value using the four nearest locations.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://developers.google.com/maps/documentation/elevation/
|
||||
"""
|
||||
provider = 'google'
|
||||
method = 'elevation'
|
||||
|
||||
_URL = 'https://maps.googleapis.com/maps/api/elevation/json'
|
||||
_RESULT_CLASS = ElevationResult
|
||||
_KEY = google_key
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'locations': str(Location(location)),
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return json_response['results']
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = ElevationQuery([45.123, -76.123])
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,181 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import google_key
|
||||
from geocoder.location import BBox
|
||||
|
||||
# todo: Paging (pagetoken) is not fully supported since we only return the first result. Need to return all results to the user so paging will make sense
|
||||
# todo: Add support for missing results fields html_attributions, opening_hours, photos, scope, alt_ids, types [not just the first one]
|
||||
# todo: Add support for nearbysearch and radarsearch variations of the Google Places API
|
||||
|
||||
|
||||
class PlacesResult(OneResult):
|
||||
|
||||
def __init__(self, json_content):
|
||||
# flatten geometry
|
||||
geometry = json_content.get('geometry', {})
|
||||
self._location = geometry.get('location', {})
|
||||
json_content['northeast'] = geometry.get(
|
||||
'viewport', {}).get('northeast', {})
|
||||
json_content['southwest'] = geometry.get(
|
||||
'viewport', {}).get('southwest', {})
|
||||
|
||||
# proceed with super.__init__
|
||||
super(PlacesResult, self).__init__(json_content)
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self._location.get('lat')
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self._location.get('lng')
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self.raw.get('id')
|
||||
|
||||
@property
|
||||
def reference(self):
|
||||
return self.raw.get('reference')
|
||||
|
||||
@property
|
||||
def place_id(self):
|
||||
return self.raw.get('place_id')
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
type = self.raw.get('types')
|
||||
if type:
|
||||
return type[0]
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw.get('formatted_address')
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
return self.raw.get('icon')
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.raw.get('name')
|
||||
|
||||
@property
|
||||
def vicinity(self):
|
||||
return self.raw.get('vicinity')
|
||||
|
||||
@property
|
||||
def price_level(self):
|
||||
return self.raw.get('price_level')
|
||||
|
||||
@property
|
||||
def rating(self):
|
||||
return self.raw.get('rating')
|
||||
|
||||
|
||||
class PlacesQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Google Places API
|
||||
====================
|
||||
The Google Places API Web Service allows you to query for place information on a variety of categories,
|
||||
such as: establishments, prominent points of interest, geographic locations, and more.
|
||||
You can search for places either by proximity or a text string.
|
||||
A Place Search returns a list of places along with summary information about each place; additional
|
||||
information is available via a Place Details query.
|
||||
|
||||
At this time, only the "Text Search" is supported by this library. "Text Search" can be used
|
||||
when you don't have pristine formatted addresses required by the regular Google Maps Geocoding API
|
||||
or when you want to do 'nearby' searches like 'restaurants near Sydney'.
|
||||
|
||||
The Geocoding best practices reference indicates that when you have 'ambiguous queries in an automated system
|
||||
you would be better served using the Places API Text Search than the Maps Geocoding API
|
||||
https://developers.google.com/maps/documentation/geocoding/best-practices
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://developers.google.com/places/web-service/intro
|
||||
https://developers.google.com/places/web-service/search
|
||||
|
||||
l = geocoder.google('Elm Plaza Shopping Center, Enfield, CT 06082', method='places')
|
||||
l = geocoder.google('food near white house', method='places')
|
||||
l = geocoder.google('1st and main', method='places')
|
||||
|
||||
Parameters
|
||||
----------
|
||||
:param location: Your search location or phrase you want geocoded.
|
||||
:param key: Your Google developers free key.
|
||||
|
||||
:param proximity: (optional) lat,lng point around which results will be given preference
|
||||
:param radius: (optional) in meters, used with proximity
|
||||
:param language: (optional) 2-letter code of preferred language of returned address elements.
|
||||
:param minprice: (optional) 0 (most affordable) to 4 (most expensive)
|
||||
:param maxprice: (optional) 0 (most affordable) to 4 (most expensive)
|
||||
:param opennow: (optional) value is ignored. when present, closed places and places without opening hours will be omitted
|
||||
:param pagetoken: (optional) get next 20 results from previously run search. when set, other criteria are ignored
|
||||
:param type: (optional) restrict results to one type of place
|
||||
"""
|
||||
provider = 'google'
|
||||
method = 'places'
|
||||
|
||||
_URL = 'https://maps.googleapis.com/maps/api/place/textsearch/json'
|
||||
_RESULT_CLASS = PlacesResult
|
||||
_KEY = google_key
|
||||
|
||||
def __init__(self, location, **kwargs):
|
||||
super(PlacesQuery, self).__init__(location, **kwargs)
|
||||
|
||||
self.next_page_token = None
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
# handle specific case of proximity (aka 'location' for google)
|
||||
bbox = kwargs.get('proximity', '')
|
||||
if bbox:
|
||||
bbox = BBox.factory(bbox)
|
||||
# do not forget to convert bbox to google expectations...
|
||||
bbox = bbox.latlng
|
||||
|
||||
# define all
|
||||
params = {
|
||||
# required
|
||||
'query': location,
|
||||
'key': provider_key,
|
||||
|
||||
# optional
|
||||
'location': bbox,
|
||||
'radius': kwargs.get('radius', ''),
|
||||
'language': kwargs.get('language', ''),
|
||||
'minprice': kwargs.get('minprice', ''),
|
||||
'maxprice': kwargs.get('maxprice', ''),
|
||||
'type': kwargs.get('type', ''),
|
||||
}
|
||||
|
||||
# optional, don't send unless needed
|
||||
if 'opennow' in kwargs:
|
||||
params['opennow'] = ''
|
||||
|
||||
# optional, don't send unless needed
|
||||
if 'pagetoken' in kwargs:
|
||||
params['pagetoken'] = kwargs['pagetoken']
|
||||
|
||||
return params
|
||||
|
||||
def _parse_results(self, json_response):
|
||||
super(PlacesQuery, self)._parse_results(json_response)
|
||||
|
||||
# store page token if any
|
||||
self.next_page_token = json_response.get('next_page_token')
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return json_response['results']
|
||||
|
||||
@property
|
||||
def query(self):
|
||||
return self.location
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = PlacesQuery('rail station, Ottawa')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from geocoder.google import GoogleResult, GoogleQuery
|
||||
from geocoder.location import Location
|
||||
|
||||
|
||||
class GoogleReverseResult(GoogleResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.address)
|
||||
|
||||
|
||||
class GoogleReverse(GoogleQuery):
|
||||
"""
|
||||
Google Geocoding API
|
||||
====================
|
||||
Geocoding is the process of converting addresses (like "1600 Amphitheatre
|
||||
Parkway, Mountain View, CA") into geographic coordinates (like latitude
|
||||
37.423021 and longitude -122.083739), which you can use to place markers or
|
||||
position the map.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://developers.google.com/maps/documentation/geocoding/
|
||||
"""
|
||||
provider = 'google'
|
||||
method = 'reverse'
|
||||
|
||||
def _location_init(self, location, **kwargs):
|
||||
return {
|
||||
'latlng': str(Location(location)),
|
||||
'sensor': 'false',
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = GoogleReverse((45.4215296, -75.6971930))
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
import time
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import google_key
|
||||
from geocoder.location import Location
|
||||
|
||||
|
||||
class TimezoneResult(OneResult):
|
||||
|
||||
def __repr__(self):
|
||||
return u'<[{}] [{}]>'.format(self.status, self.timeZoneName)
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.timeZoneName)
|
||||
|
||||
@property
|
||||
def timeZoneId(self):
|
||||
return self.raw.get('timeZoneId')
|
||||
|
||||
@property
|
||||
def timeZoneName(self):
|
||||
return self.raw.get('timeZoneName')
|
||||
|
||||
@property
|
||||
def rawOffset(self):
|
||||
return self.raw.get('rawOffset')
|
||||
|
||||
@property
|
||||
def dstOffset(self):
|
||||
return self.raw.get('dstOffset')
|
||||
|
||||
|
||||
class TimezoneQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Google Time Zone API
|
||||
====================
|
||||
The Time Zone API provides time offset data for locations on the surface of the earth.
|
||||
Requesting the time zone information for a specific Latitude/Longitude pair will
|
||||
return the name of that time zone, the time offset from UTC, and the Daylight Savings offset.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://developers.google.com/maps/documentation/timezone/
|
||||
"""
|
||||
provider = 'google'
|
||||
method = 'timezone'
|
||||
|
||||
_URL = 'https://maps.googleapis.com/maps/api/timezone/json'
|
||||
_RESULT_CLASS = TimezoneResult
|
||||
_KEY = google_key
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'location': str(Location(location)),
|
||||
'timestamp': kwargs.get('timestamp', time.time()),
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return [json_response]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = TimezoneQuery([45.5375801, -75.2465979])
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,166 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import here_app_id, here_app_code
|
||||
|
||||
from geocoder.location import BBox
|
||||
|
||||
|
||||
class HereResult(OneResult):
|
||||
|
||||
def __init__(self, json_content):
|
||||
self._display_position = json_content.get('DisplayPosition', {})
|
||||
self._address = json_content.get('Address', {})
|
||||
self._mapview = json_content.get('MapView', {})
|
||||
|
||||
for item in json_content['Address']['AdditionalData']:
|
||||
json_content[item['key']] = item['value']
|
||||
|
||||
super(HereResult, self).__init__(json_content)
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self._display_position.get('Latitude')
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self._display_position.get('Longitude')
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self._address.get('Label')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self._address.get('PostalCode')
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self._address.get('HouseNumber')
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self._address.get('Street')
|
||||
|
||||
@property
|
||||
def neighborhood(self):
|
||||
return self.district
|
||||
|
||||
@property
|
||||
def district(self):
|
||||
return self._address.get('District')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self._address.get('City')
|
||||
|
||||
@property
|
||||
def county(self):
|
||||
return self._address.get('County')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self._address.get('State')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self._address.get('Country')
|
||||
|
||||
@property
|
||||
def quality(self):
|
||||
return self.raw.get('MatchLevel')
|
||||
|
||||
@property
|
||||
def accuracy(self):
|
||||
return self.raw.get('MatchType')
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
south = self._mapview['BottomRight'].get('Latitude')
|
||||
north = self._mapview['TopLeft'].get('Latitude')
|
||||
west = self._mapview['TopLeft'].get('Longitude')
|
||||
east = self._mapview['BottomRight'].get('Longitude')
|
||||
return self._get_bbox(south, west, north, east)
|
||||
|
||||
|
||||
class HereQuery(MultipleResultsQuery):
|
||||
"""
|
||||
HERE Geocoding REST API
|
||||
=======================
|
||||
Send a request to the geocode endpoint to find an address
|
||||
using a combination of country, state, county, city,
|
||||
postal code, district, street and house number.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://developer.here.com/rest-apis/documentation/geocoder
|
||||
"""
|
||||
provider = 'here'
|
||||
method = 'geocode'
|
||||
qualified_address = ['city', 'district', 'postal', 'state', 'country']
|
||||
|
||||
_URL = 'http://geocoder.cit.api.here.com/6.2/geocode.json'
|
||||
_RESULT_CLASS = HereResult
|
||||
|
||||
@classmethod
|
||||
def _get_api_key(cls, key=None):
|
||||
# API key is split between app_id and app_code -> managed in _build_params
|
||||
pass
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
# HERE Credentials
|
||||
app_id = kwargs.get('app_id', here_app_id)
|
||||
app_code = kwargs.get('app_code', here_app_code)
|
||||
if not bool(app_id and app_code):
|
||||
raise ValueError("Provide app_id & app_code")
|
||||
|
||||
# URL Params
|
||||
params = {
|
||||
'searchtext': location,
|
||||
'app_id': app_id,
|
||||
'app_code': app_code,
|
||||
'gen': 9,
|
||||
'maxresults': kwargs.get('maxRows', 1),
|
||||
'language': kwargs.get('language', 'en'),
|
||||
}
|
||||
|
||||
# bounding box if present
|
||||
bbox = kwargs.get('bbox')
|
||||
if bbox:
|
||||
bbox = BBox(bbox=bbox)
|
||||
# do not forget to convert bbox to mapbox expectations...
|
||||
params['bbox'] = u'{north},{west};{south},{east}'.format(
|
||||
west=bbox.west,
|
||||
east=bbox.east,
|
||||
south=bbox.south,
|
||||
north=bbox.north
|
||||
)
|
||||
|
||||
for value in self.qualified_address:
|
||||
if kwargs.get(value) is not None:
|
||||
params[value] = kwargs.get(value)
|
||||
|
||||
return params
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
status = json_response.get('type')
|
||||
if not status == 'OK':
|
||||
self.error = status
|
||||
|
||||
return self.error
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
# Build intial Tree with results
|
||||
return [item['Location']
|
||||
for item in json_response['Response']['View'][0]['Result']]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = HereQuery("New York City")
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from geocoder.location import Location
|
||||
from geocoder.here import HereResult, HereQuery
|
||||
|
||||
|
||||
class HereReverseResult(HereResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.address)
|
||||
|
||||
|
||||
class HereReverse(HereQuery):
|
||||
"""
|
||||
HERE Geocoding REST API
|
||||
=======================
|
||||
Send a request to the geocode endpoint to find an address
|
||||
using a combination of country, state, county, city,
|
||||
postal code, district, street and house number.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://developer.here.com/rest-apis/documentation/geocoder
|
||||
"""
|
||||
provider = 'here'
|
||||
method = 'reverse'
|
||||
|
||||
_RESULT_CLASS = HereReverseResult
|
||||
_URL = 'http://reverse.geocoder.cit.api.here.com/6.2/reversegeocode.json'
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
params = super(HereReverse, self)._build_params(location, provider_key, **kwargs)
|
||||
del params['searchtext']
|
||||
|
||||
location = str(Location(location))
|
||||
params.update({
|
||||
'prox': location,
|
||||
'mode': 'retrieveAddresses',
|
||||
'gen': 8,
|
||||
})
|
||||
return params
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = HereReverse([45.4049053, -75.7077965])
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,92 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.location import Location
|
||||
|
||||
|
||||
class IpinfoResult(OneResult):
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
loc = self.raw.get('loc')
|
||||
if loc:
|
||||
return Location(loc).lat
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
loc = self.raw.get('loc')
|
||||
if loc:
|
||||
return Location(loc).lng
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
if self.city:
|
||||
return u'{0}, {1}, {2}'.format(self.city, self.state, self.country)
|
||||
elif self.state:
|
||||
return u'{0}, {1}'.format(self.state, self.country)
|
||||
elif self.country:
|
||||
return u'{0}'.format(self.country)
|
||||
else:
|
||||
return u''
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self.raw.get('postal')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.raw.get('city')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw.get('region')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw.get('country')
|
||||
|
||||
@property
|
||||
def hostname(self):
|
||||
return self.raw.get('hostname')
|
||||
|
||||
@property
|
||||
def ip(self):
|
||||
return self.raw.get('ip')
|
||||
|
||||
@property
|
||||
def org(self):
|
||||
return self.raw.get('org')
|
||||
|
||||
|
||||
class IpinfoQuery(MultipleResultsQuery):
|
||||
"""
|
||||
API Reference
|
||||
-------------
|
||||
https://ipinfo.io
|
||||
"""
|
||||
provider = 'ipinfo'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'http://ipinfo.io/json'
|
||||
_RESULT_CLASS = IpinfoResult
|
||||
_KEY_MANDATORY = False
|
||||
|
||||
def _before_initialize(self, location, **kwargs):
|
||||
if location.lower() == 'me' or location == '':
|
||||
self.url = 'http://ipinfo.io/json'
|
||||
else:
|
||||
self.url = 'http://ipinfo.io/{0}/json'.format(self.location)
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return [json_response]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = IpinfoQuery('8.8.8.8')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
import os
|
||||
import re
|
||||
import requests
|
||||
|
||||
|
||||
bing_key = os.environ.get('BING_API_KEY')
|
||||
tomtom_key = os.environ.get('TOMTOM_API_KEY')
|
||||
here_app_id = os.environ.get('HERE_APP_ID')
|
||||
here_app_code = os.environ.get('HERE_APP_CODE')
|
||||
geonames_username = os.environ.get('GEONAMES_USERNAME')
|
||||
opencage_key = os.environ.get('OPENCAGE_API_KEY')
|
||||
mapquest_key = os.environ.get('MAPQUEST_API_KEY')
|
||||
baidu_key = os.environ.get('BAIDU_API_KEY')
|
||||
baidu_security_key = os.environ.get('BAIDU_SECURITY_KEY')
|
||||
gaode_key = os.environ.get('GAODE_API_KEY')
|
||||
w3w_key = os.environ.get('W3W_API_KEY')
|
||||
mapbox_access_token = os.environ.get('MAPBOX_ACCESS_TOKEN')
|
||||
google_key = os.environ.get('GOOGLE_API_KEY')
|
||||
google_client = os.environ.get('GOOGLE_CLIENT')
|
||||
google_client_secret = os.environ.get('GOOGLE_CLIENT_SECRET')
|
||||
mapzen_key = os.environ.get('MAPZEN_API_KEY')
|
||||
tamu_key = os.environ.get('TAMU_API_KEY')
|
||||
geocodefarm_key = os.environ.get('GEOCODEFARM_API_KEY')
|
||||
tgos_key = os.environ.get('TGOS_API_KEY')
|
||||
locationiq_key = os.environ.get('LOCATIONIQ_API_KEY')
|
||||
|
||||
|
||||
class CanadapostKeyLazySingleton(object):
|
||||
|
||||
CANADAPOST_KEY_REGEX = re.compile(r"'(....-....-....-....)';")
|
||||
|
||||
def __init__(self):
|
||||
self._key = None
|
||||
|
||||
def __call__(self, **kwargs):
|
||||
if self._key is None:
|
||||
self._key = self.retrieve_key(**kwargs)
|
||||
return self._key
|
||||
|
||||
@classmethod
|
||||
def retrieve_key(cls, **kwargs):
|
||||
# get key with traditionnal mechanism
|
||||
key = kwargs.get('key')
|
||||
canadapost_key = os.environ.get('CANADAPOST_API_KEY')
|
||||
if key or canadapost_key:
|
||||
return key if key else canadapost_key
|
||||
|
||||
# fallback
|
||||
try:
|
||||
url = 'http://www.canadapost.ca/cpo/mc/personal/postalcode/fpc.jsf'
|
||||
timeout = kwargs.get('timeout', 5.0)
|
||||
proxies = kwargs.get('proxies', '')
|
||||
r = requests.get(url, timeout=timeout, proxies=proxies)
|
||||
match = cls.CANADAPOST_KEY_REGEX.search(r.text)
|
||||
if match:
|
||||
return match.group(1)
|
||||
else:
|
||||
raise ValueError('No API Key found')
|
||||
except Exception as err:
|
||||
raise ValueError('Could not retrieve API Key: %s' % err)
|
||||
|
||||
|
||||
canadapost_key_getter = CanadapostKeyLazySingleton()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.location import BBox
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
|
||||
|
||||
class KomootResult(OneResult):
|
||||
|
||||
def __init__(self, json_content):
|
||||
# create safe shortcuts
|
||||
self._geometry = json_content.get('geometry', {})
|
||||
self._properties = json_content.get('properties', {})
|
||||
|
||||
# proceed with super.__init__
|
||||
super(KomootResult, self).__init__(json_content)
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self._geometry['coordinates'][1]
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self._geometry['coordinates'][0]
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
extent = self._properties.get('extent')
|
||||
if extent and all(extent):
|
||||
west = extent[0]
|
||||
north = extent[1]
|
||||
east = extent[2]
|
||||
south = extent[3]
|
||||
return BBox.factory([south, west, north, east]).as_dict
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
# Ontario, Canada
|
||||
address = ', '.join([self.state, self.country])
|
||||
|
||||
# 453 Booth street, Ottawa ON, Canada
|
||||
if self.housenumber:
|
||||
middle = ', '.join([self.street, self.city])
|
||||
address = ' '.join([self.housenumber, middle, address])
|
||||
|
||||
# 453 Booth street, Ottawa ON, Canada
|
||||
elif self.street:
|
||||
middle = ', '.join([self.street, self.city])
|
||||
address = ' '.join([middle, address])
|
||||
|
||||
# Ottawa ON, Canada
|
||||
elif self.city:
|
||||
address = ' '.join([self.city, address])
|
||||
|
||||
return address
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self._properties.get('country', '')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
if self.osm_value == 'state':
|
||||
return self._properties.get('name', '')
|
||||
return self._properties.get('state', '')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
if self.osm_value == 'city':
|
||||
return self._properties.get('name', '')
|
||||
return self._properties.get('city', '')
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self._properties.get('street', '')
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self._properties.get('housenumber', '')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self._properties.get('postcode', '')
|
||||
|
||||
@property
|
||||
def osm_id(self):
|
||||
return self._properties.get('osm_id', '')
|
||||
|
||||
@property
|
||||
def osm_value(self):
|
||||
return self._properties.get('osm_value', '')
|
||||
|
||||
@property
|
||||
def osm_key(self):
|
||||
return self._properties.get('osm_key', '')
|
||||
|
||||
@property
|
||||
def osm_type(self):
|
||||
return self._properties.get('osm_type', '')
|
||||
|
||||
|
||||
class KomootQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Komoot REST API
|
||||
=======================
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://photon.komoot.de
|
||||
"""
|
||||
provider = 'komoot'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'http://photon.komoot.de/api'
|
||||
_RESULT_CLASS = KomootResult
|
||||
_KEY_MANDATORY = False
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'q': location,
|
||||
'limit': kwargs.get('maxRows', 1),
|
||||
'lang': 'en',
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return json_response['features']
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = KomootQuery('Ottawa Ontario', maxRows=3)
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.location import Location
|
||||
from geocoder.komoot import KomootResult, KomootQuery
|
||||
|
||||
|
||||
class KomootReverseResult(KomootResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.address)
|
||||
|
||||
|
||||
class KomootReverse(KomootQuery):
|
||||
"""
|
||||
Komoot REST API
|
||||
=======================
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://photon.komoot.de
|
||||
"""
|
||||
provider = 'komoot'
|
||||
method = 'reverse'
|
||||
|
||||
_URL = 'https://photon.komoot.de/reverse'
|
||||
_RESULT_CLASS = KomootReverseResult
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
location = Location(location)
|
||||
return {
|
||||
'lat': location.lat,
|
||||
'lon': location.lng,
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = KomootReverse("45.4 -75.7")
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,225 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
import re
|
||||
import geocoder
|
||||
from six import string_types
|
||||
try:
|
||||
from statistics import mean
|
||||
except ImportError:
|
||||
def mean(args):
|
||||
return sum(args) / len(args)
|
||||
|
||||
|
||||
class Location(object):
|
||||
""" Location container """
|
||||
lat = None
|
||||
lng = None
|
||||
|
||||
def __init__(self, location, **kwargs):
|
||||
self.location = location
|
||||
self.kwargs = kwargs
|
||||
self._check_input(location)
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.latlng)
|
||||
|
||||
@staticmethod
|
||||
def _convert_float(number):
|
||||
try:
|
||||
return float(number)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def _check_input(self, location):
|
||||
# Checking for a LatLng String
|
||||
if isinstance(location, string_types):
|
||||
expression = r"[-]?\d+[.]?[-]?[\d]+"
|
||||
pattern = re.compile(expression)
|
||||
match = pattern.findall(location)
|
||||
if len(match) == 2:
|
||||
lat, lng = match
|
||||
self._check_for_list([lat, lng])
|
||||
else:
|
||||
# Check for string to Geocode using a provider
|
||||
provider = self.kwargs.get('provider', 'osm')
|
||||
g = geocoder.get(location, provider=provider)
|
||||
if g.ok:
|
||||
self.lat, self.lng = g.lat, g.lng
|
||||
|
||||
# Checking for List of Tuple
|
||||
elif isinstance(location, (list, tuple)):
|
||||
self._check_for_list(location)
|
||||
|
||||
# Checking for Dictionary
|
||||
elif isinstance(location, dict):
|
||||
self._check_for_dict(location)
|
||||
|
||||
# Checking for a Geocoder Class
|
||||
elif hasattr(location, 'latlng'):
|
||||
if location.latlng:
|
||||
self.lat, self.lng = location.latlng
|
||||
|
||||
# Result into Error
|
||||
else:
|
||||
raise ValueError("Unknown location: %s" % location)
|
||||
|
||||
def _check_for_list(self, location):
|
||||
# Standard LatLng list or tuple with 2 number values
|
||||
if len(location) == 2:
|
||||
lat = self._convert_float(location[0])
|
||||
lng = self._convert_float(location[1])
|
||||
condition_1 = isinstance(lat, float)
|
||||
condition_2 = isinstance(lng, float)
|
||||
|
||||
# Check if input are Floats
|
||||
if condition_1 and condition_2:
|
||||
condition_3 = -90 <= lat <= 90
|
||||
condition_4 = -180 <= lng <= 180
|
||||
|
||||
# Check if inputs are within the World Geographical
|
||||
# boundary (90,180,-90,-180)
|
||||
if condition_3 and condition_4:
|
||||
self.lat = lat
|
||||
self.lng = lng
|
||||
return self.lat, self.lng
|
||||
else:
|
||||
raise ValueError(
|
||||
"Coords are not within the world's geographical boundary")
|
||||
else:
|
||||
raise ValueError("Coordinates must be numbers")
|
||||
|
||||
def _check_for_dict(self, location):
|
||||
# Standard LatLng list or tuple with 2 number values
|
||||
if 'lat' in location and 'lng' in location:
|
||||
lat = location['lat']
|
||||
lng = location['lng']
|
||||
self._check_for_list([lat, lng])
|
||||
|
||||
if 'y' in location and 'x' in location:
|
||||
lat = location['y']
|
||||
lng = location['x']
|
||||
self._check_for_list([lat, lng])
|
||||
|
||||
@property
|
||||
def latlng(self):
|
||||
if isinstance(self.lat, float) and isinstance(self.lng, float):
|
||||
return [self.lat, self.lng]
|
||||
return []
|
||||
|
||||
@property
|
||||
def latitude(self):
|
||||
return self.lat
|
||||
|
||||
@property
|
||||
def longitude(self):
|
||||
return self.lng
|
||||
|
||||
@property
|
||||
def xy(self):
|
||||
if isinstance(self.lat, float) and isinstance(self.lng, float):
|
||||
return [self.lng, self.lat]
|
||||
return []
|
||||
|
||||
def __str__(self):
|
||||
if self.ok:
|
||||
return u'{0}, {1}'.format(self.lat, self.lng)
|
||||
return u''
|
||||
|
||||
|
||||
class BBox(object):
|
||||
"""BBox container"""
|
||||
|
||||
DEGREES_TOLERANCE = 0.5
|
||||
|
||||
@classmethod
|
||||
def factory(cls, arg):
|
||||
# validate input first
|
||||
if not isinstance(arg, (list, dict)):
|
||||
raise ValueError(
|
||||
"BBox factory only accept a dict or a list as argument")
|
||||
# we have a dict... just check which fields are given
|
||||
if isinstance(arg, dict):
|
||||
if 'southwest' in arg:
|
||||
return cls(bounds=arg)
|
||||
elif 'bbox' in arg:
|
||||
return cls(bbox=arg['bbox'])
|
||||
elif 'bounds' in arg:
|
||||
return cls(bounds=arg['bounds'])
|
||||
elif 'lat' in arg:
|
||||
return cls(lat=arg['lat'], lng=arg['lng'])
|
||||
elif 'west' in arg:
|
||||
return cls(west=arg['west'], south=arg['south'],
|
||||
east=arg['east'], north=arg['north'])
|
||||
else:
|
||||
raise ValueError(
|
||||
"Could not found valid values in dict to create a bbox")
|
||||
# we have a list... guess what to call according to the number of parameters given:
|
||||
if len(arg) == 2:
|
||||
lat, lng = arg
|
||||
return cls(lat=lat, lng=lng)
|
||||
elif len(arg) == 4:
|
||||
return cls(bbox=arg)
|
||||
else:
|
||||
raise ValueError(
|
||||
"Could not found valid values in list to create a bbox")
|
||||
|
||||
def __init__(self, bbox=None, bounds=None,
|
||||
lat=None, lng=None,
|
||||
west=None, south=None, east=None, north=None):
|
||||
if bounds is not None and bounds.get('southwest') and bounds.get('northeast'):
|
||||
self.south, self.west = map(float, bounds['southwest'])
|
||||
self.north, self.east = map(float, bounds['northeast'])
|
||||
elif bbox is not None and all(bbox):
|
||||
self.west, self.south, self.east, self.north = map(float, bbox)
|
||||
elif lat is not None and lng is not None:
|
||||
self.south = float(lat) - self.DEGREES_TOLERANCE
|
||||
self.north = float(lat) + self.DEGREES_TOLERANCE
|
||||
self.west = float(lng) - self.DEGREES_TOLERANCE
|
||||
self.east = float(lng) + self.DEGREES_TOLERANCE
|
||||
elif all([west, south, east, north]):
|
||||
self.west, self.south, self.east, self.north = map(
|
||||
float, [west, south, east, north])
|
||||
else:
|
||||
raise ValueError("Could not create BBox/Bounds from given arguments")
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return mean([self.south, self.north])
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return mean([self.west, self.east])
|
||||
|
||||
@property
|
||||
def latlng(self):
|
||||
if isinstance(self.lat, float) and isinstance(self.lng, float):
|
||||
return [self.lat, self.lng]
|
||||
return []
|
||||
|
||||
@property
|
||||
def latitude(self):
|
||||
return self.lat
|
||||
|
||||
@property
|
||||
def longitude(self):
|
||||
return self.lng
|
||||
|
||||
@property
|
||||
def xy(self):
|
||||
if isinstance(self.lat, float) and isinstance(self.lng, float):
|
||||
return [self.lng, self.lat]
|
||||
return []
|
||||
|
||||
@property
|
||||
def as_dict(self):
|
||||
return {
|
||||
'northeast': [self.north, self.east],
|
||||
'southwest': [self.south, self.west]
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
l = Location([0.0, 0.0])
|
||||
print(l.lng)
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
import json
|
||||
|
||||
from geocoder.osm import OsmResult, OsmQuery
|
||||
from geocoder.keys import locationiq_key
|
||||
|
||||
|
||||
class LocationIQResult(OsmResult):
|
||||
pass
|
||||
|
||||
|
||||
class LocationIQQuery(OsmQuery):
|
||||
provider = 'locationiq'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'https://locationiq.org/v1/search.php'
|
||||
_RESULT_CLASS = LocationIQResult
|
||||
_KEY = locationiq_key
|
||||
_KEY_MANDATORY = True
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
if 'limit' in kwargs:
|
||||
kwargs['maxRows'] = kwargs['limit']
|
||||
return {
|
||||
'key': provider_key,
|
||||
'q': location,
|
||||
'format': 'json',
|
||||
'addressdetails': 1,
|
||||
'limit': kwargs.get('maxRows', 1),
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = LocationIQQuery('Ottawa, Ontario')
|
||||
g.debug()
|
||||
g = LocationIQQuery('Ottawa, Ontario', maxRows=5)
|
||||
print(json.dumps(g.geojson, indent=4))
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from geocoder.locationiq import LocationIQQuery
|
||||
|
||||
|
||||
class LocationIQReverse(LocationIQQuery):
|
||||
provider = 'locationiq'
|
||||
method = 'reverse'
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = LocationIQReverse("45.3, -75.4")
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,151 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import mapbox_access_token
|
||||
from geocoder.location import BBox, Location
|
||||
|
||||
|
||||
class MapboxResult(OneResult):
|
||||
|
||||
def __init__(self, json_content):
|
||||
self._geometry = json_content.get('geometry', {})
|
||||
|
||||
for item in json_content.get('context', []):
|
||||
if '.' in item['id']:
|
||||
# attribute=country & text=Canada
|
||||
attribute = item['id'].split('.')[0]
|
||||
json_content[attribute] = item['text']
|
||||
|
||||
super(MapboxResult, self).__init__(json_content)
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
coord = self._geometry['coordinates']
|
||||
if coord:
|
||||
return coord[1]
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
coord = self._geometry['coordinates']
|
||||
if coord:
|
||||
return coord[0]
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.raw.get('place_name')
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self.raw.get('address')
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return ''
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.raw.get('place')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw.get('region')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw.get('country')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self.raw.get('postcode')
|
||||
|
||||
@property
|
||||
def accuracy(self):
|
||||
if self.interpolated:
|
||||
return "interpolated"
|
||||
|
||||
@property
|
||||
def quality(self):
|
||||
return self.raw.get('relevance')
|
||||
|
||||
@property
|
||||
def interpolated(self):
|
||||
return self._geometry.get('interpolated')
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
_bbox = self.raw.get('bbox')
|
||||
if _bbox:
|
||||
west = _bbox[0]
|
||||
south = _bbox[1]
|
||||
east = _bbox[2]
|
||||
north = _bbox[3]
|
||||
return self._get_bbox(south, west, north, east)
|
||||
|
||||
|
||||
class MapboxQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Mapbox Geocoding
|
||||
================
|
||||
The Mapbox Geocoding API lets you convert location text into
|
||||
geographic coordinates (1600 Pennsylvania Ave NW → -77.0366,38.8971).
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://www.mapbox.com/developers/api/geocoding/
|
||||
|
||||
Get Mapbox Access Token
|
||||
-----------------------
|
||||
https://www.mapbox.com/account
|
||||
"""
|
||||
provider = 'mapbox'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = u'https://api.mapbox.com/geocoding/v5/mapbox.places/{0}.json'
|
||||
_RESULT_CLASS = MapboxResult
|
||||
_KEY = mapbox_access_token
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
base_params = {
|
||||
'access_token': provider_key,
|
||||
'country': kwargs.get('country'),
|
||||
'types': kwargs.get('types'),
|
||||
}
|
||||
# handle proximity
|
||||
proximity = kwargs.get('proximity', None)
|
||||
if proximity is not None:
|
||||
proximity = Location(proximity)
|
||||
# do not forget to convert bbox to mapbox expectations...
|
||||
base_params['proximity'] = u'{longitude},{latitude}'.format(
|
||||
longitude=proximity.longitude,
|
||||
latitude=proximity.latitude
|
||||
)
|
||||
|
||||
bbox = kwargs.get('bbox')
|
||||
if bbox:
|
||||
bbox = BBox(bbox=bbox)
|
||||
# do not forget to convert bbox to mapbox expectations...
|
||||
base_params['bbox'] = u'{west},{south},{east},{north}'.format(
|
||||
west=bbox.west,
|
||||
east=bbox.east,
|
||||
south=bbox.south,
|
||||
north=bbox.north
|
||||
)
|
||||
|
||||
return base_params
|
||||
|
||||
def _before_initialize(self, location, **kwargs):
|
||||
self.url = self.url.format(location)
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
# extract the array of JSON objects
|
||||
return json_response.get('features', [])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = MapboxQuery("200 Queen Street", proximity=[45.3, -66.1])
|
||||
print(g.address)
|
||||
g = MapboxQuery("200 Queen Street")
|
||||
print(g.address)
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from geocoder.mapbox import MapboxResult, MapboxQuery
|
||||
from geocoder.location import Location
|
||||
|
||||
|
||||
class MapboxReverseResult(MapboxResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.address)
|
||||
|
||||
|
||||
class MapboxReverse(MapboxQuery):
|
||||
"""
|
||||
Mapbox Reverse Geocoding
|
||||
========================
|
||||
Reverse geocoding lets you reverse this process, turning a
|
||||
pair of lat/lon coordinates into a meaningful place name
|
||||
(-77.036,38.897 → 1600 Pennsylvania Ave NW).
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://www.mapbox.com/developers/api/geocoding/
|
||||
|
||||
Get Mapbox Access Token
|
||||
-----------------------
|
||||
https://www.mapbox.com/account
|
||||
"""
|
||||
provider = 'mapbox'
|
||||
method = 'reverse'
|
||||
|
||||
_URL = 'https://api.mapbox.com/geocoding/v5/mapbox.places/{lng},{lat}.json'
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'access_token': provider_key,
|
||||
'country': kwargs.get('country'),
|
||||
'types': kwargs.get('types'),
|
||||
}
|
||||
|
||||
def _before_initialize(self, location, **kwargs):
|
||||
self.location = str(Location(location))
|
||||
lat, lng = Location(location).latlng
|
||||
self.url = self.url.format(lng=lng, lat=lat)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = MapboxReverse([45.4049053, -75.7077965])
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,125 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import mapquest_key
|
||||
|
||||
from geocoder.location import BBox
|
||||
|
||||
|
||||
class MapquestResult(OneResult):
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self.raw.get('latLng', {}).get('lat')
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self.raw.get('latLng', {}).get('lng')
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self.raw.get('street')
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
if self.street:
|
||||
return self.street
|
||||
elif self.city:
|
||||
return self.city
|
||||
elif self.country:
|
||||
return self.country
|
||||
|
||||
@property
|
||||
def quality(self):
|
||||
return self.raw.get('geocodeQuality')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self.raw.get('postalCode')
|
||||
|
||||
@property
|
||||
def neighborhood(self):
|
||||
return self.raw.get('adminArea6')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.raw.get('adminArea5')
|
||||
|
||||
@property
|
||||
def county(self):
|
||||
return self.raw.get('adminArea4')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw.get('adminArea3')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw.get('adminArea1')
|
||||
|
||||
|
||||
class MapquestQuery(MultipleResultsQuery):
|
||||
"""
|
||||
MapQuest
|
||||
========
|
||||
The geocoding service enables you to take an address and get the
|
||||
associated latitude and longitude. You can also use any latitude
|
||||
and longitude pair and get the associated address. Three types of
|
||||
geocoding are offered: address, reverse, and batch.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://www.mapquestapi.com/geocoding/
|
||||
"""
|
||||
provider = 'mapquest'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'http://www.mapquestapi.com/geocoding/v1/address'
|
||||
_RESULT_CLASS = MapquestResult
|
||||
_KEY = mapquest_key
|
||||
|
||||
def _build_headers(self, provider_key, **kwargs):
|
||||
return {
|
||||
'referer': 'http://www.mapquestapi.com/geocoding/',
|
||||
'host': 'www.mapquestapi.com',
|
||||
}
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
params = {
|
||||
'key': provider_key,
|
||||
'location': location,
|
||||
'maxResults': kwargs.get("maxRows", 1),
|
||||
'outFormat': 'json',
|
||||
}
|
||||
|
||||
bbox = kwargs.get('bbox')
|
||||
if bbox:
|
||||
bbox = BBox(bbox=bbox)
|
||||
params['boundingBox'] = u'{north},{west},{south},{east}'.format(
|
||||
west=bbox.west,
|
||||
east=bbox.east,
|
||||
south=bbox.south,
|
||||
north=bbox.north
|
||||
)
|
||||
|
||||
return params
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
if b'The AppKey submitted with this request is invalid' in json_response:
|
||||
self.error = 'MapQuest API Key invalid'
|
||||
|
||||
return self.error
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
results = json_response.get('results', [])
|
||||
if results:
|
||||
return results[0]['locations']
|
||||
|
||||
return []
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = MapquestQuery('Ottawa', maxRows=3)
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,59 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from geocoder.base import MultipleResultsQuery
|
||||
from geocoder.mapquest import MapquestResult
|
||||
from geocoder.keys import mapquest_key
|
||||
|
||||
|
||||
class MapQuestBatchResult(MapquestResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.quality)
|
||||
|
||||
|
||||
class MapquestBatch(MultipleResultsQuery):
|
||||
"""
|
||||
MapQuest
|
||||
========
|
||||
The geocoding service enables you to take an address and get the
|
||||
associated latitude and longitude. You can also use any latitude
|
||||
and longitude pair and get the associated address. Three types of
|
||||
geocoding are offered: address, reverse, and batch.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://www.mapquestapi.com/geocoding/
|
||||
|
||||
"""
|
||||
provider = 'mapquest'
|
||||
method = 'batch'
|
||||
|
||||
_RESULT_CLASS = MapQuestBatchResult
|
||||
_URL = 'http://www.mapquestapi.com/geocoding/v1/batch'
|
||||
_TIMEOUT = 30
|
||||
_KEY = mapquest_key
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
self._TIMEOUT = kwargs.get('timeout', 30)
|
||||
|
||||
return {
|
||||
'key': provider_key,
|
||||
'location': location,
|
||||
'maxResults': 1,
|
||||
'outFormat': 'json',
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
results = json_response.get('results', [])
|
||||
if results:
|
||||
return [result['locations'][0] for result in results]
|
||||
|
||||
return []
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = MapquestBatch(['Denver,CO', 'Boulder,CO'])
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
from geocoder.mapquest import MapquestResult, MapquestQuery
|
||||
from geocoder.location import Location
|
||||
|
||||
|
||||
class MapQuestReverseResult(MapquestResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.quality)
|
||||
|
||||
|
||||
class MapquestReverse(MapquestQuery):
|
||||
"""
|
||||
MapQuest
|
||||
========
|
||||
The geocoding service enables you to take an address and get the
|
||||
associated latitude and longitude. You can also use any latitude
|
||||
and longitude pair and get the associated address. Three types of
|
||||
geocoding are offered: address, reverse, and batch.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
http://www.mapquestapi.com/geocoding/
|
||||
|
||||
"""
|
||||
provider = 'mapquest'
|
||||
method = 'reverse'
|
||||
|
||||
_URL = 'http://www.mapquestapi.com/geocoding/v1/reverse'
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'key': provider_key,
|
||||
'location': str(Location(location)),
|
||||
'maxResults': 1,
|
||||
'outFormat': 'json',
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
g = MapquestReverse([45.50, -76.05])
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,109 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.location import BBox
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
from geocoder.keys import mapzen_key
|
||||
|
||||
|
||||
class MapzenResult(OneResult):
|
||||
|
||||
def __init__(self, json_content):
|
||||
# create safe shortcuts
|
||||
self._geometry = json_content.get('geometry', {})
|
||||
self._properties = json_content.get('properties', {})
|
||||
|
||||
# proceed with super.__init__
|
||||
super(MapzenResult, self).__init__(json_content)
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self._geometry['coordinates'][1]
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self._geometry['coordinates'][0]
|
||||
|
||||
@property
|
||||
def bbox(self):
|
||||
return BBox.factory(self.latlng).as_dict
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self._properties.get('label')
|
||||
|
||||
@property
|
||||
def housenumber(self):
|
||||
return self._properties.get('housenumber')
|
||||
|
||||
@property
|
||||
def street(self):
|
||||
return self._properties.get('street')
|
||||
|
||||
@property
|
||||
def neighbourhood(self):
|
||||
return self._properties.get('neighbourhood')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self._properties.get('locality')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self._properties.get('region')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self._properties.get('country')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self._properties.get('postalcode')
|
||||
|
||||
@property
|
||||
def gid(self):
|
||||
return self._properties.get('gid')
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._properties.get('id')
|
||||
|
||||
|
||||
class MapzenQuery(MultipleResultsQuery):
|
||||
"""
|
||||
Mapzen REST API
|
||||
=======================
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://mapzen.com/documentation/search/search/
|
||||
"""
|
||||
provider = 'mapzen'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'https://search.mapzen.com/v1/search'
|
||||
_RESULT_CLASS = MapzenResult
|
||||
_KEY = mapzen_key
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
raise DeprecationWarning('MapZen shut down as of January 2018: https://mapzen.com/blog/shutdown')
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {
|
||||
'text': location,
|
||||
'api_key': provider_key,
|
||||
'size': kwargs.get('maxRows', 1)
|
||||
}
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return json_response['features']
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = MapzenQuery('201 Spear Street, San Francisco')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.mapzen import MapzenResult, MapzenQuery
|
||||
from geocoder.location import Location
|
||||
|
||||
|
||||
class MapzenReverseResult(MapzenResult):
|
||||
|
||||
@property
|
||||
def ok(self):
|
||||
return bool(self.address)
|
||||
|
||||
|
||||
class MapzenReverse(MapzenQuery):
|
||||
"""
|
||||
Mapzen REST API
|
||||
=======================
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://mapzen.com/documentation/search/reverse/
|
||||
"""
|
||||
provider = 'mapzen'
|
||||
method = 'reverse'
|
||||
|
||||
_URL = 'https://search.mapzen.com/v1/reverse'
|
||||
_RESULT_CLASS = MapzenReverseResult
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
location = Location(location)
|
||||
return {
|
||||
'point.lat': location.lat,
|
||||
'point.lon': location.lng,
|
||||
'size': kwargs.get('size', 1),
|
||||
'layers': kwargs.get('layers'),
|
||||
'source': kwargs.get('sources'),
|
||||
'boundary.country': kwargs.get('country'),
|
||||
'api_key': provider_key
|
||||
}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = MapzenReverse("45.4049053 -75.7077965", key='search-un1M9Hk')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
|
@ -0,0 +1,140 @@
|
|||
#!/usr/bin/python
|
||||
# coding: utf8
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
|
||||
from geocoder.base import OneResult, MultipleResultsQuery
|
||||
|
||||
|
||||
class MaxmindResults(OneResult):
|
||||
|
||||
def __init__(self, json_content):
|
||||
# create safe shortcuts
|
||||
self._location = json_content.get('location', {})
|
||||
self._traits = json_content.get('traits', {})
|
||||
|
||||
# proceed with super.__init__
|
||||
super(MaxmindResults, self).__init__(json_content)
|
||||
|
||||
@property
|
||||
def lat(self):
|
||||
return self._location.get('latitude')
|
||||
|
||||
@property
|
||||
def lng(self):
|
||||
return self._location.get('longitude')
|
||||
|
||||
@property
|
||||
def timezone(self):
|
||||
return self._location.get('time_zone')
|
||||
|
||||
@property
|
||||
def metro_code(self):
|
||||
return self._location.get('metro_code')
|
||||
|
||||
@property
|
||||
def domain(self):
|
||||
return self._traits.get('domain')
|
||||
|
||||
@property
|
||||
def isp(self):
|
||||
return self._traits.get('isp')
|
||||
|
||||
@property
|
||||
def organization(self):
|
||||
return self._traits.get('organization')
|
||||
|
||||
@property
|
||||
def ip(self):
|
||||
return self._traits.get('ip_address')
|
||||
|
||||
@property
|
||||
def postal(self):
|
||||
return self.raw.get('postal', {}).get('code')
|
||||
|
||||
@property
|
||||
def city(self):
|
||||
return self.raw.get('city', {}).get('names', {}).get('en')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self.raw.get('subdivision', {}).get('names', {}).get('en')
|
||||
|
||||
@property
|
||||
def country(self):
|
||||
return self.raw.get('country', {}).get('names', {}).get('en')
|
||||
|
||||
@property
|
||||
def country_code(self):
|
||||
return self.raw.get('country', {}).get('iso_code')
|
||||
|
||||
@property
|
||||
def continent(self):
|
||||
return self.raw.get('continent', {}).get('names', {}).get('en')
|
||||
|
||||
@property
|
||||
def continent_code(self):
|
||||
return self.raw.get('continent', {}).get('code')
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
if self.city:
|
||||
return u'{0}, {1}, {2}'.format(self.city, self.state, self.country)
|
||||
elif self.state:
|
||||
return u'{0}, {1}'.format(self.state, self.country)
|
||||
elif self.country:
|
||||
return u'{0}'.format(self.country)
|
||||
else:
|
||||
return u''
|
||||
|
||||
|
||||
class MaxmindQuery(MultipleResultsQuery):
|
||||
"""
|
||||
MaxMind's GeoIP2
|
||||
=======================
|
||||
MaxMind's GeoIP2 products enable you to identify the location,
|
||||
organization, connection speed, and user type of your Internet
|
||||
visitors. The GeoIP2 databases are among the most popular and
|
||||
accurate IP geolocation databases available.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
https://www.maxmind.com/en/geolocation_landing
|
||||
"""
|
||||
provider = 'maxmind'
|
||||
method = 'geocode'
|
||||
|
||||
_URL = 'https://www.maxmind.com/geoip/v2.0/city_isp_org/{0}'
|
||||
_RESULT_CLASS = MaxmindResults
|
||||
_KEY_MANDATORY = False
|
||||
|
||||
def _build_headers(self, provider_key, **kwargs):
|
||||
return {
|
||||
'Referer': 'https://www.maxmind.com/en/geoip_demo',
|
||||
'Host': 'www.maxmind.com',
|
||||
}
|
||||
|
||||
def _build_params(self, location, provider_key, **kwargs):
|
||||
return {'demo': 1}
|
||||
|
||||
def _before_initialize(self, location, **kwargs):
|
||||
location = location or 'me'
|
||||
self.url = self._URL.format(location)
|
||||
|
||||
def _catch_errors(self, json_response):
|
||||
error = json_response.get('error')
|
||||
if error:
|
||||
self.error = json_response.get('code')
|
||||
|
||||
return self.error
|
||||
|
||||
def _adapt_results(self, json_response):
|
||||
return [json_response]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
g = MaxmindQuery('8.8.8.8')
|
||||
g.debug()
|
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\stacy\Downloads\geocoder-1.38.1.tar.gz
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue