如何使用Python、JSON和谷歌地图在服务器端进行反向地理编码?
我正在尝试服务器端的反向地理编码,想要获取一个json格式的响应,现在我想从这个json响应中提取2到3个变量:
我想解析这些数据,最后得到比如说:
administrative_area_level_1 = 'Stockholm'
jsondata = json.load(urllib2.urlopen('http://maps.googleapis.com/maps/api/geocode/json?latlng=59.3,18.1&sensor=false'))
这是我用来获取json的python代码,现在我想知道怎么解析它,以便只获取:
- administrative_area_level_1 的长名称(也就是州或地区的名称)
- locality 的长名称(也就是城市的名称)
- 如何解析我的json的理解
我可以解析它,但有时候并不总是返回 administrative_area_1:
jsondata["results"][0]["address_components"][5]["long_name"]
上面的代码在纽约的某个点正确输出了“New York”,但在斯德哥尔摩却输出了一个邮政城市的名称,比如Johanneshow,这并不是administrative_area_1(地区/州)。那么怎么才能确保这个函数总是返回administrative_area_1,最好是不用循环呢?
我希望它能像下面这样直接访问国家、地区和城市:
logging.info("country:"+str(jsondata["results"][9]["formatted_address"]))
logging.info("administrative_area_level_1:"+str(jsondata["results"][8]["formatted_address"]))
logging.info("locality:"+str(jsondata["results"][8]["formatted_address"]))
提前谢谢你
更新
这里有一个很好的答案,得到了我期待的结果。在等待答案的同时,我也尝试自己实现一个解决方案,似乎可以做到:
jsondata = json.load(urllib2.urlopen('http://maps.googleapis.com/maps/api/geocode/json?latlng='+str(ad.geopt.lat)+','+str(ad.geopt.lon)+'&sensor=false'))
logging.info("geography:"+str(jsondata["results"][1]["formatted_address"]))
region = None
city = None
for result in jsondata["results"]:
#logging.info("result:"+str(result))
for component in result["address_components"]:
logging.info("components:"+str(component))
logging.info("components type:"+str(component["types"]))
if 'administrative_area_level_1' in component["types"]:
#logging.info(unicode('found admin area:%s' % component["long_name"]))
region = component["long_name"]
if 'locality' in component["types"]:
logging.info("found locality:"+str(component["long_name"]))
city = component["long_name"]
1 个回答
处理响应
其实不需要解析JSON,因为它已经被json.load()
处理过了,并且以Python的数据结构返回。你可以把它当作简单的字典来使用,里面可以包含列表或其他字典。
访问响应中需要的部分
要访问你需要的数据,可以使用以下代码:
jsondata['results'][0]['address_components']
这里面包含了所有地名信息:
[{u'long_name': u'S\xf6dra L\xe4nken', u'types': [u'route'], u'short_name': u'S\xf6dra L\xe4nken'}, {u'long_name': u'Stockholm', u'types': [u'locality', u'political'], u'short_name': u'Stockholm'}, {u'long_name': u'Stockholm', u'types': [u'administrative_area_level_1', u'political'], u'short_name': u'Stockholm'}, {u'long_name': u'Sweden', u'types': [u'country', u'political'], u'short_name': u'SE'}, {u'long_name': u'12146', u'types': [u'postal_code'], u'short_name': u'12146'}, {u'long_name': u'Johanneshov', u'types': [u'postal_town'], u'short_name': u'Johanneshov'}]
筛选你需要的数据
如你所见,有很多数据其实是你不需要的,但你只想要locality
和administrative_area_level_1
的信息。你可以使用filter()
这个Python函数来筛选数据,像这样:
>>> mydata = jsondata['results'][0]['address_components']
>>> types = ['locality', 'administrative_area_level_1']
>>> geonames = filter(lambda x: len(set(x['types']).intersection(types)), mydata)
基本上,你只会得到那些在"types"列表中包含'locality'或'administrative_area_level_1'的元素。经过上面的操作,geonames
将会是一个包含你需要的字典的列表:
[{u'long_name': u'Stockholm', u'types': [u'locality', u'political'], u'short_name': u'Stockholm'}, {u'long_name': u'Stockholm', u'types': [u'administrative_area_level_1', u'political'], u'short_name': u'Stockholm'}]
展示数据
要显示这些名字,你可以例如遍历它们,展示long_name
和对应的types
值:
>>> for geoname in geonames:
common_types = set(geoname['types']).intersection(set(types))
print '{} ({})'.format(geoname['long_name'], str(', '.join(common_types)))
Stockholm (locality)
Stockholm (administrative_area_level_1)
这就是你期待的结果吗?
完整代码
代码可能看起来像这样:
import json
import urllib2
def get_geonames(lat, lng, types):
url = 'http://maps.googleapis.com/maps/api/geocode/json' + \
'?latlng={},{}&sensor=false'.format(lat, lng)
jsondata = json.load(urllib2.urlopen(url))
address_comps = jsondata['results'][0]['address_components']
filter_method = lambda x: len(set(x['types']).intersection(types))
return filter(filter_method, address_comps)
lat, lng = 59.3, 18.1
types = ['locality', 'administrative_area_level_1']
# Display all geographical names along with their types
for geoname in get_geonames(lat, lng, types):
common_types = set(geoname['types']).intersection(set(types))
print '{} ({})'.format(geoname['long_name'], ', '.join(common_types))