Solicitações HTTP e análise JSON em Python

202

Desejo consultar dinamicamente o Google Maps por meio da API do Google Directions. Como exemplo, esta solicitação calcula a rota de Chicago, IL para Los Angeles, CA através de dois pontos de referência em Joplin, MO e 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

Retorna um resultado no formato JSON .

Como posso fazer isso em Python? Quero enviar uma solicitação, receber o resultado e analisá-lo.

Uma corrida
fonte

Respostas:

348

Eu recomendo usar a impressionante biblioteca de solicitações :

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

Conteúdo de resposta JSON: https://requests.readthedocs.io/en/master/user/quickstart/#json-response-content

zeekay
fonte
2
Para mim, eu precisava fazer em json=paramsvez de, params=paramsou recebo um erro 500.
Demongolem
140

O requestsmódulo Python cuida da recuperação e decodificação dos dados JSON, devido ao seu decodificador JSON interno. Aqui está um exemplo retirado da documentação do 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/...

Portanto, não há necessidade de usar algum módulo separado para decodificar JSON.

linkyndy
fonte
4
Se você precisa ser compatível com as solicitações 0.x (Debian wheezy), você deve usar json.load()ou json.loads(), como em 0.x, jsoné uma propriedade e não uma função.
precisa saber é o seguinte
2
@nyuszika Se você estiver usando o debian, se possível, use o pip para obter novas bibliotecas python. Você não deseja codificar com bibliotecas python antigas, a menos que haja um motivo importante para usar o que o debian possui nos repositórios do apt.
SHernandez
@SHernandez Esse é um ponto válido, mas alguns pacotes podem depender do pacote python-requests(ou python3-requests), portanto, você precisará instalar em outro lugar /usr/localpara evitar a quebra desses pacotes. Por outro lado, quando a portabilidade / compatibilidade é trivial, na minha opinião vale a pena.
nyuszika7h
3
Como extrair apenas um par nome-valor específico da resposta json 'r'?
3lokh
1
Em r.json()(da minha resposta) você tem a resposta real, decodificada por JSON. Você pode acessá-lo como um normal list/ dict; print r.json()para ver como é. Ou consulte os documentos da API do serviço para o qual você fez a solicitação.
precisa saber é
37

requestspossui .json()método embutido

import requests
requests.get(url).json()
maow
fonte
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
fonte
3
Obrigado por sua ajuda, no entanto, o seguinte deve ser observado: A função urllib.urlopen () foi removida no Python 3.0 em favor de urllib2.urlopen ().
Arun
2
Arun, sim, mas ele não é mais chamado urllib2
Corey Goldberg
3
É urllib.requestem Python 3.
nyuszika7h
Não funciona. json.loads fornece 'TypeError: o objeto JSON deve ser str, não' HTTPResponse '' e json.loads fornece 'TypeError: o objeto JSON deve ser str, não' bytes ''
M Hornbacher
16

Use a biblioteca de solicitações, imprima os resultados para localizar melhor as chaves / valores que deseja extrair e use aninhados para loops para analisar os dados. No exemplo, extraio instruções de direção passo a passo.

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']
Michael
fonte
Michael, como posso entender isso depois de obter os dados? Como exibi-lo no formato visual json "clássico" (como o que você obtém no seu navegador)? Aqui está o que eu recebo no meu terminal: [link] s13.postimg.org/3r55jajk7/terminal.png
Alexander Starbuck
3
@AlexStarbuck import pprintthen ->pprint.pprint(step['html_instructions'])
Michael
7

Tente o seguinte:

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
fonte
1
pedidos tem sua própria função json
LilaQ
0

Também para o Json bonito no console:

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

possível usar dumps com recuo. ( Importe json )

user5510975
fonte