Skip to content

Instantly share code, notes, and snippets.

@mimosa
Created June 4, 2014 06:44
Show Gist options
  • Save mimosa/d70c6af1f69e686106ca to your computer and use it in GitHub Desktop.
Save mimosa/d70c6af1f69e686106ca to your computer and use it in GitHub Desktop.
# -*- encoding: utf-8 -*-
require 'addressable/uri'
require 'digest/md5'
require 'resolv'
require 'excon'
require 'cgi'
require 'oj'
module Baidu
class Geocoder
attr_accessor :ak, :sk, :gateway_url
def initialize(ak = 'l7Y2LLRC4I14GCjR8lqtLIoB', sk = 'SamojXhRdUQPjvl9SfPyGf8gdB0xwGC9')
self.ak = ak
self.sk = sk
self.gateway_url = 'http://api.map.baidu.com'
end
def lookup(opts)
if opts.is_a?(Hash) && ( opts.has_key?(:address) || opts.has_key?(:ip) || (opts.has_key?(:lat) && opts.has_key?(:lng)) )
case
when opts.has_key?(:lat) && opts.has_key?(:lng)
geo_location(opts[:lat], opts[:lng])
when opts.has_key?(:ip) && ip?(opts[:ip])
geo_ip(opts[:ip])
when opts.has_key?(:address)
geo_address(opts[:address])
end
else
puts '请包含参数::address, :ip, :lat, :lng'
puts '_'*88
return nil
end
end
def geo_address(address)
path = '/geocoder'
params = { key: self.ak, output: 'json', address: address }
json = get_json( path, params )
if json && json['status'] == 'OK' && !json['result'].empty?
loc = json['result']['location']
geo_location(loc['lat'], loc['lng'])
end
end
def geo_ip(ip)
path = '/location/ip'
params = { ak: self.ak, ip: ip, coor: 'bd09ll' }
uri = uri_parse( self.gateway_url + path, params)
# 百度签名
params[:sn] = sign(uri)
json = get_json( path, params )
if json && json['status'] == 0
loc = json['content']['point']
geo_location(loc['y'], loc['x'])
end
end
def geo_location(lat, lng)
path = '/geocoder'
params = { key: self.ak, output: 'json', location: [lat, lng].join(',') }
json = get_json( path, params )
result = {}
if json && json['status'] == 'OK' && !json['result'].empty?
json = json['result']
result[:address] = json['formatted_address'] # 地址
address = json['addressComponent'] # 行政区域解析
result.merge!({
street_number: address['street_number'],
street: address['street'],
district: address['district'],
city: address['city'],
region: address['province'],
country: '中国'
})
location = json['location'] # 坐标
result.merge!({
latitude: location['lat'],
longitude: location['lng']
})
end
result
end
private
def client
@conn ||= ::Excon.new('http://api.map.baidu.com', connect_timeout: 60)
end
def get_json(path, params)
req = client.get(path: path, query: params)
if req.status == 200
return ::Oj.load(req.body) rescue nil
end
nil
end
def sign(uri)
salt = urlencode("#{uri.path}?#{uri.query}#{self.sk}")
return md5(salt)
end
def urlencode(str)
::CGI.escape(str)
end
def md5(str)
::Digest::MD5.hexdigest(str)
end
def uri_parse(url, params={})
uri = ::Addressable::URI.parse(url)
uri.query_values = params
return uri
end
def ip?(str)
case str
when ::Resolv::IPv4::Regex
return true
when ::Resolv::IPv6::Regex
puts '不支持IPv6'
puts '_'*88
end
false
end
end
end
geocoder = Baidu::Geocoder.new

geocoder.lookup(ip: '221.131.192.80')

geocoder.lookup(address: '杭州长江南路336')

geocoder.lookup(lng: 120.208955, lat: 30.16512)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment