Żądania HTTP i parsowanie JSON w Pythonie

202

Chcę dynamicznie wyszukiwać w Mapach Google za pośrednictwem interfejsu API Google Directions. Na przykład to żądanie oblicza trasę z Chicago, IL do Los Angeles, Kalifornia przez dwa punkty trasy w Joplin, MO i 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

Zwraca wynik w formacie JSON .

Jak mogę to zrobić w Pythonie? Chcę wysłać takie żądanie, otrzymać wynik i przeanalizować go.

Bieg
źródło

Odpowiedzi:

348

Polecam korzystanie z niesamowitej biblioteki żądań :

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

Treść odpowiedzi JSON: https://requests.readthedocs.io/en/master/user/quickstart/#json-response-content

zeekay
źródło
2
Dla mnie musiałem zrobić json=paramszamiast params=paramslub pojawia się błąd 500.
demongolem
140

requestsModuł Pythona dba zarówno pobierania danych JSON i dekodowania go, ze względu na wbudowany dekoder JSON. Oto przykład zaczerpnięty z dokumentacji modułu :

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

Nie ma więc potrzeby używania osobnego modułu do dekodowania JSON.

linkyndy
źródło
4
Jeśli chcesz być kompatybilny z żądaniami 0.x (wheezy Debiana), powinieneś użyć json.load()lub json.loads()zamiast tego, jak w 0.x, jsonjest raczej właściwością niż funkcją.
nyuszika7h,
2
@nyuszika Jeśli używasz Debiana, jeśli to możliwe, użyj pip, aby uzyskać nowsze biblioteki Pythona. Nie chcesz kodować ze starymi bibliotekami Pythona, chyba że istnieje ważny powód, aby użyć tego, co debian ma w repozytoriach apt.
SHernandez,
@SHernandez To jest poprawny punkt, ale niektóre pakiety mogą zależeć od pakietu python-requests(lub python3-requests), więc będziesz musiał zainstalować gdzieś indziej, /usr/localaby uniknąć uszkodzenia tych pakietów. Z drugiej strony, gdy przenośność / kompatybilność jest banalna, moim zdaniem warto.
nyuszika7h
3
Jak wyodrębnić tylko określoną parę nazwa-wartość z odpowiedzi JSON „r”?
3lokh
1
W r.json()(z mojej odpowiedzi) masz właściwą odpowiedź, dekodowaną w JSON. Możesz uzyskać do niego dostęp jak normalny list/ dict; print r.json()żeby zobaczyć jak to wygląda. Lub zapoznaj się z dokumentacją API usługi, o którą poprosiłeś.
linkyndy,
37

requestsma wbudowaną .json()metodę

import requests
requests.get(url).json()
maow
źródło
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
źródło
3
Dziękujemy za pomoc, należy jednak pamiętać, że: Funkcja urllib.urlopen () została usunięta w Pythonie 3.0 na korzyść urllib2.urlopen ().
Arun,
2
Arun, tak, ale nie ma już nazwy urllib2
Corey Goldberg,
3
Jest urllib.requestw Pythonie 3.
nyuszika7h
To nie działa. json.loads daje „TypeError: obiekt JSON musi być str, a nie„ HTTPResponse ””, a json.load daje „TypeError: obiekt JSON musi być str, a nie„ bajty ””
M Hornbacher
16

Skorzystaj z biblioteki żądań, ładnie wydrukuj wyniki, aby lepiej zlokalizować klucze / wartości, które chcesz wyodrębnić, a następnie użyj zagnieżdżonej pętli do analizy danych. W przykładzie wyodrębniam wskazówki dojazdu krok po kroku.

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
źródło
Michael, jak mogę to zrozumieć, kiedy otrzymam dane? Jak wyświetlić go w „klasycznym” formacie wizualnym Json (takim jak ten, który otrzymujesz w przeglądarce)? Oto, co otrzymuję w swoim terminalu: [link] s13.postimg.org/3r55jajk7/terminal.png
Alexander Starbuck
3
@AlexStarbuck import pprintnastępnie ->pprint.pprint(step['html_instructions'])
Michael
7

Spróbuj tego:

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
źródło
1
żądania mają swoją własną funkcję json
LilaQ
0

Również dla ładnego Jsona na konsoli:

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

możliwe użycie zrzutów z wcięciem. (Proszę zaimportować json )

użytkownik5510975
źródło