Einige Beispiele in Python zur Konvertierung von Quellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
jens-s e87cbc4a99 „README.md“ ändern 4 months ago
LICENSE Initial commit 4 months ago
README.md „README.md“ ändern 4 months ago

README.md

SWORD-Examples

Einige Beispiele in Python zur Konvertierung von Quellen.

Karl Barth: Kurze Auslegung des Römerbriefs

Dieses Werk steht auf archive.org zur Verfügung und ist als Public Domain gekennzeichnet. Da das US-amerikanische PD nicht mit dem europäischen „gemeinfrei“ übereinstimmt, ist die Rechtslage in Deutschland nicht ganz so einfach. Technisch steht aber ein OCR-Text in verhältnismäßig guter Qualität zur Verfügung ("FULL TEXT" im rechten Kasten).

Als Grundlage können wir - wie im vorherigen Teil - folgendes Grundgerüst nehmen:

<?xml version="1.0" encoding="UTF-8" ?>
<osis xmlns="http://www.bibletechnologies.net/2003/OSIS/namespace" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.bibletechnologies.net/2003/OSIS/namespace
      http://www.bibletechnologies.net/osisCore.2.1.1.xsd">
      
<osisText osisIDWork="Barth-Röm" osisRefWork="book" xml:lang="de">
    <header>

      <work osisWork="WorkID">
      <title>Kurze Erklärung des Römerbriefs</title>
      <creator role="aut">Karl Barth</creator>
      </work>
      <work osisWork="Bible">
      <refSystem>Bible</refSystem>
      </work>
    </header>
    
    
<div type="book" osisID="Kurze Erklärung des Römerbriefs">
  [...]
</div>
</osisText>
</osis>

Der obere Bereich beinhaltet die Grundinformationen, dort wo [...] vermerkt ist, kommen nun die Inhalte ins Spiel. Ein Blick in das Inhaltsverzeichnis verrät uns, dass die Buchstruktur sehr einfach ist. Wir müssen nur ein paar majorSections hinzufügen:

<div type="majorSection" osisID="VORWORT">
<title>VORWORT</title>
...
</div>

Die eigentliche Transformation erledigen wir mit Python. Zunächst benötigen wir einige Bibliotheken:

import os, subprocess
import re

Nun definieren wir noch Ein- und Ausgabe und lesen die Datei:

infile = "20200323_KURZE ERKLARUNG DESRDMERBRIEFES_djvu.txt"
outfile = "röm.xml"
f = open(infile, "r")
text = f.read()

Jetzt transformieren wir zunächst alle Seitenzahlen in eckige Klammern und entfernen die Zeilenumbrüche:

text = re.sub (  r"\n\n\n([0-9]+)[\s*]\n\n\n",
                  " [\g<1>] "
                    , text)
text = text.replace("  ", "")

Das einzige, was uns noch vom direkten Einfügen in unsere Vorlage abhält, sind die Zeilenumbrüche. OSIS verlangt Paragraphen in <p>-Tags. Außerdem haben wir noch im Satz getrennte Wörter. Diese können wir mit der folgenden for-Schleife lösen:

lines = text.split("\n")
print (len(lines))
for i in range(0,len(lines)):
    line = lines[i].strip()
    if len(line)<4 and line!="":
        continue
    elif len(line)<20:
        # New Paragraph
        paragraph = paragraph + line
        output = output +  ("<p>"+(paragraph)+"</p>\n")
        paragraph = ""
    else:
        if line[-1] == "-":
            paragraph = paragraph + line[:-1]
        elif line[-1] == "¬":
            paragraph = paragraph + line[:-1]
        else:
            paragraph = paragraph + line + " "
if paragraph != "":
    output = output +  ("<p>"+(paragraph)+"</p>\n")

Jetzt schreiben wir noch den fertig transformierten Text in die Ausgabedatei und kopieren dann die Inhalte in die Vorlage.

f2 = open(outfile, "w")
f2.write(output)

Was fangen wir nun mit der XML-Datei an? Wir müssen sie erneut mit den SWORD-Hilfsprogrammen konvertieren:

xml2gbs Barth-Röm.xml Barth-Röm

Die drei neuen Dateien verschiebt man wieder in das SWORD-Verzeichnis (~/.sword/modules/...) und erzeugt eine conf-Datei, die z.B. so aussehen kann:

[Barth-Röm]
DataPath=./modules/genbook/rawgenbook/Barth-Röm/Barth-Röm
ModDrv=RawGenBook
BlockType=CHAPTER
SourceType=OSIS
CompressType=ZIP
GlobalOptionFilter=OSISFootnotes
GlobalOptionFilter=OSISHeadings
Encoding=UTF-8
Lang=de
LCSH=Bible--Commentaries.
Description=Kurze Erklärung des Römerbriefs
About=Kurze Erklärung des Römerbriefs, Karl Barth (1959)
History_1.0=Initial version
DistributionLicense=Public Domain, see https://archive.org/details/20200323kurzeerklarungdesrdmerbriefes_202003/mode/2up

Nun kann man den Text von Karl Barth in SWORD bewundern. Wir hätten nur noch ein, zwei Schönheitsoperationen zu erledigen: Die Fußnoten. Zum Glück enthält dieses Buch fast gar keine. Man kann mit einem beliebigen Texteditor nach dem Sternchen * suchen. Die Fußnoten ergänzen wir dann mit dem <note>-Tag:

Gestehen wir es gleich zu: Wären uns die Verse 19—21<note type="x-footnote">* Vgl. zu dieser Stelle KD. I, 2 S. 334 f. und II, 1 S. 131 f.</note> für sich, vielleicht als Fragment [...]

Das automatische Behandeln von Fußnoten ist keine einfache Aufgabe und das händische Nacharbeiten von vielen Fußnoten eine sehr mühsame Fleißarbeit.

Ulrich Wilckens: Das Evangelium nach Johannes

Einige Bücher der Kommentarreihe Neues Testament Deutsch (NTD) stehen bei Digi20 zum Download, z.B. der Johannes-Kommentar. Dieses Buch darf nur für private Zwecke digital bearbeitet werden. Andere Bücher (etwa die Theologie von Stuhlmacher) stehen wiederum unter Creative Commons-Lizenz zur Verfügung. Hier müsste jemand mit guten Kenntnissen der rechtlichen Situation die Weitergabe prüfen.

Das OCR des PDFs ist einigermaßen akzeptabel. Allerdings haben wir entweder sehr viel Arbeit mit dem Inhaltsverzeichnis vor uns oder versuchen, automatisch Überschriften und Unterüberschriften zu erkennen. Auch das ist nicht trivial. Schön ist eine durchgängige Form (1. .... 1.1.... 1.1.1.....). Oft werden aber verschiedene Formate verwendet oder noch schlimmer: sogar gewechselt. (§1 Einleitung, 1.1 ... I., II. , XI. ....). Es ist also händisches Nacharbeiten zu erwarten. Immerhin wird in der Reihe NTD nicht mit Fußnoten gearbeitet...

Zusätzlich zu unserem Beispiel oben benötigen wir noch eine Bibliothek, die PDF-Dateien lesen kann:

import pdfplumber

Zuerst definieren wir einige Werte:

filename="datei.pdf"  # Eingabedatei
startpage=10 # Die Startseite, ab hier beginnt der Text
endpage= 288 # Letzte Seite 
linelength=45 # Zeilen, die kürzer als 45 Zeichen sind beenden einen Paragraphen

Dann lesen wir sukzessive alle entsprechenden Seiten ein:

for pagenumber in range(startpage, endpage):    
    page = pdf.pages[pagenumber]
    pagen = page.crop ( (30,0, (page.width), yval) 
    text = pagen.extract_text(x_tolerance=3)

Der page.crop-Befehl schneidet uns die Fußzeile mit den Seitenzahlen ab. Ansonsten müssten wir diese nach dem Muster von oben behandeln. Wir trennen den Wert von text nun wie oben nach dem Zeilenende und verarbeiten ihn wie im Beispiel oben weiter: text.split("\n").

Eine kleine Funktion annotiert übrigens auch direkt Links zu Bibelstellen. Dies ist extrem nützlich, um diese nicht händisch nachschlagen zu müssen:

def markbooks (text):
    for book in filter:
        text = text.replace (book+"  ", book+" ")
    for book in filter:
        bookn = str(filter[book])
        text = re.sub (   r"("+book.replace(" ", "[\s]")+")[\.]?[ ]?([0-9]+?),[ ]?([0-9]*)(?!-)[ ]?.*?(\.?)([0-9]*)" ,
                       '<reference osisRef="'+str(filter[book])+r'.\g<2>.\g<3>\g<4>'+'"'+r'>\g<0>'+'</reference>'
                    , text)
        text = re.sub (        r"("+book.replace(" ", "[\s]")+")[\.]?[ ]?([0-9]+?),[ ]?([0-9]*)(-+)[ ]?(\.?)([0-9]*)" ,
                       '<reference osisRef="'+bookn+r'.\g<2>.\g<3>\g<4>'+bookn+r'.\g<2>.\g<6>'+'"'+r'>\g<0></reference>'
                    , text)
        # Eine weitere Iteration für Formate wie Röm 3,1; 15.2
        text = re.sub (        r"("+book.replace(" ", "[\s]")+")[\.]?[ ]?([0-9]+?),[ ]?([0-9]*)(?!-)[ ]?.*?(\.?)([0-9]*)</reference>[;]?[:]?[ ]?([0-9]+?),[ ]?([0-9]*)" ,
                       ''+book+r' \g<2> \g<3>,\g<4>'+'</reference>'+'; <reference osisRef="'+str(filter[book])+r'.\g<6>.\g<7>'+'"'+r'>\g<6>,\g<7>'+'</reference>'
                    , text)
    return text

Der Inhalt des Dictionaries „filter“ ist dabei reine Fleißarbeit. Hier steht zu jeder möglichen Kurzform eines biblischen Buches ihre enstprechende Normalform:

filter = {"1Mo":"Gen","1 Mo":"Gen", "Gen":"Gen", 
          "1Mose":"Gen",
          "2Mo":"Exod","2 Mo":"Exod", "Ex":"Exod", 
          "Exod":"Exod",  "2Mose":"Exod", 
          "3Mo":"Lev","3 Mo":"Lev", "Lev":"Lev", 
          "3Mose":"Lev", 
          "Neh":"Neh", ...