Einfache Datenanreicherung mit Wikidata

Beim Aufräumen meiner Browser-Tabs gefunden…

…es ging darum, wie wir an mehr Informationen (z.B. auch ein Bild) für eine Medienstation bekommen, wenn wir nur eine GND ID haben…

Die Antwort ist einfach: Einfach mal bei Wikidata fragen. Im Grunde ist es eine generalisierte Variante der Abfrage aus dem Beitrag über Hugo und Wikidata.

SELECT ?propertyLabel ?valueLabel
WHERE {
  ?item wdt:P227 "10153740-2" .
  ?item ?wdt ?o .
  ?property wikibase:directClaim ?wdt .
  SERVICE wikibase:label {
    bd:serviceParam wikibase:language "en,de" .
    ?property rdfs:label ?propertyLabel .
  }
  OPTIONAL {
    FILTER(isIRI(?o))
    ?o rdfs:label ?enLabel .
    FILTER(LANG(?enLabel) = "en")
  }
  BIND(COALESCE(?enLabel, STR(?o)) AS ?valueLabel)
}

Die Abfrage kann einfach in das Abfragefenster des Wikidata Query Services kopiert werden. Um die gesuchte GND ID zu ändern muss einfach wdt:P227 (hier "10153740-2") geändert werden. Natürlich lässt sich auch nach anderen Identifiern suchen, es gibt inzwischen sehr viele in Wikidata:

Und zur Einbindung in ein Jupyter Notebook oder Python Script, kann diese Funktion genutzt werden:

import urllib.request
import json
import urllib.parse

def query_by_gnd(gnd_id):
    query = """
    SELECT ?propertyLabel ?valueLabel ?valueURI
    WHERE {{
      ?item wdt:P227 "{}" .
      ?item ?wdt ?o .
      ?property wikibase:directClaim ?wdt .

      SERVICE wikibase:label {{
        bd:serviceParam wikibase:language "en,de" .
        ?property rdfs:label ?propertyLabel .
      }}

      OPTIONAL {{
        FILTER(isIRI(?o))
        ?o rdfs:label ?enLabel .
        FILTER(LANG(?enLabel) = "en")
      }}

      BIND(COALESCE(?enLabel, STR(?o)) AS ?valueLabel)

      BIND(IF(isIRI(?o), ?o, ?undefined) AS ?valueURI)
    }}
    """.format(gnd_id)

    endpoint = "https://query.wikidata.org/sparql"
    params = {
        'query': query,
        'format': 'json'
    }
    url = f"{endpoint}?{urllib.parse.urlencode(params)}"

    wikidata = {}

    try:
        req = urllib.request.Request(url, headers={'Accept': 'application/sparql-results+json'})
        with urllib.request.urlopen(req) as response:
            data = response.read().decode('utf-8')
        results = json.loads(data)
        for binding in results['results']['bindings']:
            key = binding['propertyLabel']['value']
            value = binding['valueLabel']['value']
            if key in wikidata:
                if isinstance(wikidata[key], list):
                    wikidata[key].append(value)
                else:
                    wikidata[key] = [wikidata[key], value]
            else:
                wikidata[key] = value
        return wikidata

    except urllib.error.URLError as e:
        print(f"Error accessing Wikidata endpoint: {e.reason}")
    except json.JSONDecodeError as e:
        print(f"Error decoding JSON: {e.reason}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")