2009-10-28 8 views
38

J'imagine que cela doit avoir une réponse simple, mais je me bats: je veux prendre une URL (qui sort json) et obtenir les données dans un dictionnaire utilisable en python . Je suis coincé sur la dernière étape.Obtenir des données json via url et utiliser en python (simplejson)

>>> import urllib2 
>>> import simplejson 
>>> req = urllib2.Request("http://vimeo.com/api/v2/video/38356.json", None, {'user-agent':'syncstream/vimeo'}) 
>>> opener = urllib2.build_opener() 
>>> f = opener.open(req) 
>>> f.read()    # this works 
'[{"id":"38356","title":"Forgetfulness - Billy Collins Animated Poetry","description":"US Poet Laureate Billy Collins reads his poem ","url":"http:\\/\\/vimeo.com\\/38356","upload_date":"2006-01-24 15:21:03","thumbnail_small":"http:\\/\\/80.media.vimeo.com\\/d1\\/5\\/47\\/74\\/thumbnail-4774968.jpg","thumbnail_medium":"http:\\/\\/80.media.vimeo.com\\/d1\\/5\\/46\\/85\\/thumbnail-4685118.jpg","thumbnail_large":"http:\\/\\/images.vimeo.com\\/87\\/39\\/873998\\/873998_640x480.jpg","user_name":"smjwt","user_url":"http:\\/\\/vimeo.com\\/smjwt","user_portrait_small":"http:\\/\\/bitcast.vimeo.com\\/vimeo\\/portraits\\/defaults\\/d.30.jpg","user_portrait_medium":"http:\\/\\/bitcast.vimeo.com\\/vimeo\\/portraits\\/defaults\\/d.75.jpg","user_portrait_large":"http:\\/\\/bitcast.vimeo.com\\/vimeo\\/portraits\\/defaults\\/d.100.jpg","user_portrait_huge":"http:\\/\\/bitcast.vimeo.com\\/vimeo\\/portraits\\/defaults\\/d.300.jpg","stats_number_of_likes":"281","stats_number_of_plays":"9173","stats_number_of_comments":23,"duration":"112","width":"320","height":"240","tags":"poetry, poet, online poetry, famous poet, video poetry, modern poetry, famous poem, poetry sites, poetry websites, audio poetry, american poet, animation clips, american poetry, free poetry sites, animation art, free poetry, animated clips, poem, poet laureate"}]' 
>>> simplejson.load(f) 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/usr/lib/python2.5/site-packages/django/utils/simplejson/__init__.py", line 298, in load 
    parse_constant=parse_constant, **kw) 
    File "/usr/lib/python2.5/site-packages/django/utils/simplejson/__init__.py", line 338, in loads 
    return _default_decoder.decode(s) 
    File "/usr/lib/python2.5/site-packages/django/utils/simplejson/decoder.py", line 326, in decode 
    obj, end = self.raw_decode(s, idx=_w(s, 0).end()) 
    File "/usr/lib/python2.5/site-packages/django/utils/simplejson/decoder.py", line 344, in raw_decode 
    raise ValueError("No JSON object could be decoded") 
ValueError: No JSON object could be decoded 

Des idées où je vais mal?

+3

Les choses simples d'abord: le f.read() dans l'extrait est juste à des fins d'explication, non? Raison de demander est parce que si cela fait partie du code prévu, cela a pour effet de "vider" f, d'où le ValueError w/simplejason. – mjv

+1

django.utils.simplejson est déprécié; utilisez json à la place. – ifischer

Répondre

43

Essayez

f = opener.open(req) 
simplejson.load(f) 

sans courir f.read() en premier. Lorsque vous exécutez f.read(), le contenu du handle de fichier est tronqué afin qu'il ne reste plus rien lorsque votre appel simplejson.load(f)

+1

Merci - Je prenais juste étape par étape pour m'assurer que je pouvais voir les données ... évidemment, je ne sais pas assez sur 'read()'! Merci. – thornomad

+0

En python 3, simplejson est remplacé par json, et il a besoin d'une conversion de bytes. data = json.loads (str (opener.open (req) .read(), "utf-8")) fonctionnera pour une réponse codée en UTF-8. – Mead

+2

nit ci-dessus - conversion "utf-8" va avec 'charges', pas' str' (au moins en python 2.7.3) ~ 'data = json.loads (str (opener.open (req) .read()) , "utf-8") ' –

10

La première ligne lit le fichier entier. La deuxième ligne essaie alors de lire la suite à partir du fichier, mais il n'y a rien:

>>> f.read()    # this works 
blah blah blah 
>>> simplejson.load(f) 

Soit il suffit d'omettre la ligne f.read(), ou d'enregistrer la valeur de lecture, et l'utiliser dans des charges:

json = f.read() 
simplejson.loads(json) 
-7

Il y a un moyen encore plus simple - vous n'avez pas besoin de simplejson du tout. Python peut analyser json dans un dict/array en utilisant l'instruction eval tant que vous définissez true/false/null sur les bonnes valeurs.

# fetch the url 
url = "https://api.twitter.com/1/users/lookup.json?user_id=6253282,18949452" 
json = urllib2.urlopen(url).read() 

# convert to a native python object 
(true,false,null) = (True,False,None) 
profiles = eval(json) 
+3

Ceci exige que vous ayez absolument confiance à la source du json bien que – JeffS

+0

@JeffS Pouvez-vous expliquer pourquoi c'est? – Amanda

+4

Veuillez voir: http://docs.python.org/library/functions.html#eval Ainsi, la valeur de la chaîne json est interprétée comme du code python, ce qui signifie que vous autorisez l'exécution du code en tant que programme , et pourrait être un problème de sécurité majeur. – JeffS