Żą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.

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


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.


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,


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))

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, 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))

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 )

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.