Solicitudes HTTP y análisis JSON en Python

202

Quiero consultar dinámicamente Google Maps a través de la API de Google Directions. Como ejemplo, esta solicitud calcula la ruta desde Chicago, IL a Los Ángeles, CA a través de dos puntos de referencia en Joplin, MO y Oklahoma City, OK:

http://maps.googleapis.com/maps/api/directions/json?origin=Chicago,IL&destination=Los+Angeles,CA&waypoints=Joplin,MO|Oklahoma+City,OK&sensor=false

Devuelve un resultado en el formato JSON .

¿Cómo puedo hacer esto en Python? Quiero enviar dicha solicitud, recibir el resultado y analizarlo.

Arun
fuente

Respuestas:

348

Recomiendo usar la impresionante biblioteca de solicitudes :

import requests

url = 'http://maps.googleapis.com/maps/api/directions/json'

params = dict(
    origin='Chicago,IL',
    destination='Los+Angeles,CA',
    waypoints='Joplin,MO|Oklahoma+City,OK',
    sensor='false'
)

resp = requests.get(url=url, params=params)
data = resp.json() # Check the JSON Response Content documentation below

Contenido de respuesta JSON: https://requests.readthedocs.io/en/master/user/quickstart/#json-response-content

zeekay
fuente
2
Para mí, tenía que hacer en json=paramslugar de params=paramsu obtengo un error 500.
demongolem
140

El requestsmódulo Python se encarga tanto de recuperar datos JSON como de decodificarlos, debido a su decodificador JSON incorporado. Aquí hay un ejemplo tomado de la documentación del módulo :

>>> import requests
>>> r = requests.get('https://github.com/timeline.json')
>>> r.json()
[{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...

Por lo tanto, no tiene sentido usar un módulo separado para decodificar JSON.

linkyndy
fuente
44
Si necesita ser compatible con las solicitudes 0.x (Debian wheezy), debe usar json.load()o json.loads(), como en 0.x, jsones una propiedad en lugar de una función.
nyuszika7h
2
@nyuszika Si está utilizando Debian, si es posible, use pip para obtener nuevas bibliotecas de Python. No desea codificar con bibliotecas antiguas de Python, a menos que haya una razón importante para usar lo que Debian tiene en los repositorios apt.
SHernandez
@SHernandez Ese es un punto válido, pero algunos paquetes pueden depender del python-requests(o python3-requests) paquete, por lo que deberá instalarlo en otro lugar que /usr/localno sea romper esos paquetes. Por otro lado, cuando la portabilidad / compatibilidad es trivial, en mi opinión, vale la pena.
nyuszika7h
3
¿Cómo extraer solo un par nombre-valor particular de la respuesta json 'r'?
3lokh
1
En r.json()(de mi respuesta) tienes la respuesta real, decodificada por JSON. Puedes acceder a él como un normal list/ dict; print r.json()para ver cómo se ve. O consulte los documentos de la API del servicio que solicitó.
linkyndy
37

requeststiene un .json()método incorporado

import requests
requests.get(url).json()
maow
fuente
25
import urllib
import json

url = 'http://maps.googleapis.com/maps/api/directions/json?origin=Chicago,IL&destination=Los+Angeles,CA&waypoints=Joplin,MO|Oklahoma+City,OK&sensor=false'
result = json.load(urllib.urlopen(url))
clyfish
fuente
3
Gracias por su ayuda, sin embargo, se debe tener en cuenta lo siguiente: La función urllib.urlopen () se ha eliminado en Python 3.0 a favor de urllib2.urlopen ().
Arun
2
Arun, sí, pero ya no se llama urllib2
Corey Goldberg
3
Está urllib.requesten Python 3.
nyuszika7h
No funciona. json.loads da 'TypeError: el objeto JSON debe ser str, no' HTTPResponse '' y json.load da 'TypeError: el objeto JSON debe ser str, no' bytes '
M Hornbacher
16

Use la biblioteca de solicitudes, imprima los resultados de manera bonita para que pueda localizar mejor las claves / valores que desea extraer, y luego use anidados para bucles para analizar los datos. En el ejemplo extraigo instrucciones de manejo paso a paso.

import json, requests, pprint

url = 'http://maps.googleapis.com/maps/api/directions/json?'

params = dict(
    origin='Chicago,IL',
    destination='Los+Angeles,CA',
    waypoints='Joplin,MO|Oklahoma+City,OK',
    sensor='false'
)


data = requests.get(url=url, params=params)
binary = data.content
output = json.loads(binary)

# test to see if the request was valid
#print output['status']

# output all of the results
#pprint.pprint(output)

# step-by-step directions
for route in output['routes']:
        for leg in route['legs']:
            for step in leg['steps']:
                print step['html_instructions']
Miguel
fuente
Michael, ¿cómo puedo entender esto una vez que obtuve los datos? ¿Cómo lo visualizo en formato visual "clásico" json (como el que obtienes en tu navegador)? Esto es lo que obtengo en mi terminal: [link] s13.postimg.org/3r55jajk7/terminal.png
Alexander Starbuck
3
@AlexStarbuck import pprintentonces ->pprint.pprint(step['html_instructions'])
Michael
7

Prueba esto:

import requests
import json

# Goole Maps API.
link = 'http://maps.googleapis.com/maps/api/directions/json?origin=Chicago,IL&destination=Los+Angeles,CA&waypoints=Joplin,MO|Oklahoma+City,OK&sensor=false'

# Request data from link as 'str'
data = requests.get(link).text

# convert 'str' to Json
data = json.loads(data)

# Now you can access Json 
for i in data['routes'][0]['legs'][0]['steps']:
    lattitude = i['start_location']['lat']
    longitude = i['start_location']['lng']
    print('{}, {}'.format(lattitude, longitude))
Raghav Gupta
fuente
1
request tiene su propia función json
LilaQ
0

También para la bonita Json en consola:

 json.dumps(response.json(), indent=2)

posible usar volcados con sangría. ( Importa json )

usuario5510975
fuente