Medborgarprogrammering 2 - Riksdagens API

Jag har fastnat lite i ett hobbyprojekt som handlar om att koda mot olika former av öppna data. Jag inspirerades av en väldigt intressant bloggpostom hur man kan visualisera data från data.riksdagen.se med hjälp av D3.js och javascript. På twitter tipsades jag även om den intressanta sidan demokratikollen.se.

Över ett par koppar kaffe satte jag igång ett försök att anropa dessa datamängder till mitt nyligen inlärda programmeringsmodersmål Python. Det gick "sådär". Problemet är att jag inte riktigt begriper strukturen på den data man får när man anropar Riksdagens API. Om någon begriper vad jag gör fel, kommentera gärna.

Uppdatering: Problemet löstes av Jimmy. Skrolla längst ned för att kopiera.

Här är skriptet som jag har skrivit i ett försök att komma åt e-postaddresser (med mera) som gömmer sig en bit in i json-strukturen som man får när man anropar APIt:

``` {.EnlighterJSRAW data-enlighter-language="python"}

-- coding: utf-8 --

from urllib2 import urlopen from json import load

Load and parse JSON objects from web.

apiUrl = "http://data.riksdagen.se/personlista/?iid=&fnamn=&enamn=&f_ar=&kn=&parti=&valkrets=&rdlstatus=&org=&utformat=json&termlista=" apiParam = "" outputFormat = "?format=json" response = urlopen(apiUrl + apiParam + outputFormat)

For more responsiveness, save the above file and use:

response = open('data.json')

json_obj = load(response)

jsonData = json_obj['personlista']['person']

validentries = 0 validemail = 0

for item in jsonData: validentries += 1

for item in jsonData: print "-" * 20 print item['tilltalsnamn'] + " " + item['efternamn'] + ", " + item['parti'] + ", " + item['kon'] data = item['personuppgift']['uppgift'] try: for u in data: if u['kod'] == 'Officiell e-postadress': print u['uppgift'] validemail += 1 except: TypeError

print control variables. Entries should be 349 MPs

print "Found %d valid entries (MPs)" %validentries print "Found %d valid e-mail addresses" %validemail

Skriptet är lite omständigt för jag har lagt in lite kontrollsummor för
att hela tiden ha koll på att alla 349 riksdagsledamöter sysslar med. På
rad 27 hämtar jag bara namn, parti och kön för att printa ut en första
rad. Men på rad 28 försöker jag gräva mig ned djupare för att få tag på
följande data:

``` {.EnlighterJSRAW data-enlighter-language="js"}
"personuppgift": {
          "uppgift": [
            {
              "kod": "Officiell e-postadress",
              "uppgift": "anna.wallen[på]riksdagen.se",
              "typ": "eadress",
              "intressent_id": "0970427364222"
            }

Det är inga problem så länge datastrukturen ser ut som ovan. Inuti en lång lista som börjar med [ligger ett antal dictionaries som sedan innehåller datan som är intressant (här finns även telefonnummer, hemsidor, osv.). Men så kommer man till ca. 30 av 300 riksdagsledamoter som ser ut så här:

``` {.EnlighterJSRAW data-enlighter-language="js"} "personuppgift": { "uppgift": { "kod": "Officiell e-postadress", "uppgift": "magnus.manhammar[på]riksdagen.se", "typ": "eadress", "intressent_id": "025967059622" } }

Observera avsaknaden av bracket(s). Av någon obegriplig anledning så
genererar riksdagen bara en dictionary när det bara finns en enda
dictionary. Alltså, den läggs inte i en lista, som i exemplet ovan.

Nu till min fråga. Hur skriver jag skriptet så att det även kan få in
informationen i denna "lägre" nivå. Alltså, vad ska jag skriva efter
`except` för att även få med den sista informationen?

Tacksam för svar, frågor eller ledtrådar.

\\\\  
Här kommer det fungerande skriptet, tack vare Jimmys insatser i
kommentarsfältet. Nu är det bara att sätta igång att modifiera!

``` {.EnlighterJSRAW data-enlighter-language="python"}
#-*- coding: utf-8 -*-
from urllib2 import urlopen
from json import load


#Load and parse JSON objects
apiUrl = "http://data.riksdagen.se/personlista/?iid=&fnamn=&enamn=&f_ar=&kn=&parti=&valkrets=&rdlstatus=&org=&utformat=json&termlista="
apiParam = ""
outputFormat = "?format=json"
response = urlopen(apiUrl + apiParam + outputFormat)

#For more responsiveness, save the above file and use:
#response = open('data.json')
json_obj = load(response)

jsonData = json_obj['personlista']['person']

#some control variables to check for errors.
validentries = 0
validemail = 0

for item in jsonData:
    validentries += 1

for item in jsonData:
        print "-" * 20
        print item['tilltalsnamn'] + " " + item['efternamn'] + ", " + item['parti'] + ", " + item['kon']
        data = item['personuppgift']['uppgift']
        if isinstance(data, list):
            for u in data:
                if u['kod'] == 'Officiell e-postadress':
                    print u['uppgift']
                    validemail += 1
        elif isinstance(data, dict):
                    print data['uppgift']
                    validemail += 1
        else:
            raise TypeError

#print control variables. Entries should be 349 MPs
print "Found %d valid entries (MPs)" %validentries
print "Found %d valid e-mail addresses" %validemail