lab_weather/geocoder/baidu.py

136 lines
3.7 KiB
Python

#!/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()