3 # :Copyright: © 2014 Günter Milde.
4 # Released without warranty under the terms of the
5 # GNU General Public License (v. 2 or later)
8 # wortfugen.py: Teste unkategorisierte Trennstellen auf Wortfugen
9 # ===============================================================
13 """Suche nach "Teilwortkandidaten" in der `Wortliste`"""
20 # Importiere Python Module::
22 import re
# Funktionen und Klassen für reguläre Ausdrücke
23 import sys
# sys.exit() zum Abbruch vor Ende (für Testzwecke)
25 from collections
import defaultdict
# Wörterbuch mit Default
26 from copy
import deepcopy
28 from werkzeug
import WordFile
, join_word
, udiff
29 from analyse
import read_teilwoerter
, teilwoerter
30 from abgleich_teilwoerter
import wortliste_to_teilwoerter
32 # sys.stdout mit UTF8 encoding.
33 sys
.stdout
= codecs
.getwriter('UTF-8')(sys
.stdout
)
41 # Die freie `Wortliste der deutschsprachigen Trennmustermannschaft`_
42 # ("Lembergsche Liste")::
44 wordfile
= WordFile('../../wortliste') # ≅ 400 000 Einträge/Zeilen
49 # Sprach-Tag nach [BCP47]_::
51 # sprachvariante = 'de-1901' # "traditionell"
52 sprachvariante
= 'de-1996' # Reformschreibung
53 # sprachvariante = 'de-x-GROSS' # ohne ß (Großbuchstaben und Kapitälchen)
54 # sprachvariante = 'de-1901-x-GROSS' # ohne ß (Schweiz oder GROSS)
55 # sprachvariante = 'de-1996-x-GROSS' # ohne ß (Schweiz oder GROSS)
56 # sprachvariante = 'de-CH-1901' # ohne ß (Schweiz) ("süssauer")
60 # Verwende die Wortliste oder die mit ``analyse.py`` generierte Teilwortliste
61 # als Quelle der kategorisierten Trennungen::
63 use_teilwoerter
= False
64 # use_teilwoerter = True
65 # use_teilwoerter = None # use spelldict
67 # Textdateien mit Wortbestandteilen
68 # ---------------------------------
70 # * Ein Wortteil/Zeile
71 # * Groß/Kleinschreibung unterschieden
72 # * Kodierung: utf8 (bis auf 'ogerman')
74 # Wörterbucher für die Rechtschreibprüfprogramme Ispell/Aspell
75 # Unterscheiden Groß-/Kleinschreibung und beinhalten auch kurze Wörter. ::
77 def wortdatei(wortfile
, encoding
='utf8'):
78 for line
in open(wortfile
):
79 yield line
.rstrip().decode(encoding
)
81 if use_teilwoerter
is None:
82 if sprachvariante
== 'de-1996':
83 spellfile
= '../../spell/hunspell-%s'%sprachvariante
85 spellfile
= '../../spell/aspell-%s'%sprachvariante
87 spelldict
= set(w
for w
in wortdatei(spellfile
)
90 # print "spelldict", len(spelldict)
94 # Entferne Wörter/Silben, die (fast) nie in Wortverbindungen vorkommen
95 # TODO: Solitäre aus einer Datei lesen. ::
97 for solitaer
in ('baren', 'RAF'):
98 spelldict
.discard(solitaer
)
100 # Präfixe (auch als Präfix verwendete Partikel, Adjektive, ...)::
102 praefixe
= set(w
for w
in wortdatei('wortteile/praefixe'))
104 # Präfixe die keine selbständigen Wörter sind::
106 vorsilben
= set(w
for w
in wortdatei('wortteile/vorsilben'))
108 # Erstsilben: Wörter, die häufig als erste
109 # Silbe eines Wortes (aber nicht oder nur selten als Teilwörter) auftreten
110 # aber keine Vorsilben sind ::
112 erstsilben
= set(w
for w
in wortdatei('wortteile/erstsilben'))
114 # Endsilben, die keine eigenständigen Wörter sind
115 # (nicht (nur) Endungen im morphologischen Sinne, sondern ganze Silben)::
117 endsilben
= set(w
for w
in wortdatei('wortteile/endsilben'))
120 # Einträge der "Wortliste"
121 # ------------------------
124 wordfile
= WordFile('../../wortliste') # ≅ 400 000 Einträge/Zeilen
125 wortliste
= list(wordfile
)
127 # Sammeln unbekannter Wortteile::
129 unbekannt1
= defaultdict(list)
130 unbekannt2
= defaultdict(list)
132 # Wörterbuch zum Aufsuchen der Teilwörter
133 # ---------------------------------------
136 words
= read_teilwoerter(path
='teilwoerter-%s.txt'%sprachvariante
)
137 words
= set(words
.trennvarianten
.keys())
138 elif use_teilwoerter
is False: # Gesamtwörter als "Teilwörter":
139 words
= wortliste_to_teilwoerter(wortliste
, sprachvariante
)
140 words
= set(words
.trennvarianten
.keys())
145 # 2. Durchlauf: Analyse
146 # =====================
148 # Durchlaufe alle Einträge::
150 wortliste_neu
= deepcopy(wortliste
)
152 for entry
in wortliste_neu
:
154 # Wort mit Trennungen in Sprachvariante::
156 wort
= entry
.get(sprachvariante
)
157 if wort
is None: # Wort existiert nicht in der Sprachvariante
160 # Spezielle Teilwörter suchen::
162 # teile = wort.split(u'-')
163 # if teile[-1] == 'burg':
164 # print ('-'.join(teile[:-1]) + '=' + teile[-1])
167 if u
'·' not in wort
: # keine unkategorisierte Trennstelle
170 # Trenne an unkategorisierten Trennstellen (markiert durch '·')::
172 teile
= wort
.split(u
'·')
174 # Wortteile analysieren::
176 for i
in range(1,len(teile
)):
177 erstwort
= u
'·'.join(teile
[:i
])
178 zweitwort
= u
'·'.join(teile
[i
:])
180 # Key: Teilwort ohne Trennung, Groß/Kleinschreibung übertragen::
183 erstkey
= join_word(erstwort
)
184 zweitkey
= join_word(zweitwort
)
185 except AssertionError, e
: # Spezialtrennung
188 if wort
[0].istitle():
189 zweitkey
= zweitkey
.title()
194 # Blöcke zur regelbasierten Kategorisierung.
195 # Zum Auskommentieren und Anpassen.
197 # Fugen-s o.ä. weglassen oder hinzufügen::
199 # erstkey = erstkey[:-1]
200 # erstkey = erstkey + 's'
204 if ((erstkey
in words
205 or erstkey
.lower() in words
206 or erstkey
.upper() in words
)
207 and erstkey
not in erstsilben
208 and erstkey
.lower() not in vorsilben
209 and erstkey
.lower() not in praefixe
212 or zweitkey
.lower() in words
213 or zweitkey
.upper() in words
)
214 and zweitkey
.lower() not in endsilben
216 compound
= '='.join((erstwort
, zweitwort
.lower()))
217 print u
'%-30s %-15s %s'% (compound
, erstkey
,zweitkey
)
218 entry
.set(compound
, sprachvariante
)
222 # if (erstkey in vorsilben
223 # # and zweitkey in words
225 # print str(entry), (u'%s<%s'% (erstkey,zweitwort))
226 # entry.set('-'.join((erstwort, zweitwort)), sprachvariante)
230 # if (erstkey in words
231 # and zweitkey.lower() in endsilben
233 # print str(entry), (u'%s-%s'% (erstkey,zweitwort))
234 # entry.set('-'.join((erstwort, zweitwort)), sprachvariante)
239 # if (erstkey in erstsilben or erstkey in vorsilben):
240 # print str(entry), (u'%s-%s'% (erstkey,zweitwort))
241 # entry.set('-'.join((erstwort, zweitwort)), sprachvariante)
243 # # Neueintragskandidaten::
245 # if (erstkey not in words
246 # and erstkey not in vorsilben
247 # and erstkey not in erstsilben
249 # unbekannt1[erstwort].append(wort)
251 # elif (zweitkey not in words
252 # and zweitkey.lower() not in endsilben
254 # unbekannt2[zweitwort].append(wort)
256 # print ("%s-%s %s" % (erstwort, zweitwort, entry))
262 # Unbekannte Teilwörter/Silben::
264 def testausgabe(unbekannt
):
265 checkliste
= ['%3d %s %s' % (len(unbekannt
[key
]), key
,
266 ','.join(unbekannt
[key
]))
267 for key
in sorted(unbekannt
.keys())]
269 return u
'\n'.join(checkliste
) + '\n'
273 print testausgabe(unbekannt1
)
275 print testausgabe(unbekannt2
)
278 # Ein Patch für die wortliste::
280 patch
= udiff(wortliste
, wortliste_neu
,
281 wordfile
.name
, wordfile
.name
+'-neu',
282 encoding
=wordfile
.encoding
)
286 patchfile
= open('wortliste.patch', 'w')
287 patchfile
.write(patch
+ '\n')
289 print u
'keine Änderungen'