OAI-Schnittstellen Request, Antwort, Herunterladen der Daten

Dieses Tutorial bietet Beispiele für Abfragen über die OAI-Schnittstelle mit Python. Es behandelt exemplarische Anfragen an die OAI-PMH-Schnittstelle der Staatsbibliothek zu Berlin - PK. Darüber hinaus wird das Herunterladen der Daten und das Speichern in einer CSV-Datei erläutert.

Einrichten der Arbeitsumgebung

Zuerst richten wir die Arbeitsumgebung ein, indem wir die benötigten Python-Bibliotheken importieren. Für Anfragen über die OAI-Schnittstelle wird die Bibliothek "sickle" genutzt, während für die Verarbeitung der XML-Daten die Bibliothek "etree" verwendet wird.

from sickle import Sickle
from lxml import etree

Abfrage aller Datensets

Die OAI-Basis-URL der Staatsbibliothek zu Berlin – PK ist https://oai.sbb.berlin. Bitte beachten Sie, dass die ausgegebene Antwort der Übersichtlichkeit halber auf 10 Antworten beschränkt wird. Sollten Sie alle Antworten einsehen wollen, löschen Sie den entsprechenden Teil des Codes oder setzen Sie ein # vor die Zeilen.

sickle = Sickle('https://oai.sbb.berlin')
oai_sets = sickle.ListSets()
counter = 0
for oai_set in oai_sets:
    print('setSpec value for selective harvesting: ' + oai_set.setSpec)
    print('Name of the set (setName): ' + oai_set.setName + '\n')
    # Die folgenden Zeilen Code sind dazu da die angezeigten Ergebnisse auf 10 zu beschränken. 
    # Wenn Sie alle Ergebnisse einsehen möchten, löschen
    # Sie das unten stehende Segment oder fügen Sie ein # vor allen den Zeilen ein.
    counter += 1
    if counter >= 10:
        break
setSpec value for selective harvesting: all
Name of the set (setName): Alle Kategorien

setSpec value for selective harvesting: historische.drucke
Name of the set (setName): Historische Drucke

setSpec value for selective harvesting: theologie
Name of the set (setName): Theologie

setSpec value for selective harvesting: rechtswissenschaft
Name of the set (setName): Rechtswissenschaft

setSpec value for selective harvesting: militaerwesen
Name of the set (setName): Militärwesen

setSpec value for selective harvesting: geschichte.ethnographie.geographie
Name of the set (setName): Geschichte / Ethnographie / Geographie

setSpec value for selective harvesting: krieg.1914.1918
Name of the set (setName): Krieg 1914-1918

setSpec value for selective harvesting: landwirtschaft
Name of the set (setName): Landwirtschaft / Forstwirtschaft

setSpec value for selective harvesting: politik.staat.gesellschaft.wirtschaft
Name of the set (setName): Politik / Staat / Gesellschaft / Wirtschaft

setSpec value for selective harvesting: sprachen.literaturen
Name of the set (setName): Sprachen / Literaturen

Ausgabe von Titeln und Autoren eines Sets

Im folgenden Beispiel werden wir die Titel und die Autoren aus dem Set "Illustrierte Liedflugschriften" auflisten. Für die Anfrage müssen Metadatenformat und Set angegeben werden. Wir fragen hier die Dublin Core Metadaten ab, kurz DC. Die abgerufenen Daten sind in der XML-Antwort enthalten und werden durch nummerierte beschreibende Elemente dargestellt.
Für weitere Informationen zum Metadatenformat DC (Dublin Core) können Sie die DC-Spezifikationen unter http://www.openarchives.org/OAI/2.0/oai_dc/ und http://purl.org/dc/elements/1.1/ heranziehen. Weitere OAI-Funktionen werden unter http://www.openarchives.org/OAI/2.0/ spezifiziert und auf der Stabi-Lab-Seite unter dem Reiter "Daten" beschrieben.
Bitte beachten Sie, dass die ausgegebene Antwort der Übersichtlichkeit halber auf 10 Antworten beschränkt wird. Sollten Sie alle Antworten einsehen wollen, löschen Sie den entsprechenden Teil des Codes oder setzen Sie ein # vor die Zeilen.

namespaces = {
    'oai': 'http://www.openarchives.org/OAI/2.0/',
    'oai_dc': 'http://www.openarchives.org/OAI/2.0/oai_dc/',
    'dc': 'http://purl.org/dc/elements/1.1/'
}

count=0
counter = 0

for record in sickle.ListRecords(**{'metadataPrefix': 'oai_dc', 'set': 'illustrierte.liedflugschriften'}):
    
    if ('ger' in record.raw):
        tree = etree.ElementTree(record.xml)
        result = tree.xpath('/oai:record/oai:metadata/oai_dc:dc/dc:title/text()', namespaces=namespaces)
        if (result):
            count += 1
            author = tree.xpath('/oai:record/oai:metadata/oai_dc:dc/dc:creator/text()', namespaces=namespaces)
            print(str(count) + ": " + result[0])
            # Die folgenden Zeilen Code sind dazu da die angezeigten Ergebnisse auf 10 zu beschränken. 
            # Wenn Sie alle Ergebnisse einsehen möchten, löschen
            # Sie das unten stehende Segment oder fügen Sie ein # vor allen den Zeilen ein.
            counter += 1
            if counter >= 10:
                break
            # bis hier löschen oder ein # vor die vorherigen Zeilen setzen.
            if author:
                print(author[0])
               
1: Sechs Geystliche Wey=||nacht Lieder/ Von der geburt Christi/|| vnd von den heiligen drey Kœnigen/|| Jm thon/ Wie bey einem jeden || Lied verzeichnet ist.||
2: Alte vnd || Newe Geistli=||che Lieder vnd Lob=||gesenge/ von der Ge=||burt Christi/ vnsers || Herrn/ fuer die Jun=||ge Christen.|| Johan Spang.||
Spangenberg, Johann
3: Ein schœn geist||lich Liedt/ Ach Herre || Gott/ mich treybt die not.|| Ein ander geistlich Lied/|| Der genaden Brunn thut fliessen. Jm thon/|| Die Bruenlein die thun fliessen.||
4: Ein new Lied/ der Je=||ger Geistlich.|| Ein ander geistlich lied/|| Jn dem thon/ Auss hertem || wee klagt sich ein Held.||
5: Ein schœn New Geist=||lich Lied/ Wach auff wach auff O || menschen kindt/ [et]c. Jm Thon/|| Kompt her zu mir spricht || Gottes Son.||
6: Der 103. Psalm/ Nu lob || mein seele den Herren. Jn || gesangs weyß. [Übers. v. Johannes Poliander] || Mer drey schöner Geist||licher Lieder. Das erst/ Herr Gott deine || gewalt/ ist vber jung vnd alt. Das ander/|| der mensch lebt nicht allein in brod.|| Das dritte/ Allein zu dir Herr || Jhesu Christ. [v. Johannes Schneesing]||
Schneesing, Johannes
7: Ein schœn new || Liede/ von Herrn D. Martini || Luthers sterben/ darinn kuertzlich be=||griffen/ was er inn der letzten zeit geredt || sehr trœstlich allen Christen/ durch || Leonhardum Ketner von || Herßbruck.|| Jm thon/ Jch rueff zu dir Herr || Jesu Christ.||
Kettner, Leonhart
8: Ein Christli=||cher Abentreien/ vom Leben || vnd ampt Johannis des Tauf=||fers/ fuer Christliche/ zuechtige || Jungfrawlein. N.H.||
Herman, Nikolaus
9: Zwey schœne newe Geist-||licher Liede/ auß Gœttlicher Schrifft/|| Von dem wuest~e wesen der jetzig~e bœsen || welt ... || ~Jm thon/|| Frisch auff jhr Landts=||knecht alle/ [et]c.|| Das Ander Lied zu bit=||ten vmb vergebung der Suend/ vnnd || vmb sterck~ug des glaubens/ Auch vmb || ein seliges endt. ~Jm thon/ wie der 13.|| Psalm/ HErr Gott wie lang || vergissest mein/ [et]c.||
Müntzer, M. R.
10: Zwey Schœne newe Lie=||der. Das erst/ Jch armer Suender klag || mich sehr. Das ander/ O Got Vat=||er im hœchsten Thron/ vnd || sind in dem Thon/ Jch || armes Meydlein || klag mich || seh/ etc.||

Der Folgenden Code gibt die Links zu den digitalisierten Objekten aus. Hierfür wird entsprechend das DC-Schema /oai:record/oai:metadata/oai_dc:dc/dc:identifier/text() angesprochen und zusammen mit dem Titel ausgegeben.
Bitte beachten Sie, dass die ausgegebene Antwort der Übersichtlichkeit halber auf 10 Antworten beschränkt wird. Sollten Sie alle Antworten einsehen wollen, löschen Sie den entsprechenden Teil des Codes oder setzen Sie ein # vor die Zeilen.

namespaces = {
    'oai': 'http://www.openarchives.org/OAI/2.0/',
    'oai_dc': 'http://www.openarchives.org/OAI/2.0/oai_dc/',
    'dc': 'http://purl.org/dc/elements/1.1/'
}

count=0
counter=0

for record in sickle.ListRecords(**{'metadataPrefix': 'oai_dc', 'set': 'illustrierte.liedflugschriften'}):
    
    if ('ger' in record.raw):
        tree = etree.ElementTree(record.xml)
        result = tree.xpath('/oai:record/oai:metadata/oai_dc:dc/dc:title/text()', namespaces=namespaces)
        if (result):
            count += 1
            urn = tree.xpath('/oai:record/oai:metadata/oai_dc:dc/dc:identifier/text()', namespaces=namespaces)
            print(str(count) + ": " + result[0])
            if urn:
                print("https://digital.staatsbibliothek-berlin.de/werkansicht?ppn=" + urn[0])
                # Die folgenden Zeilen Code sind dazu da die angezeigten Ergebnisse auf 10 zu beschränken. 
                # Wenn Sie alle Ergebnisse einsehen möchten, löschen
                # Sie das unten stehende Segment oder fügen Sie ein # vor allen den Zeilen ein.
                counter += 1
                if counter >= 10:
                    break
1: Sechs Geystliche Wey=||nacht Lieder/ Von der geburt Christi/|| vnd von den heiligen drey Kœnigen/|| Jm thon/ Wie bey einem jeden || Lied verzeichnet ist.||
https://digital.staatsbibliothek-berlin.de/werkansicht?ppn=PPN66805073X
2: Alte vnd || Newe Geistli=||che Lieder vnd Lob=||gesenge/ von der Ge=||burt Christi/ vnsers || Herrn/ fuer die Jun=||ge Christen.|| Johan Spang.||
https://digital.staatsbibliothek-berlin.de/werkansicht?ppn=PPN668091029
3: Ein schœn geist||lich Liedt/ Ach Herre || Gott/ mich treybt die not.|| Ein ander geistlich Lied/|| Der genaden Brunn thut fliessen. Jm thon/|| Die Bruenlein die thun fliessen.||
https://digital.staatsbibliothek-berlin.de/werkansicht?ppn=PPN668097213
4: Ein new Lied/ der Je=||ger Geistlich.|| Ein ander geistlich lied/|| Jn dem thon/ Auss hertem || wee klagt sich ein Held.||
https://digital.staatsbibliothek-berlin.de/werkansicht?ppn=PPN668102799
5: Ein schœn New Geist=||lich Lied/ Wach auff wach auff O || menschen kindt/ [et]c. Jm Thon/|| Kompt her zu mir spricht || Gottes Son.||
https://digital.staatsbibliothek-berlin.de/werkansicht?ppn=PPN66814730X
6: Der 103. Psalm/ Nu lob || mein seele den Herren. Jn || gesangs weyß. [Übers. v. Johannes Poliander] || Mer drey schöner Geist||licher Lieder. Das erst/ Herr Gott deine || gewalt/ ist vber jung vnd alt. Das ander/|| der mensch lebt nicht allein in brod.|| Das dritte/ Allein zu dir Herr || Jhesu Christ. [v. Johannes Schneesing]||
https://digital.staatsbibliothek-berlin.de/werkansicht?ppn=PPN668148160
7: Ein schœn new || Liede/ von Herrn D. Martini || Luthers sterben/ darinn kuertzlich be=||griffen/ was er inn der letzten zeit geredt || sehr trœstlich allen Christen/ durch || Leonhardum Ketner von || Herßbruck.|| Jm thon/ Jch rueff zu dir Herr || Jesu Christ.||
https://digital.staatsbibliothek-berlin.de/werkansicht?ppn=PPN668153601
8: Ein Christli=||cher Abentreien/ vom Leben || vnd ampt Johannis des Tauf=||fers/ fuer Christliche/ zuechtige || Jungfrawlein. N.H.||
https://digital.staatsbibliothek-berlin.de/werkansicht?ppn=PPN668165987
9: Zwey schœne newe Geist-||licher Liede/ auß Gœttlicher Schrifft/|| Von dem wuest~e wesen der jetzig~e bœsen || welt ... || ~Jm thon/|| Frisch auff jhr Landts=||knecht alle/ [et]c.|| Das Ander Lied zu bit=||ten vmb vergebung der Suend/ vnnd || vmb sterck~ug des glaubens/ Auch vmb || ein seliges endt. ~Jm thon/ wie der 13.|| Psalm/ HErr Gott wie lang || vergissest mein/ [et]c.||
https://digital.staatsbibliothek-berlin.de/werkansicht?ppn=PPN668409428
10: Zwey Schœne newe Lie=||der. Das erst/ Jch armer Suender klag || mich sehr. Das ander/ O Got Vat=||er im hœchsten Thron/ vnd || sind in dem Thon/ Jch || armes Meydlein || klag mich || seh/ etc.||
https://digital.staatsbibliothek-berlin.de/werkansicht?ppn=PPN66841247X

Herunterladen der Daten als CSV-Datei

Im Folgenden zeigen wir Ihnen, wie Sie die Metadaten auslesen, in einen DataFrame einbinden und als CSV-Datei speichern.

Um die für Sie und Ihre Anfrage geeigneten Metadatenelemente zu identifizieren, werfen wir zuerst einen Blick auf die Unterelemente eines Objekts. Beachten Sie bitte, dass wir hier die DC-Metadaten betrachten, nicht die METS-Metadaten.

import requests

response = requests.get('https://oai.sbb.berlin/?verb=GetRecord&metadataPrefix=oai_dc&identifier=oai:digital.staatsbibliothek-berlin.de:PPN668091029')
flugschrift1_xml = response.text
print(flugschrift1_xml)
<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/oai-static/oai2.xsl" type="text/xsl"?>
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
  <responseDate>2024-01-04T09:46:32Z</responseDate>
  <request verb="GetRecord" metadataPrefix="oai_dc" identifier="oai:digital.staatsbibliothek-berlin.de:PPN668091029">https://oai.sbb.berlin/</request>
  <GetRecord>
    <record>
      <header>
        <identifier>oai:digital.staatsbibliothek-berlin.de:PPN668091029</identifier>
        <datestamp>2018-07-13T13:55:50Z</datestamp>
        <setSpec>historische.drucke</setSpec>
        <setSpec>musik</setSpec>
        <setSpec>theologie</setSpec>
      </header>
      <metadata>
        <oai_dc:dc xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd">
          <dc:title>Alte vnd || Newe Geistli=||che Lieder vnd Lob=||gesenge/ von der Ge=||burt Christi/ vnsers || Herrn/ fuer die Jun=||ge Christen.|| Johan Spang.||</dc:title>
          <dc:creator>Spangenberg, Johann</dc:creator>
          <dc:subject>Historische Drucke</dc:subject>
          <dc:subject>Musik</dc:subject>
          <dc:subject>Theologie</dc:subject>
          <dc:publisher>Sachse, Melchior</dc:publisher>
          <dc:type>monograph</dc:type>
          <dc:type>text</dc:type>
          <dc:format>application/mets+xml</dc:format>
          <dc:format>image/jpeg</dc:format>
          <dc:identifier>PPN668091029</dc:identifier>
          <dc:identifier>PPN567450481</dc:identifier>
          <dc:identifier>http://resolver.staatsbibliothek-berlin.de/SBB00005DC200000000</dc:identifier>
          <dc:language>ger</dc:language>
          <dc:date>1544</dc:date>
          <dc:coverage>Erfurt</dc:coverage>
          <dc:rights>Public Domain Mark 1.0</dc:rights>
        </oai_dc:dc>
      </metadata>
    </record>
  </GetRecord>
</OAI-PMH>

Gehen wir nun davon aus, dass Sie die folgenden Metadaten für die Weiterverwendung benötigen: dc:date, dc:coverage, dc:publisher und dc:creator. Exemplarisch werden wir diese für alle 1589 Objekte im Set "Illustrierte Liedflugschriften" in einen DataFrame (eine Datenmatrix, in der Daten in Zeilen und Spalten organisiert sind) einbinden.

# Importieren der benötigten Bibliotheken
import requests
import xml.etree.ElementTree as ET
import pandas as pd

# Festlegen der OAI-Parameter
base_url = 'https://oai.sbb.berlin/'
metadata_prefix = 'oai_dc'
set_name = 'illustrierte.liedflugschriften'

# Definitieren der Funktion zum Extrahieren der Daten aus dem OAI-Response
def extract_data(response_xml):
    ns = {
        "oai_dc": "http://www.openarchives.org/OAI/2.0/oai_dc/",
        "dc": "http://purl.org/dc/elements/1.1/"
    }
    dates = []
    places = []
    publishers = []
    creators = []

    flugschriften = ET.fromstring(response_xml)
    for item in flugschriften.findall(".//oai_dc:dc", ns):
        # Hier können Sie andere Metadaten-Elemnte abfragen, indem Sie
        # anstatt .//dc:date ein anderes Metadaten-Element einfügen.
        dates.append(item.find('.//dc:date', ns).text)
        places.append(item.find('.//dc:coverage', ns).text)
        publisher_element = item.find('.//dc:publisher', ns)
        if publisher_element is not None:
            publishers.append(publisher_element.text)
        else:
            publishers.append(None)
        creator_element = item.find('.//dc:creator', ns)
        if creator_element is not None:
            creators.append(creator_element.text)
        else:
            creators.append(None)

    return dates, places, publishers, creators

# Definitinieren der Funktion zum Durchführen der OAI-Abfrage und Extrahieren der Daten
def get_data(url):
    response = requests.get(url)
    response_xml = response.text
    dates, places, publishers, creators = extract_data(response_xml)
    return dates, places, publishers, creators, response_xml

# Erstellen leerer Listen und Abrufen der Daten von allen Seiten
all_dates = []
all_places = []
all_publishers = []
all_creators = []

next_url = f"{base_url}?verb=ListRecords&metadataPrefix={metadata_prefix}&set={set_name}"
while next_url:
    dates, places, publishers, creators, response_xml = get_data(next_url)
    all_dates.extend(dates)
    all_places.extend(places)
    all_publishers.extend(publishers)
    all_creators.extend(creators)
    
    # Überprüfung ob es einen Resumption Token gibt und weitere Daten vorhanden sind
    root = ET.fromstring(response_xml)
    resumption_token = root.find('.//{http://www.openarchives.org/OAI/2.0/}resumptionToken')
    if resumption_token is not None:
        next_url = f"{base_url}?verb=ListRecords&resumptionToken={resumption_token.text}"
    else:
        next_url = None

# Erstellen eines DataFrames mit allen gesammelten Daten
flugschriften_df = pd.DataFrame({'date': all_dates, 'place': all_places, 'publisher': all_publishers, 'creator': all_creators})

flugschriften_df
date place publisher creator
0 1555 Nürnberg Gutknecht, Friedrich None
1 1544 Erfurt Sachse, Melchior Spangenberg, Johann
2 1560 Nürnberg Neuber, Valentin None
3 1560 s.l. None None
4 1560 Nürnberg Gutknecht, Friedrich None
... ... ... ... ...
1584 1850 [S.l.] None None
1585 1850 [S.l.] None None
1586 1870 [Berlin] Queva Queva, A.
1587 1850 [S.l.] None Mosen, Julius
1588 1850 [S.l.] None None

1589 rows × 4 columns

Wenn Sie diesen DataFrame als CSV-Datei speichern und lokal weiterverwenden möchten, nutzen Sie folgenden Code. Entfernen Sie dafür das # vor dem Code, um diesen auszuführen. Sie erhalten dann eine CSV-Datei, die Sie mit Jupyter Notebooks oder Excel öffnen und weiterverarbeiten können.

# flugschriften_df.to_csv('FS1.csv')

Für Inspirationen, wie Sie die Daten visuell aufbereiten stehen Ihnen unter https://infovis.fh-potsdam.de/tutorials/ hilfreiche Tutorials zur Verfügung. Diese Tutorials wurden von Prof. Dr. Marian Dörk der Fachhoschule Potsdam erstellt.
Dieses Jupyter-Notebook wurde von Ulrike Förstel im Rahmen ihrer Bachelorarbeit im Studiengang Informations- und Datenmanagement an der Fachhochschule Potsdam erstellt.