Ваш код отлично работает в Python 2. Вам просто нужно разобрать строку JSON, возвращаемый API с использованием json.loads(jsongeocode)
.
Сообщение об ошибке TypeError: The JSON Object must be str, not 'bytes'
подсказывает мне, что вы используете Python 3. Однако вы импортируете модуль urllib2
, который присутствует только в Python 2. Я не уверен, как вы это достигли. В любом случае, если предположить, что Python 3:
import json
from urllib.request import urlopen
address="1600+Amphitheatre+Parkway,+Mountain+View,+CA"
url="https://maps.googleapis.com/maps/api/geocode/json?address=%s" % address
response = urlopen(url)
json_byte_string = response.read()
>>> type(json_byte_string)
<class 'bytes'>
>>> jdata = json.loads(json_byte_string)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python3.4/json/__init__.py", line 312, in loads
s.__class__.__name__))
TypeError: the JSON object must be str, not 'bytes'
Таким образом, существует исключение, которое вы видели. Ответ, содержащийся в json_byte_string
, является байтовой строкой - он имеет класс bytes
, однако в Python 3 json.loads()
ожидает str
, который является строкой Unicode. Поэтому вам нужно преобразовать json_byte_string
из строки байта в Unicode. Для этого требуется, чтобы вы знали кодировку строки байта.Здесь я использую UTF8, потому что это то, что было указано в заголовке Content-Type
ответа:
>>> response.headers['Content-Type']
'application/json; charset=UTF-8'
>>> json_string = str(json_byte_string, 'utf8')
>>> type(json_string)
<class 'str'>
Теперь он может быть передан в json.loads()
:
>>> jdata = json.loads(json_string)
>>> jdata
{'results': [{'types': ['street_address'], 'address_components': [{'types': ['street_number'], 'long_name': '1600', 'short_name': '1600'}, {'types': ['route'], 'long_name': 'Amphitheatre Parkway', 'short_name': 'Amphitheatre Pkwy'}, {'types': ['locality', 'political'], 'long_name': 'Mountain View', 'short_name': 'Mountain View'}, {'types': ['administrative_area_level_2', 'political'], 'long_name': 'Santa Clara County', 'short_name': 'Santa Clara County'}, {'types': ['administrative_area_level_1', 'political'], 'long_name': 'California', 'short_name': 'CA'}, {'types': ['country', 'political'], 'long_name': 'United States', 'short_name': 'US'}, {'types': ['postal_code'], 'long_name': '94043', 'short_name': '94043'}], 'formatted_address': '1600 Amphitheatre Parkway, Mountain View, CA 94043, USA', 'geometry': {'location_type': 'ROOFTOP', 'viewport': {'northeast': {'lng': -122.0828811197085, 'lat': 37.4236854802915}, 'southwest': {'lng': -122.0855790802915, 'lat': 37.4209875197085}}, 'location': {'lng': -122.0842301, 'lat': 37.4223365}}, 'place_id': 'ChIJ2eUgeAK6j4ARbn5u_wAGqWA'}], 'status': 'OK'}
И у вас есть декодированный JSON строка в качестве словаря. Отформатированный адрес доступен как:
>>> jdata['results'][0]['formatted_address']
'1600 Amphitheatre Parkway, Mountain View, CA 94043, USA'
Существует лучший способ сделать это: использовать requests
:
import requests
address="1600+Amphitheatre+Parkway,+Mountain+View,+CA"
url="https://maps.googleapis.com/maps/api/geocode/json?address=%s" % address
r = requests.get(url)
jdata = r.json()
>>> jdata['results'][0]['formatted_address']
'1600 Amphitheatre Parkway, Mountain View, CA 94043, USA'
Намного лучше!
Все еще не работает. Я думаю, что 'json.loads()' является правильным вызовом функции, но я получаю ту же ошибку. – JuiCe
Я ПРИНИМАЮ, ЧТО НАЗАД! Это другая ошибка. Я обновлю свой вопрос – JuiCe
, вам нужно будет преобразовать его в строку раньше, см. Обновление. – Geotob