From f4172c1af6b36605f624ceba34689c5c16a16150 Mon Sep 17 00:00:00 2001 From: Guenter Milde Date: Fri, 16 May 2014 11:57:31 +0200 Subject: [PATCH] Skripte zum Abgleich mit externen Wortlisten. --- skripte/python/abgleich_neueintraege.py | 366 ++++++++++++++++++++++++++++++++ skripte/python/expand_teilwoerter.py | 80 +++---- skripte/python/spellcheck.py | 75 +++++++ 3 files changed, 485 insertions(+), 36 deletions(-) create mode 100644 skripte/python/abgleich_neueintraege.py create mode 100644 skripte/python/spellcheck.py diff --git a/skripte/python/abgleich_neueintraege.py b/skripte/python/abgleich_neueintraege.py new file mode 100644 index 0000000..f64ca63 --- /dev/null +++ b/skripte/python/abgleich_neueintraege.py @@ -0,0 +1,366 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- +# :Copyright: © 2011 Günter Milde. +# Released without warranty under the terms of the +# GNU General Public License (v. 2 or later) +# :Id: $Id: $ + +# Versuche Trennstellen neuer Wörter aus vorhandenen zu ermitteln +# =============================================================== +# +# Übertragen von kategorisierten Trennstellen vorhandener Wörter +# auf neu aufzunehmende, ungetrennte Wörter. +# +# Erwartet eine Datei mit 1 Wort/Zeile. + +# Erstellt einen Patch mit den Wörtern, welche durch Abgleich mit der +# Datenbasis getrennt werden konnten. +# :: + +import re, sys, codecs, copy, os +from werkzeug import WordFile, WordEntry, join_word, toggle_case +# sort.py im Überverzeichnis: +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +from sort import sortkey_duden + +# Konfiguration +# ------------- +# +# Sprachvarianten +# ~~~~~~~~~~~~~~~ +# Sprach-Tag nach [BCP47]_:: + +# sprachvariante = 'de-1901' # "traditionell" +sprachvariante = 'de-1996' # Reformschreibung +# sprachvariante = 'de-1901-x-GROSS' # ohne ß (Schweiz oder GROSS) +# sprachvariante = 'de-1996-x-GROSS' # ohne ß (Schweiz oder GROSS) +# sprachvariante = 'de-CH-1901' # ohne ß (Schweiz) ("süssauer") + +# Funktionen +# ----------- +# +# Übertrag von Einträgen auf Wörter mit anderer Endung:: + +def endungsabgleich(key, alt, neu, grossklein=False): + + if not key.endswith(join_word(neu)): + return '' + + altkey = key[:-len(join_word(neu))] + join_word(alt) + if grossklein: + altkey = toggle_case(altkey) + + try: + altentry = words[altkey] + except KeyError: + return '' + + entry = WordEntry(key) + # print "fundum", key, unicode(entry) + for wort in altentry[1:]: + if not wort.startswith(u'-'): + if alt: + wort = wort[:-len(alt)] + wort += neu + if grossklein: + wort = toggle_case(wort) + if join_word(wort) != key: + print u"# Übertragungsproblem: %s -> %s (%s,%s) %s" % ( + altkey, key, alt, neu, wort) + return '' + entry.append(wort) + + return entry + + +# Endungen +# -------- +# ``(, )`` Paare von Endungen +# +# Achtung: die Auswahl zu testender Wörter erfolgt anhand der "neu"-Endung. +# Daher darf diese nicht leer sein! +# :: + +endungen = [ + (u'', u'-de'), + # (u'', u'-en'), + # (u'', u'-er'), + # (u'', u'-is-mus'), + # (u'', u'-ität'), + (u'', u'-lein'), + (u'', u'-ne'), + (u'', u'-nem'), + (u'', u'-nen'), + (u'', u'-ner'), + (u'', u'-sche'), + (u'', u'-tum'), + (u'', u'>ar-tig'), + (u'', u'>chen'), + (u'', u'>heit'), + (u'', u'>keit'), + (u'', u'>schaft'), + (u'', u'>schaft'), + (u'', u'>weise'), + # (u'', u'd'), + # (u'', u'e'), + # (u'', u'e-rin'), + # (u'', u'er'), + # (u'', u'is-mus'), + # (u'', u'm'), + # (u'', u'n'), + # (u'', u'ner'), + # (u'', u'r'), + # (u'', u's'), + # (u'', u's-te'), + # (u'', u's-te'), + # (u'', u's>los'), + # (u'', u'st'), + # (u'', u't'), + # (u'', u't-te'), + (u'-al', u'a-le'), + (u'-an', u'a-ne'), + (u'-at', u'a-te'), + (u'-ben', u'b-ne'), + # (u'-che', u'ch'), + (u'-de', u'd'), + (u'-en', u'>bar>keit'), + # (u'-en', u'e'), + (u'-en', u'e-ne'), + (u'-er', u'e-rei'), + (u'-er', u'e-rin'), + (u'-ern', u'e-re'), + (u'-ge', u'g'), + (u'-gen', u'g'), + (u'-in', u'i-ne'), + (u'-on', u'o-nen'), + (u'-re', u'r'), + (u'-re', u'rt'), + (u'-ren', u'r-ne'), + (u'-ren', u'rt'), + (u'-sche', u'sch'), + (u'-sen', u's-ne'), + (u'-sten', u's-mus'), + (u'-te',u't'), + (u'-tern', u't-re'), + (u'-ös', u'ö-se'), + (u'a', u'-ar'), + (u'a', u'-as'), + (u'b', u'-be'), + (u'b', u'-ber'), + (u'bar', u't'), + (u'bt', u'b-te'), + (u'ce', u'-cen'), + (u'ch', u'-che'), + (u'ch', u'-cher'), + (u'ck', u'-cke'), + (u'ck', u'-cker'), + (u'd', u'-de'), + (u'd', u'-dem'), + (u'd', u'-den'), + (u'd', u'-der'), + (u'd', u'-des'), + (u'd', u'>heit'), + (u'e', u'-en'), + (u'e-ren', u'-ti-on'), + (u'e-ren', u'sch'), + (u'el', u'le'), + # (u'en', u'e'), + (u'en', u'em'), + (u'en', u'en-de'), + (u'en', u'end'), + (u'en', u'er'), + (u'en', u'es'), + (u'en', u'est'), + (u'en', u't'), + (u'en', u'te'), + (u'en', u'us'), + (u'end',u'en' ), + # (u'er', u'e'), + (u'er', u'e-rei'), + (u'er', u'ens'), + (u'er', u'in'), + (u'er', u'ung'), + (u'es', u'est'), + (u'es', u's-te'), + (u'f', u'-fe'), + (u'f', u'-fer'), + (u'g', u'-ge'), + (u'g', u'-gen'), + (u'g', u'-ger'), + (u'g', u'-ger'), + (u'g', u'-ges'), + (u'g', u'-gung'), + (u'ie', u'e'), + (u'in', u'en'), + (u'isch', u'i-sche'), + (u'k', u'-ke'), + (u'k', u'-ken'), + (u'k', u'-ker'), + (u'l', u'-le'), + (u'l', u'-len'), + (u'l', u'-ler'), + (u'l', u'-lis-mus'), + (u'le', u'-ler'), + (u'li-che', u'tem'), + (u'li-che', u'ten'), + (u'ln', u'-le'), + (u'lt', u'-le'), + (u'm', u'-me'), + (u'm', u'-mer'), + (u'me', u'-men'), + (u'mus', u'men'), + (u'mus', u'ten'), + (u'mus', u'tik'), + (u'n', u'-at'), + (u'n', u'-er'), + (u'n', u'-ne'), + (u'n', u'-nen'), + (u'n', u'-nis-mus'), + (u'n', u'r'), + (u'n', u'st'), + (u'n', u't'), + (u'n',u'-ner'), + (u'nd',u'n'), + (u'ne',u'ner'), + # (u'ne',u'n'), + (u'o',u'-on'), + (u'o',u'-os'), + (u'o',u'en'), + (u'on',u'o-nen'), + (u'p', u'-pe'), + (u'p', u'-pen'), + (u'p', u'-per'), + (u'ph', u'-phen'), + (u'ph', u'-phis-mus'), + (u'r', u'-re'), + (u'r', u'-rei'), + (u'r', u'-ren'), + (u'r', u'-rin'), + (u'r', u'-ris-mus'), + (u'r', u'-rung'), + (u're', u'ste'), + (u'ren', u'r-te'), + (u'ren', u'rst'), + (u'ren', u'rt'), + (u'rn', u'-re'), + (u'rn', u'-rung'), + (u'rn', u'-rung'), + (u'rt', u'-re'), + (u'rt', u'r-te'), + (u's', u''), + (u's', u'-se'), + (u's', u'-se-re'), + (u's', u'-se-res'), + (u's', u'-ser'), + (u's', u's-se'), + (u's', u's-ses'), + (u'sch', u'-sche'), + (u'sch', u'-schen'), + (u'sch', u'-scher'), + (u'st', u'-ste'), + (u'st', u'-sten'), + (u'st', u'n'), + (u't', u'-ba-re'), + (u't', u'-bar'), + (u't', u'-te'), + (u't', u'-te'), + (u't', u'-ten'), + (u't', u'-ter'), + (u't', u'-tes'), + (u't', u'-tin'), + (u't', u'-tis-mus'), + # (u't', u'e'), + (u't', u'n'), + (u't', u'st'), + (u'te', u'le'), + # (u'te', u't'), + (u'ten', u'mus'), + (u'ten', u'ren'), + (u'ten', u'tung'), + (u'ter', u'te-ren'), + (u'ti-on', u'tor'), + (u'um', u'a'), + (u'us', u'en'), + (u'v', u'-ve'), + (u'v', u'-ver'), + (u'v', u'-vis-mus'), + (u'-ve', u'v'), + (u'z', u'-ten'), + (u'z', u'-ze'), + (u'z', u'-zen'), + (u'z', u'-zer'), + (u'ß', u'-ße'), + (u'ß', u's-se'), + (u'ös', u'ö-se'), + ] + +if __name__ == '__main__': + + # sys.stdout mit UTF8 encoding. + sys.stdout = codecs.getwriter('UTF-8')(sys.stdout) + +# `Wortliste` einlesen:: + + wordfile = WordFile('wortliste-expandiert') # + Teilwort-Entries + words = wordfile.asdict() + + neuwortdatei = open("zusatzwörter-de-1996-hunspell-compact") + neueintraege = [] + neueintraege_grossklein = [] + +# Erstellen der neuen Einträge:: + + for line in neuwortdatei: + key = line.decode('utf8').strip() + + if len(key) <= 3: + continue + +# Test auf vorhandene (Teil-) Wörter: + + try: + entry = words[key] + neueintraege.append(entry) + continue + except KeyError: + pass + # kleingeschrieben + try: + entry = words[key.lower()] + neueintraege_grossklein.append(entry) + continue + except KeyError: + pass + # Großgeschrieben + try: + entry = words[key.title()] + neueintraege_grossklein.append(entry) + continue + except KeyError: + pass + + # Endungsabgleich:: + + for alt, neu in endungen: + entry = endungsabgleich(key, alt, neu, grossklein=False) + if entry: + neueintraege.append(entry) + # break + + for alt, neu in endungen: + entry = endungsabgleich(key, alt, neu, grossklein=True) + if entry: + neueintraege_grossklein.append(entry) + # break + + +# Patch erstellen:: + + print u'# als Teilwörter' + for entry in neueintraege: + print unicode(entry) + print + print u'# als Teilwörter (andere Großschreibung)' + for entry in neueintraege_grossklein: + print unicode(entry) + diff --git a/skripte/python/expand_teilwoerter.py b/skripte/python/expand_teilwoerter.py index 5bce7b3..e35b723 100644 --- a/skripte/python/expand_teilwoerter.py +++ b/skripte/python/expand_teilwoerter.py @@ -7,12 +7,12 @@ # Erweitern der Wortliste um Kombinationen von Teilwörtern # ======================================================== -# +# # Zerlegen von Composita an den Wortfugen und Übernahme der Teile als # eigenständige Einträge. - +# # >>> from expand_teilwoerter import * - +# # :: import os, re, sys, codecs, copy @@ -25,30 +25,30 @@ from sort import sortkey_duden # Funktionen # ----------- - +# # Iterator, gibt alle geordneten Teilkombinationen zurück - +# # >>> list(multisplitter(u'test', u'=')) # [u'test'] - +# # >>> list(multisplitter(u'a=b', u'=')) # [u'a', u'a=b', u'b'] - +# # >>> list(multisplitter(u'a=b=c', u'=')) # [u'a', u'a=b', u'a=b=c', u'b', u'b=c', u'c'] - +# # >>> list(multisplitter('a=b=c=d', '=')) # ['a', 'a=b', 'a=b=c', 'a=b=c=d', 'b', 'b=c', 'b=c=d', 'c', 'c=d', 'd'] - +# # >>> list(multisplitter(u'a=b==c', u'==')) # [u'a=b', u'a=b==c', u'c'] - +# # >>> list(multisplitter('a=b==c=de', '==')) # ['a=b', 'a=b==c=de', 'c=de'] - +# # >>> list(multisplitter('a=b==c=de', '===')) # ['a=b==c=de'] - +# # >>> list(multisplitter('er[>> list(multisplitter('Schiff[=s/s=]tau', u'=')) @@ -57,7 +57,7 @@ from sort import sortkey_duden # [u'a{ll/ll=l}ie-bend'] # >>> list(multisplitter('Be[t=t/{tt/tt=t}]uch', u'=')) # [u'Be[t=t/{tt/tt=t}]uch'] - +# # :: def multisplitter(wort, sep): @@ -77,22 +77,22 @@ def multisplitter(wort, sep): # Gib eine Liste möglicher Zerlegungen eines Kompositums zurück. # Berücksichtige dabei die Bindungsstärke bis zum Level 3 # ("===", zur Zeit höchste Auszeichnung in der Wortliste). - +# # >>> multisplit(u'test') # [u'test'] - +# # >>> multisplit(u'a=b') # [u'a', u'a=b', u'b'] - +# # >>> multisplit(u'a=b=c') # [u'a', u'a=b', u'a=b=c', u'b', u'b=c', u'c'] - +# # >>> multisplit(u'a==b=c') # [u'a', u'a==b=c', u'b', u'b=c', u'c'] - +# # >>> multisplit(u'a==b=c==d') # [u'a', u'a==b=c', u'a==b=c==d', u'b', u'b=c', u'c', u'b=c==d', u'd'] - +# # >>> for w in multisplit(u'Brenn=stoff==zel-len===an>> from werkzeug import WordEntry -# +# # >>> split_entry(WordEntry(u'Aachen;Aa-chen')) # [[u'Aachen', u'Aa-chen']] # >>> aalbestand = WordEntry(u'Aalbestand;Aal=be>> split_entry(aalbestand) # [[u'Aal', u'Aal'], [u'Aalbestand', u'Aal=be>> godi = WordEntry(u'Abendgottesdienste;-2-;Abend==got-tes=dien-ste;Abend==got-tes=diens-te') # >>> for entry in split_entry(godi): # ... print entry @@ -139,14 +139,14 @@ def multisplit(wort): # Gottes;-2-;Got-tes;Got-tes # Gottesdienste;-2-;Got-tes=dien-ste;Got-tes=diens-te # Dienste;-2-;Dien-ste;Diens-te - +# # >>> bb = WordEntry(u'Biberbettuch;-2-;Bi-ber==be[t=t/{tt/tt=t}]uch') # >>> for entry in split_entry(bb): # ... print entry # Biber;-2-;Bi-ber # Biberbettuch;-2-;Bi-ber==be[t=t/{tt/tt=t}]uch # Bettuch;-2-;Be[t=t/{tt/tt=t}]uch - +# # :: def split_entry(entry): @@ -169,21 +169,16 @@ def split_entry(entry): entries[i][col] = parts[i] if entries: + for e in entries: + e.conflate_fields() # Sprachabgleich return entries else: return [entry] +# Gib ein Dictionary mit Einträgen der Wortliste und Teilwortkombinationen zurück: - -if __name__ == '__main__': - - # sys.stdout mit UTF8 encoding. - sys.stdout = codecs.getwriter('UTF-8')(sys.stdout) - -# `Wortliste` einlesen:: - - wordfile = WordFile('../../wortliste') # ≅ 400 000 Einträge/Zeilen - words = {} +def expand_wordfile(wordfile): + words = {} # Wörter aus der Liste for entry in wordfile: try: @@ -192,10 +187,23 @@ if __name__ == '__main__': print "problematisch", unicode(entry) words[entry[0].lower()] = entry continue + for e in entries: if len(entries) == 1 or e[0].lower() not in words: words[e[0].lower()] = e + + return words + +if __name__ == '__main__': + + # sys.stdout mit UTF8 encoding. + sys.stdout = codecs.getwriter('UTF-8')(sys.stdout) + +# `Wortliste` einlesen:: + wordfile = WordFile('../../wortliste') # ≅ 400 000 Einträge/Zeilen + + words = expand_wordfile(wordfile) print len(words), "expandiert" @@ -203,5 +211,5 @@ if __name__ == '__main__': for entry in sorted(words.values(), key=sortkey_duden): - outfile.write(unicode(entry).encode('utf8')) + outfile.write(str(entry)) outfile.write('\n') diff --git a/skripte/python/spellcheck.py b/skripte/python/spellcheck.py new file mode 100644 index 0000000..273b6fb --- /dev/null +++ b/skripte/python/spellcheck.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- +# :Copyright: © 2011 Günter Milde. +# Released without warranty under the terms of the +# GNU General Public License (v. 2 or later) +# :Id: $Id: $ + +# "Korporavergleich (Wortliste vs. diverse Rechtschreibprüfprogramme) +# =================================================================== +# +# Liste Differenz der Stichproben in der "wortliste" und dem "Dumping" von +# aspell/hunspell. +# +# :: + +import re, sys, codecs, copy +from werkzeug import WordFile, WordEntry, join_word, udiff +# from abgleich_teilwoerter import wortliste_to_teilwoerter + +# Konfiguration +# ------------- +# +# Sprachvarianten +# ~~~~~~~~~~~~~~~ +# Sprach-Tag nach [BCP47]_:: + +# sprachvariante = 'de-1901' # "traditionell" +sprachvariante = 'de-1996' # Reformschreibung +# sprachvariante = 'de-1901-x-GROSS' # ohne ß (Schweiz oder GROSS) +# sprachvariante = 'de-1996-x-GROSS' # ohne ß (Schweiz oder GROSS) +# sprachvariante = 'de-CH-1901' # ohne ß (Schweiz) ("süssauer") + +# Vergleichsbasis +# ~~~~~~~~~~~~~~~ +# +# :: + +spelldatei = '../../spell/aspell-de-1996-compact' + + +# Funktionen +# ----------- +# :: + +if __name__ == '__main__': + + # sys.stdout mit UTF8 encoding. + sys.stdout = codecs.getwriter('UTF-8')(sys.stdout) + +# `Wortliste` einlesen:: + + wordfile = WordFile('../../wortliste') + words = wordfile.asdict() + +# Vergleichswörter einlesen:: + + for line in open(spelldatei, 'r'): + # if line.startswith('#'): + # continue + # Dekodieren, Zeilenende entfernen + line = line.decode('utf8').strip() + # Tags entfernen (bei "-compact") + key = line.split(u'/')[0] + + # kurze Wörter haben wir nicht: + if len(key) < 4: + continue + + if (key not in words + and key.lower() not in words + and key.title() not in words): + + print key + + -- 2.11.4.GIT