Python urllib2: Odbierz odpowiedź JSON z adresu url

90

Próbuję uzyskać adres URL za pomocą Pythona, a odpowiedź to JSON. Jednak kiedy biegnę

import urllib2
response = urllib2.urlopen('https://api.instagram.com/v1/tags/pizza/media/XXXXXX')
html=response.read()
print html

HTML jest typu str i oczekuję JSON. Czy istnieje sposób, w jaki mogę przechwycić odpowiedź jako JSON lub słownik Pythona zamiast str.

Deepak B
źródło
1
Czy response.read()zwraca prawidłowy ciąg JSON?
Martijn Pieters
Tak, to prawidłowy ciąg JSON, po prostu lub wpisz str, a nie dykt
Deepak B
Jeśli jest to reprezentacja ciągu w formacie JSON, a nie reprezentacja obiektu w formacie JSON (dict), nie można zmusić serwera do zwrócenia innych danych; prawdopodobnie musisz zgłosić inną prośbę. Jeśli chodzi tylko o to, że nie wiesz, jak przeanalizować reprezentację JSON w równoważny obiekt Pythona, odpowiedź Martjina Pietersa jest poprawna.
abarnert

Odpowiedzi:

183

Jeśli adres URL zwraca prawidłowe dane zakodowane w formacie JSON, użyj jsonbiblioteki, aby zdekodować:

import urllib2
import json

response = urllib2.urlopen('https://api.instagram.com/v1/tags/pizza/media/XXXXXX')
data = json.load(response)   
print data
Martijn Pieters
źródło
1
@ ManuelSchneid3r: Odpowiedź jest dla Pythona 2, gdzie czytanie z responsedaje ci bajty i json.load()oczekuje , że odczytasz bajtest. JSON musi być zakodowany przy użyciu kodeka UTF, a powyższe działa dla UTF-8, UTF-16 i UTF-32, pod warunkiem, że kodek BOM jest dołączony dla dwóch ostatnich kodeków. Odpowiedź, do której podajesz łącze, zakłada, że ​​użyto UTF-8, co zwykle jest poprawne, ponieważ jest to ustawienie domyślne. Począwszy od Pythona 3.6, jsonbiblioteka automatycznie dekoduje kody bajtowe z danymi JSON, pod warunkiem, że używane jest kodowanie UTF.
Martijn Pieters
@ ManuelSchneid3r: W przeciwnym razie zalecałbym korzystanie z requestsbiblioteki, która również automatycznie wykrywa prawidłowy kodek UTF do użycia w przypadkach, gdy brakuje BOM i nie określono zestawu znaków w nagłówku odpowiedzi. Po prostu użyj response.json()metody.
Martijn Pieters
35
import json
import urllib

url = 'http://example.com/file.json'
r = urllib.request.urlopen(url)
data = json.loads(r.read().decode(r.info().get_param('charset') or 'utf-8'))
print(data)

urllib , dla Pythona 3.4
HTTPMessage , zwracane przez r.info ()

SanalBathery
źródło
1
Solidny kod inny niż print dataniepoprawny dla Pythona 3. Powinien być print(data).
David Metcalfe
1
Tak, a linia 2 powinna być import urllib.request. Ponadto ten plik .json w adresie URL już nie istnieje.
hack-tramp
5
"""
Return JSON to webpage
Adding to wonderful answer by @Sanal
For Django 3.4
Adding a working url that returns a json (Source: http://www.jsontest.com/#echo)
"""

import json
import urllib

url = 'http://echo.jsontest.com/insert-key-here/insert-value-here/key/value'
respons = urllib.request.urlopen(url)
data = json.loads(respons.read().decode(respons.info().get_param('charset') or 'utf-8'))
return HttpResponse(json.dumps(data), content_type="application/json")
szop pracz
źródło
1
uff, ten json.dumps () uratował mi dzień.
Lloyd,
W przypadku Django 1.7 +, możesz użyć JsonResponse bezpośrednio w następujący sposób from django.http import JsonResponse return JsonResponse({'key':'value'})
szop
1
Robiłem json.dump () zamiast json.dumps (), czując się głupio. Dzięki za zapisanie!
Hashir Baig
4

Uważaj na walidację itp., Ale proste rozwiązanie jest następujące:

import json
the_dict = json.load(response)
MostafaR
źródło
2
resource_url = 'http://localhost:8080/service/'
response = json.loads(urllib2.urlopen(resource_url).read())
Jossef Harush
źródło
1

Jedna linijka biblioteki standardowej Python 3:

load(urlopen(url))

# imports (place these above the code before running it)
from json import load
from urllib.request import urlopen
url = 'https://jsonplaceholder.typicode.com/todos/1'
Adam
źródło
0

Chociaż wydaje mi się, że już odpowiedział, chciałbym dodać do tego mój mały fragment

import json
import urllib2
class Website(object):
    def __init__(self,name):
        self.name = name 
    def dump(self):
     self.data= urllib2.urlopen(self.name)
     return self.data

    def convJSON(self):
         data=  json.load(self.dump())
     print data

domain = Website("https://example.com")
domain.convJSON()

Uwaga: obiekt przekazany do json.load () powinien obsługiwać .read () , dlatego urllib2.urlopen (self.name) .read () nie będzie działać. Doamin przekazany powinien mieć w tym przypadku protokół http

Nitigya Sharma
źródło
0

możesz również pobrać json, używając requestsjak poniżej:

import requests

r = requests.get('http://yoursite.com/your-json-pfile.json')
json_response = r.json()
Haritsinh Gohil
źródło
0

To kolejne prostsze rozwiązanie Twojego pytania

pd.read_json(data)

gdzie data jest wyjściem str z następującego kodu

response = urlopen("https://data.nasa.gov/resource/y77d-th95.json")
json_data = response.read().decode('utf-8', 'replace')
Himanshu Aggarwal
źródło
-1

Żaden z podanych tutaj przykładów nie zadziałał dla mnie. Były albo dla Pythona 2 (uurllib2), albo te dla Pythona 3 zwracały błąd „ImportError: Żaden moduł o nazwie request”. Wyszukuję w Google komunikat o błędzie i najwyraźniej wymaga on zainstalowania modułu - co jest oczywiście nie do przyjęcia przy tak prostym zadaniu.

Ten kod zadziałał dla mnie:

import json,urllib
data = urllib.urlopen("https://api.github.com/users?since=0").read()
d = json.loads(data)
print (d)
Uxbridge
źródło
2
Najwyraźniej używasz Pythona 2. W Pythonie 3 nie ma urllib.urlopen; urlopenjest w urllib.requestmodule.
Nick Matteo