tovotu

19. Februar 2015
Wörterbücher offline verfügbar machen mit dictmaster.py
Sprache:Python - Libs:pyquery,urllib2,sqlite3,pyglossary

Mein App-Projekt FireDict ist inzwischen zu einer verhältnismäßig ausgereiften und brauchbaren Lösung für die Anzeige von Offline-Wörterbüchern unter Firefox OS und Android herangereift. Ein Nachteil hat die App aber noch: Die passenden Wörterbücher müssen aus Drittquellen selbst zusammengesucht werden.

Diese Quellen gibt es zuhauf und teilweise ist der Datenbestand direkt im passenden Format zugänglich. Aber in den meisten Fällen ist man doch auf eine Konvertierung angewiesen oder muss sich über veraltete und schlecht formatierte Versionen ärgern.

Mir schwebte schon länger ein Universalwerkzeug zur automatischen Erstellung von angenehm formatierten Offline-Wörterbüchern aus online verfügbaren Quellen vor. Mit der Entwicklung des Tools dictmaster habe ich erste Schritte zur Realisierung dieser Idee getan.

dictmaster basiert auf Python (Version 2.7), urllib2, pyquery (mit lxml), sqlite3 und pyglossary. Die Entwicklung findet zum jetzigen Zeitpunkt ausschließlich unter und im Hinblick auf Linux statt, eventuell könnte dictmaster aber auch mittels cygwin unter Windows lauffähig gemacht werden. Momentan handelt es sich um ein bloßes Kommandozeilen-Werkzeug. Eine grafische Oberfläche wäre ein schönes Extra für die Zukunft, momentan wird daran aber nicht gearbeitet.

Hier einige Eindrücke, wie die mit dictmaster erstellten Wörterbücher in der App FireDict aussehen. (Highlights sind sicherlich das GNU Collaborative Dictionary of English, das CIA Word Factbook 2014 sowie das Dictionnaire de l'Académie Française, für die seit Jahren nur veraltete und wenig ansprechende Stardict-Versionen im Internet kursieren. Ähnliches trifft auf das Online Etymology Dictionary von Douglas Harper zu.)

Zur Nutzung bezieht man den Quellcode von FramaGit, initialisiert das benötigte Untermodul pyglossary mit git submodule update --init und startet aus dem Projektverzeichnis heraus mit

./dictmaster.py PLUGIN_NAME

Statt PLUGIN_NAME gibt man den Namen eines der im Unterverzeichnis dictmaster/plugins verfügbaren Plugins (ohne Dateiendung) an, etwa acadfran.

Die Funktionsweise der Software

dictmaster bezieht die Wörterbuchdaten direkt von der entsprechenden Onlinequelle. Das kann eine große Zip-Datei sein (etwa bei xmlittre oder beim CIA World Factbook factbook), meistens werden allerdings einige Bots parallel damit beschäftigt, die Wörterbuchdaten aus dem HTML-Code existierender Online-Angebote zu extrahieren (etwa bei zeno). Die Rohdaten werden lokal in einer sqlite-Tabelle gespeichert (Datei db.sqlite im Ausgabeverzeichnis).

Nach dem Download bringt das Tool die Rohdaten in ein (HTML-)Format, das von Wörterbuch-Apps wie FireDict ansprechend dargestellt wird. Oft ist das Ausgabeformat schöner und übersichtlicher als die Vorlage.

Auch das Wörterbuch selbst wird zunächst in eine sqlite-Tabelle geschrieben, in der Duplikate, Synonyme und andere Querbeziehungen schnell aufgearbeitet werden können. Schließlich folgt die Ausgabe im Stardict-Format (Dateien stardict.* im Ausgabeverzeichnis).

Der Prozess kann an den meisten Stellen mittels Strg+c problemlos unterbrochen und zu einem späteren Zeitpunkt fortgesetzt werden.

Bedienung über die Kommandozeile

Neben dem oben erwähnten Namen des gewünschten Plugins müssen oft weitere pluginspezifische Parameter mittels der Option --popts übergeben werden, etwa

./dictmaster.py zeno --popts "Georges-1913"

Mit der Option --output (bzw. kurz -o) kann man den Pfad zum gewünschten Ausgabeverzeichnis angeben und mittels --reset kann man das vorherige Leeren des Ausgabeverzeichnisses erzwingen (zuvor bereits heruntergeladene Daten werden dabei gelöscht!).

./dictmaster.py xmlittre -o "$HOME/Wörterbücher/Littré"
./dictmaster.py folkets --popts "Sv-En" --reset

Ohne die Option -o wird ./data/<pluginname>/ als Ausgabeverzeichnis angenommen. Benötigt ein Plugin die Angabe weiterer Parameter mittels --popts, teilt es einem das gewöhnlich mit.

Eine Übersicht über alle Optionen erhält man mit

./dictmaster.py --help

Blick in die Zukunft

Das Projekt ist auf FramaGit beheimatet[1] und befindet sich aktuell noch in einem recht frühen Entwicklungsstadium. Die Erstellung neuer Plugins ist freilich nicht so einfach, wie sie sein könnte. Auf der anderen Seite stehen rechtliche Bedenken: Im Prinzip verstehe ich dictmaster als eine Art Online-Recorder für Wörterbücher. Nicht alle Wörterbücher, die mit dictmaster bezogen werden können, stehen allerdings unter freien Lizenzen. Unternehmen wie Google, die eigene Webcrawler einsetzen, betreiben praktisch ebenfalls Online-Recording - lediglich in einem weitaus gigantischeren Maßstab. Man sollte aber immer bedenken, dass die mit dictmaster bezogenen Inhalte meistens nicht für die Weitergabe bestimmt sind. Das Urheberrecht bleibt natürlich bei den Autoren der jeweiligen Wörterbücher und es gelten die entsprechenden Lizenzbestimmungen.

  1. framagit.org/tuxor1337/dictmaster

Kommentare

David 30. März 2016

Vielen Dank für dieses sehr nützliche Skript! Ich kriege es aber noch nicht zum Laufen und kenne mich leider zu wenig aus, um die Fehlermeldung zu verstehen.

Meine Eingabe lautet (im Verzeichnis des Skripts):

python2 ./dictmaster.py dwds --popts ./thirdparty/wordlists/deu/dwds.txt 32

Die Daten werden heruntergeladen, dann aber kommt folgende (Fehler)meldung:

Running plugin 'dwds'.

Processing... a: 0Exception in thread Thread-4:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/home/david/programme/dictmaster/dictma ster/postprocessor.py", line 48, in run
self.process()
File "/home/david/programme/dictmaster/dictma ster/postprocessor.py", line 166, in process
self.do_html(doc)
File "/home/david/programme/dictmaster/dictma ster/postprocessor.py", line 215, in do_html
self.append(doc(container), doc(container))
File "/home/david/programme/dictmaster/dictma ster/postprocessor.py", line 178, in append
definition = self.do_html_definition(dd, term)
File "/home/david/programme/dictmaster/dictma ster/plugins/dwds.py", line 152, in do_html_definition_32
doc("*").removeAttr("class").removeAttr( "id").removeAttr("onclick")
File "/usr/lib/python2.7/dist-packages/pyquery/pyquery.py", line 739, in removeAttr
del tag.attrib[name]
File "lxml.etree.pyx", line 2311, in lxml.etree._Attrib.__delitem__ (src/lxml/lxml.etree.c:61224)
File "apihelpers.pxi", line 567, in lxml.etree._delAttribute (src/lxml/lxml.etree.c:19716)
KeyError: 'class'
done.
filename=data/dwds/32/stardict.ifo
done.

Plugin 'dwds' quit.

Bin für jeden Hinweis dankbar!

Vielen Dank,

David




Administrator 3. Januar 2016

Auf dwds.de sind mehrere Wörterbücher gehostet. Neben dem Digitalen Wörterbuch der Deutschen Sprache (Panel ID 5) unterstützt dictmaster.py auch das etymologische Wörterbuch von Dr. Pfeiffer (Panel ID 32). Diese IDs sind interne Bezeichnungen von dwds.de. In Zukunft sollte ich da vielleicht aussagekräftigere Informationen ausgeben. (Nachtrag: Ist seit dem 12.01.2016 der Fall.)

Und richtig, Python 3 unterstütze ich aktuell noch nicht. Es gab da irgendwelche Probleme mit Unicode, wenn ich mich recht erinnere. Wer Lust hat, kann gerne einen python3-kompatiblen Fork erstellen.

Leo 2. Januar 2016

Natürlich funktioniert es, das Skript mit python2 auszuführen. Allerdings ist mir nicht klar, was die geforderte Panel ID meint:

python2 dictmaster.py dwds --popts "dwds"
LZO compression support is not available
Error: Expected exactly two plugin params: a word list file and a panel id.

Vielen Dank!

Leo 2. Januar 2016

Hallo,

vielen Dank für das Skript! Ich würde gerne eine offline Version des DWDS für GoldenDict verwenden. Beim Versuch, dictmaster.py auszuführen, gibt es Probleme mit dem Skript dictmaster/util.py, die nach einer kurzen Suche auf Kompatibilitätsprobleme von Python 2 und 3 (die print Funktion konnte ich anpassen) und urllib2 und urllib3.

Ich verwende Arch Linux und habe urllib3 installiert. Nachdem ich in dictmaster/util.py urllib2 mit urllib3 ersetzt habe, erhalte ich folgende Meldung beim Ausführen von dictmaster.py:

./dictmaster.py dwds
Traceback (most recent call last):
File "./dictmaster.py", line 7, in <module>
from dictmaster.util import load_plugin
File "/home/leo/dictmaster/dictmaster/util.py ", line 9, in <module>
from urllib3 import URLError, HTTPError
ImportError: cannot import name 'URLError'

Was sollte ich tun?

Viele Grüße
Leo
« 1 2
Neue Kommentare zu diesem Artikel bitte per Mail an kommentare-519(at)tovotu.de!