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 bloggpost om 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:

#-*- 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:

"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:

"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!

#-*- 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

6 reaktioner till “Medborgarprogrammering 2 – Riksdagens API”

  1. Du kan fråga efter vilken typ som strukturen du får tillbaka har med hjälp av isinstance:

    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’]
    else:
    raise TypeError

  2. Jimmy: Aha! Intressant. Dock får jag :
    File ”APIpythonjson.py”, line 37, in
    raise TypeError
    TypeError

    när jag skriver hela loopen som:

    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’]
    else:
    raise TypeError

Kommentera

E-postadressen publiceras inte. Obligatoriska fält är märkta *

Time limit is exhausted. Please reload CAPTCHA.