Как поменять местами геокодирование с помощью карт python, json и google? - PullRequest
6 голосов
/ 06 декабря 2011

Я пытаюсь использовать обратное геокодирование на стороне сервера, которое может дать мне ответ json, и теперь я хочу получить 2 или 3 переменные из ответа json:

Я хотел бы, например, проанализировать эти данные и закончить, например,. 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'))

Вот мой код на python, который выбирает json, теперь мне интересно, как разобрать его, чтобы получить только

  • administrator_area_level_1 длинное имя (т. Е. Название штата или региона)
  • название населенного пункта (т.е. название города)
  • понимание, как разобрать мой JSON

Я могу разобрать, но это не всегда так выглядит как administrator_area_1:

jsondata["results"][0]["address_components"][5]["long_name"]

В строке выше правильно выводится «Нью-Йорк» для точки в Нью-Йорке, но для Стокгольма выводится почтовый город, то есть Йоханнесшоу, который не является adminraive_area_1 (регион / штат). Так как же гарантировать, что функция всегда возвращает административное_решение_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 Ответ

13 голосов
/ 06 декабря 2011

Обработка ответа

Нет необходимости анализировать 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'hort_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)

В основном вы получаете только элементы, которые имеют 'locality' или 'administrator_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 s и соответствующие 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))
...