special characters HTML und Unicode

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Daikoku
User
Beiträge: 66
Registriert: Montag 20. April 2015, 21:14

Hallo,

ich habe einen String der special characters enthält.

Beispiel :

Code: Alles auswählen

# Eine wahllose Aneinanderreihung von characters.
# Der Inhalt der Strings ergeben keinen Sinn. Sie dienen nur zur Beschreibung meines Problems.

# This string shows HTML entities.
html_chars = '"'&> ý' 

# This string shows Unicode characters.
uft8_chars = '\xc3\x80\xc3\x81\xc3\x82\xc2\xa9\xc4\x80\xc5\x81\xc6\x80\xc8\x80'
Meine Frage ist :
Gibt es ein Python Modul welches diese characters übersetzt, also Umwandelt.

Ich hätte gerne zum Beispiel :
Æ in AE
Ç in C
Ð in D

Oder muss ich mir für dieses Problem eine eigene Lösung exakt auf meine Wünsche hin selber erarbeiteten ?
Gibt es irgendwelche Gepflogenheiten oder gar verbindliche Regeln, die ich beim Umwandeln beachten sollte ?

Mir ist durchaus bewusst, das sich Umwandeln zuerst einmal trivial anhört, aber dann doch sehr schnell
durchaus sehr komplex werden kann.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Zu den HTML-Entities:

Code: Alles auswählen

import HTMLParser

html_chars = '"'&> ý'
parser = HTMLParser.HTMLParser()
print parser.unescape(html_chars)
Und was die UTF-8 Zeichen angeht:

Code: Alles auswählen

utf8_chars = '\xc3\x80\xc3\x81\xc3\x82\xc2\xa9\xc4\x80\xc5\x81\xc6\x80\xc8\x80'
decoded = utf8_chars.decode('utf-8')
Oder meintest du im zweiten Fall etwas anderes?
BlackJack

@Daikoku: Und wenn Du dann Unicode statt Entities oder UTF-8 hast, hilft vielleicht das unidecode-Modul (bedingt) weiter.
Daikoku
User
Beiträge: 66
Registriert: Montag 20. April 2015, 21:14

@BlackJack Vielen Dank für Deinen Hinweis, ich werde mir das einmal anschauen.

@snafu und Alle: Der Lösungsvorschlag von snafu ist genau der, welcher ich gesucht habe. Danke.

Aber wie immer im Leben, war das nur der erste Schritt zur Lösung meines Problems.
Ich werde später noch einmal darauf zurück kommen.

Vorher habe ich eine andere Frage.

Code: Alles auswählen

import HTMLParser
parser = HTMLParser.HTMLParser()
parser.unescape()
Ich kann das in der Dokumentation leider nicht finden.
https://docs.python.org/2/library/htmlparser.html

Mich interessiert zum Beispiel, ob dieses Modul, alle HTML character entities berücksichtigt.
Wenn, Nein welche Ausnahmen gibt es ? und wo stehen dieses geschrieben ?
Meine Referenz : https://en.wikipedia.org/wiki/List_of_X ... references

Kann ich das Modul einfach so benutzen, oder muss ich mir auch Gedanken über eine try, exception Lösung machen ?

zu str.decode([encoding[, errors]]):

Das encoding in der Funktion ist soweit klar, und der error default value ist strict.
Wie müsste ein Text-String aussehen, damit eine error exception ausgelöst wird ?
Vielleicht ist für meine Lösung ignore oder replace der besserer Weg ?

Irgendwo steht geschrieben Python wäre eine einfach zu lernende Sprache.
Ob etwas einfach oder schwer ist, ist an sich nicht das wirkliche Problem,
sondern der Weg zur Lösung mit all seine Details die es dabei zu bedenken gilt.
Aus einem schlechten Weg kann auch eine einfach zu lernende Sprache kein gutes Ergebnis machen.

Nochmals vielen Dank, für eure Hilfestellungen.
BlackJack

@Daikoku: Use the source. :-) In der `unescape()`-Methode wird das `htmlentitydefs`-Modul verwendet welches HTML 4.0 abdecken sollte und die Methode fügt da noch ''' hinzu was in XHTML 1.0 hinzugekommen ist.

Um Ausnahmen muss man sich eigentlich immer Gedanken machen wenn man sie sinnvoll behandeln kann und will. Wobei die Methode unbekannte Entities anscheinend einfach ignoriert.

Ein Bytestring führt zu einer Ausnahme bei `decode()` wenn die Bytes mit der angegeben Kodierung nicht dekodiert werden können. Bei UTF-8 zum Beispiel wenn die Daten kein gültiges UTF-8 sind, bei ASCII wenn Bytewerte ausserhalb des ASCII-Wertebereichs vorkommen, und so weiter. Ob 'ignore' oder 'replace' besser geeignet wären kommt darauf an was Du im konkreten Fall bei kaputten Eingabedaten machen willst und ob ignorieren oder Ersatzzeichen dabei tatsächlich Sinn machen.

Man kann in Python lesbaren Quelltext schreiben — ob die Sprache an sich deswegen einfach zu lernen ist… nun es gibt schwieriger zu lernende Sprachen. :-)
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Daikoku: Du hast völlig recht damit, dass man sich natürlich erstmal darüber im Klaren sein muss, ob es schon vorgefertigte Funktionalität für ein Problem gibt. Ohne entsprechende Kenntnisse hilft einem Pythons umfangreiche Standardbibliothek auch nicht weiter, weil man anfangs schlecht wissen kann, welche Funktion aus welchem Modul das eigene Problem denn nun lösen kann. Genau für sowas ist aber ja das Forum da.

Und behalte ruhig deinen Fragestil so bei, wie er ist. Es gibt genug Leute, die leisten weit weniger Eigenrecherche und Transferleistungen hinsichtlich des neu erworbenen Wissen, als du es tust. Es macht einfach viel mehr Spass zu antworten, wenn man das Gefühl hat, dass sein Gegenüber ein gewisses Maß an nötiger Intelligenz und die Fähigkeit des Mitdenkens mitbringt. Vielen Anfängern fehlt leider genau diese Eigenschaft.

Und noch ein heißer Tipp: Wenn dein Code komplexer wird und du zwar einerseits die Mittel der Standardbibliothek hinreichend ausschöpfst, aber trotzdem das Gefühl hast, dass bestimmt schon zig andere Leute etwas sehr ähnliches programmiert haben, dann ist sicherlich auch der Python Package Index einen Blick wert. Das ist, wie unschwer aus dem Namen zu erkennen ist, die Python-eigene Paketverwaltung. Da wird man oft fündig und kann sich dann entweder direkt das Paket installieren (normalerweise mithilfe des Shell-Tools `pip`) und/oder im Quelltext des Pakets nachsehen, wie jemand anders das Problem gelöst hat. Dies kann man dann ggf für die eigenen Zwecke angepasst übernehmen (dann aber natürlich die Lizenz des Quelltextes beachten) oder es als erste Inspiration für eine eigene Implementierung verwenden.
Daikoku
User
Beiträge: 66
Registriert: Montag 20. April 2015, 21:14

@BlackJack I use always the source, weil es ansonsten schwierig werden würde, ohne Sourcen ein Python-Programm zu benutzen. :wink:

O.K; I have take a glimpse into the source.
Take a glimpse, bitte nur verwenden, wenn man einen Hinweis mit einem Augenzwinkern geben möchte.
Catch a glimpse of, einen flüchtigen Blick auf etwas werfen,
Take a glimpse of, einen intensiven Blick auf etwas werfen,
Bei Etikette wahrenden Gespräche, bitte nicht verwenden, da dieses unhöflich wäre.

Ich habe mir HTMLParser.py und auch htmlentitydefs.py angesehen.
Um es kurz zu machen. unescape() ist nicht W3C konform. Gilt für HTML 4, XHTML 1.0 und HTML 5.
HTML 5 ist gar nicht vorhanden. In der W3C Doku zu HTML 5 steht, entity definitions derived von HTML 4.
Hilft mir an dieser Stelle, aber auch nicht wirklich weiter, da "derived" abgeleitet bedeutet.
Bei HTML 5 entities kann ein richtiges Ergebnis heraus kommen, muss aber nicht.
http://www.w3.org/TR/html5/syntax.html# ... references

Ich benutze Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on win32.
Bei Python 3 kann alles ganz Anders sein. Wer möchte kann einmal nach schauen :
Falls vorhanden in htmlentitydefs.py, ab Zeile 4 das dictionary muss einen key: 'ac;' mit dem value : 'U+0223E' beinhalten.
Wenn nicht vorhanden, gilt auch für Python 3 das gleiche wie für Python 2.

Aus meiner Sicht habe ich jetzt zwei Möglichkeiten:
1. Ich schaue ob es ein passendes Third-Party Module gibt, da ich mir nicht vorstellen kann, das ich der Erste bin, der so etwas braucht.
2. Ich muss mir eine eigene Lösung erarbeiten.

Kennt jemand ein Third-Party Module, bei dem es sich lohnen würde, einmal nach zu schauen ?
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Möglicherweise ist BeautifulSoup hier ganz hilfreich. Das kommt sowohl mit diversen Encodings als auch mit HTML Entities ganz gut klar. Doku gibt es hier.
Daikoku
User
Beiträge: 66
Registriert: Montag 20. April 2015, 21:14

@snafu Vielen Dank für Deine wohlwollende Worte.

@an Alle : Ich selber würde von jedem anderen, aber auch erwarten, dass er zu erst einmal darstellt, welche Überlegungen er selber zu einer möglichen Lösung bereits angestellt hat.
Wenn ich sinnvoll helfen soll, muss ich wissen, wo ich ihn abholen muss, um ihn zu einer möglichen Lösung hin führen zu können.

In einem anderen Threat, hatte ich deshalb einmal kurz gefragt, ob ich Quellen angeben darf.
z.B. ist stackoverflow.com eine Konkurrenz zu diesem Forum und es hätte durchaus sein können, das ein Hinweis darauf, nicht so gerne gesehen wird, oder ich permanent mein Wissen aus Quellen beziehe, welche nicht unbedingt zu empfehlen sind.

Wenn ich Code-Snippets poste, welche nicht von mir sind, gebe ich unter Umständen einen Wissensstand vor, den ich gar nicht habe und das führt dann dazu, dass ich antworten bekomme, die mir nicht wirklich weiter helfen.

Ich habe den heutigen Threat HILFE!!! gelesen.
Wenn sich die Einstellung dieser Personen nicht grundlegend ändert, wird bei dem Studium und später im Beruf nichts sinnvolles dabei raus kommen.
Immer nur einen Dummen suchen, der die gerade anliegenden Aufgabenstellungen für einen erledigt, führt zu keinem selbstbestimmten Leben und gibt einem auch nicht wirklich ein Gefühl der Gelassenheit und Zufriedenheit. Wenn dann auch noch Fehler passieren, waren es grundsätzlich immer die Anderen.
Es macht doch Spass, etwas neues zu lernen, Fehler zu machen, Irrtümer zu unterliegen, sich über Ergebnisse auszutauschen gerne auch kontrovers.
Ich könnte es auch kurz Interaktion nennen und dies macht einen doch nicht wirklich dümmer. Aber das ist meine persönliche Meinung, jedem das seine.

Doch zurück zu diesem Threat.
Ich werde mir einmal andere ThirdParty Produkte anschauen, aber ich befürchte, das ich mir eine eigene Lösung erarbeiten muss.
Vielleicht aber habe ich das Glück, das Rat nicht gänzlich neu erfinden zu müssen.

Das richtige encodieren ist essenziell wichtig für mich. Nachstehend einmal kurz dargestellt warum.

Ich habe Rohdaten, welche ich zu erst einmal aufbereiten muss, weil in diesen Daten special characters vor kommen, welche ich so nicht will.
Die aller meisten special characters sind eindeutig zu behandeln, andere sind aber nur einfach Müll.
Sei wie es sei, mit '"'&> ý' oder '\xc3\x80\xc3\x81\xc3\x82\xc2\xa9\xc4\x80\xc5\x81\xc6\x80\xc8\x80' kann ich so, nicht wirklich etwas anfangen.
Also muss ich diese encoden. Bei den HTML-Entitäten und bei UTF-8 ist das vom Grunde her auch sehr einfach.
Es gibt entsprechende Referenzen hierzu, HTML=W3C und UTF-8 = ISO/IEC 10646-1.

An dieser Stelle muss ich lediglich sicherstellen, dass diese Referenzen zu 100% umgesetzt wurden.

Ein Modul, was nur die am häufigsten gebrauchten characters encoded, kann ich nicht gebrauchen.
Entweder man macht die Dinge richtig oder gar nicht, alles andere, fällt einem früher oder später, auf die Füsse.

Gehen wir einmal davon aus, ich habe entsprechende Module, welche W3C und ISO konform sind.
Dann habe ich jetzt Daten, welche zu mindestens für mich, weniger kryptisch sind.

Angenommen ich würde diese Daten in folgende Datenstruktur speichern und dann bearbeiten :

Code: Alles auswählen

from operator import itemgetter

sc = { '1' : [ { 'A': 'y', 'B': 'c'},  { 'A': 'ý', 'B': '´c'},  { ... } , { ... } ] }

for k,v in sc.iteritems():
    for counter, item in enumerate(sorted(v, key=itemgetter('A')), start=1):
         .....
Für mich stellt sich jetzt die Frage, wie sieht das sorted Ergebnis aus.
Bitte beachten, dass die dictionaries in der Liste unterschiedliche values haben. (y und ý) sowie (c und ´c).
Ich habe keine Ahnung wie das Ergebnis aussehen wird, aber ich gehe einmal davon aus :
..... c,y,´c,ý .....
Würde mir ein solches Ergebnis gefallen. Nein.

Also muss ich wieder zurück zur Decodierung. Die Frage, welche sich jetzt stellt, ist was mach mit ý.
Mache ich daraus einfach ein y ? Was mach ich mit dem Datenmüll ? Kann ich den überhaupt
herausfiltern ? All das hat Auswirkung auf das Ergebnis der Sortierung. Ich habe mich damit noch nicht
näher beschäftigt, weil ich soweit noch gar nicht gekommen bin.

Also zurück zum Anfang, ich muss erst einmal eine für mich brauchbare Decodierung finden oder eben selber eine entwickeln.
Ich werde mir Gedanken machen und komme, dann wieder darauf zurück.

Vielen Dank für Eure Geduld und Hilfestellungen.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Daikoku: da hast Du jetzt aber ein riesiges Fass aufgemacht. Wenn es um die Sortierreihenfolge geht, gibt es allein für Deutsch zig Varianten. Will man dann noch international arbeiten, wird man keine zufriedenstellende Lösung finden. Hier mal ein Beispiel:

Code: Alles auswählen

>>> locale.setlocale(locale.LC_COLLATE, 'de_DE.utf-8')
'de_DE.utf-8'
>>> locale.getlocale(locale.LC_COLLATE)
('de_DE', 'UTF8')
>>> sorted([u'ähnlich',u'anders',u'àle'], cmp=locale.strcoll)
[u'\xe4hnlich', u'\xe0le', u'anders']
Hier mal ein kleiner Artikel dazu: http://www.unicode.org/reports/tr10/. Wer sich aber wie an welche Regel hält, dürfte wohl sehr schwierig herauszufinden sein. Im oberen Beispiel übernimmt das das Betriebssystem bzw. die entsprechende libc-Bibliothek, das heißt, das kann sich auch noch von System zu System unterscheiden.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Gibt es überhaupt eine richtige, offizielle Sortierreihenfolge mit Sonderzeichen?

Bleiben wir mal beim deutschen äöüß... Wo kommen die "offiziell" hin?!? Wobei wahrscheinlich zielführender ist, zu fragen, wo sie praktischerweise für die Anwendung einsortiert werden sollte...

Nur mal eine Idee: alle Sonder-Buchstaben normalisieren (also ä -> a, á -> a), dann sortieren und wieder Rückwandeln?!?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Eine Sortierreihenfolge gibt es nicht, es gibt mehrere. Unterschiedliche Sprachen, Länder und Anwendungszwecke haben da eigene Standards von denen keiner unbedingt offizieller als der andere ist. Unicode definiert aber sowohl einen Algorithmus zum sortieren und eine Default Reihenfolge, an die sich natürlich nicht alle halten.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Bezüglich der Sortierung: Ich hatte mir mal eine Funktion geschrieben, die dazu dient, unter Berücksichtigung der länderspezifischen Regelung eine Sortierung vorzunehmen. Hierzu wird kurz vor der Sortierung ein entsprechender Wert für die `locale`-Einstellungen gesetzt. Anschließend wird die Sortierung vorgenommen und danach wird der vorherige Stand wiederhergestellt, sodass man also wieder die alten `locale`-Einstellungen hat. Es ist der Versuch, die eher umständlichen Schritte zur länderspezifischen Sortierung zu abstrahieren. Vielleicht hilft es als Vorlage ja weiter. Der Code läuft sowohl unter Python 2.7 als auch unter Python 3.

Code: Alles auswählen

import functools
import locale

def get_sorted(items, locale_name='', strict=False):
    """
    Sort `items` with respect to characters that are specific to the given
    locale. The result will be returned as a new list.

    `locale_name` defines the locale to be used. It has the same meaning as if
    it would have been passed to the stdlib's `locale.setlocale()`-function. If
    given as an empty string (the default) then the system's default locale will
    be used.

    Use `strict` to decide what to do if setting the locale failed with a
    `locale.Error`. `True` means that the function will fail by throwing the
    error. `False` means that the error is ignored and sorting is done
    locale-independent by simply calling `sorted(items)`.

    Note that this function temporary changes the interpreter's global locale
    configuration. It does this by storing the current locale and then setting
    the given locale name. Then the items are sorted and after that it will set
    the stored locale again. This function is not thread-safe.
    """
    locale_name_was_set = False
    old_locale = locale.getlocale(locale.LC_COLLATE)
    sortkey = functools.cmp_to_key(locale.strcoll)
    try:
        # `old_locale` might be invalid (at least on Windows)
        # => try to set it before doing the "real" switch
        locale.setlocale(locale.LC_COLLATE, old_locale)
        locale.setlocale(locale.LC_COLLATE, locale_name)
        locale_name_was_set = True
        result = sorted(items, key=sortkey)
    except locale.Error:
        if strict:
            raise
        result = sorted(items)
    finally:
        if locale_name_was_set:
            # this would fail otherwise
            locale.setlocale(locale.LC_COLLATE, old_locale)
    return result
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@snafu: Als sortkey kannst Du gleich locale.strxfrm nehmen. Wenn Du still und heimlich immer auf den non-locale-sort umsteigst, wirst Du nie fehler beim locale-Namen finden und Dich immer nur wundern, warum die Sortierung nicht funktioniert. Zumindest eine Warning sollte man ausgeben.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Sirius3 hat geschrieben:Als sortkey kannst Du gleich locale.strxfrm nehmen.
Mit `locale.strxfrm` wirft er mir eine Exception bei Unicode-Strings, die außerhalb des ASCII-Zeichensatzes sind (also z.B. deutsche Umlaute).

Code: Alles auswählen

Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> import locale
>>> locale.setlocale(locale.LC_COLLATE, '')
'German_Germany.1252'
>>> sorted([u'bämm'], key=locale.strxfrm)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 1:
ordinal not in range(128)
Daher bin ich bewusst den anderen Weg gegangen.
Wenn Du still und heimlich immer auf den non-locale-sort umsteigst, wirst Du nie fehler beim locale-Namen finden und Dich immer nur wundern, warum die Sortierung nicht funktioniert. Zumindest eine Warning sollte man ausgeben.
Ganz so ist es ja nicht. Man kann den `strict`-Parameter nutzen und würde den Fehler dann sehen. Für meine Zwecke war es eben wichtiger, überhaupt ein Ergebnis zu haben, selbst wenn das Ändern der `locale`-Einstellungen schiefgegangen ist. Das Ausgeben einer Warnung ist allerdings keine schlechte Idee.
Daikoku
User
Beiträge: 66
Registriert: Montag 20. April 2015, 21:14

zuerst einmal vielen Dank für die Ideen und Gedanken, die Ihr Euch alle gemacht habt.

Das Thema HTML Entities ist erledigt, das Ergebnis habe ich in einem separaten Threat zusammengefasst. http://www.python-forum.de/viewtopic.php?f=1&t=36604


Bleibt das Thema Sonderzeichen.

Ich muss ehrlich gestehen, das mich diese Komplexität ein wenig überrascht hat.

Ich habe einmal die Ressourcen meiner Firma genutzt und nachgeschaut, wie wir dieses Problem handhaben und das ist erschreckend einfach :

Ich kann in meinem System sehr genau hinterlegen, wie ich was sortiert haben möchte.

Beispiel : Lodz und Łódź

Es gibt eine Tabelle, wo vereinfacht dargestellt, das wie folgt hinterlegt ist : A;B;C;D;E;F;G;H;I;J:K;L;Ł;M ......

Damit ist festgelegt, das Ł nach L kommt. Das Ganze geht noch viel detaillierter, aber das soll hier jetzt nicht das Thema sein.

Nachdem das so eingetragen wurde, ist es nun auch völlig egal, ob ich mir meine Daten, auf einem SmartPhone, Tablet, Mac, PC oder
auf was auch immer auswerten lasse, die Sortierung ist immer gleich. Selbst dann, wenn ich die Spracheinstellung von deutsch auf zum Beispiel japanisch ändere.
Jeder User kann seine ganz individuelle Sortierung hinterlegen.
Es gibt aber auch, für einige Reports einheitliche Sortierungen, die zentral festgelegt werden, und vom User nicht übersteuert werden können.

Auf meinem SmartPhone und Tablet habe ich u.a. Sybase SQL Anywhere laufen und über meinen PC greife ich auf die selben Daten in HANA, Oracle oder DB/2 zu
und erhalte von meiner Applikation, die Daten immer in der gewünschten Reihenfolge.

Ich habe auf den verschiedenen Datenbanken eine entsprechende Tabellen angelegt und diese dann, von der jeweiligen Datenbanken selber sortieren lassen.
Dabei habe ich festgestellt, das völlig unterschiedliche Ergebnis, bei gleichem Datenbestand heraus kommen.


Für mich bedeutet das, das die Sortierung immer von der Applikation gesteuert wird, völlig unabhängig vom Betriebssystem, der Programmiersprache oder der jeweiligen Datenbank.

Damit komme ich zu folgendem Ergebnis.

Ich muss festlegen, wie ich etwas sortiert haben möchte und muss gleichzeitig sicherstellen, das diese Vorgaben auch immer eingehalten werden.
Ein einfaches sorted() oder SELECT from …. ORDER BY … wird das so nicht leisten können.

Meine Tests haben auch gezeigt, das es unterschiedliche Sortierroutinen gibt. Wer weiß, ob das in Python immer so bleibt, wie es jetzt gerade ist, oder ob nicht irgendwann einmal, jemand auf die Idee kommt, eine völlig andere Routine zu implementieren und schon habe ich dann völlig andere Ergebnisse.

Wenn ich einmal nach vorne schaue, ergibt sich für mich noch ein weiteres Problem. Wenn ich zum Beispiel meine Daten von Python nach HTML rendern lasse darf die Sortierung der Daten zu keinem anderen Ergebnis führen, als wenn ich das, über ECMAScript direkt im Browser umsetzen würde.

Ich muss mir noch ein paar weiter gehende Gedanken machen :

Orte haben unterschiedliche Namen :
- Breslau = Wrocław
- Danzig = Gdańsk
- Stettin = Szczecin
- Wien = Vienna

Ich könnte mir vorstellen, das es zum Beispiel für die EU einheitliche Städte Bezeichnungen gibt. Gibt es Konventionen für Ortsbezeichnungen ? Es kann eigentlich nicht sein, das in Dokumenten eines Projektes zum Beispiel einmal von Breslau und in einem weiteren Dokument plötzlich von Wrocław die Rede ist, je nachdem wer dieses gerade verfasst hat. Das führt doch zu Verwirrungen, oder ist das jedem sofort klar das Breslau gleich Wrocław ist. Also mir nicht. Und wie gebe ich überhaupt Wrocław über meine Tastatur ein. Klar ich kann das Layout softwaretechnisch ändern, aber meine physikalische Tastatur ist immer noch die gleiche. Woher soll ich jetzt wissen, welche Taste das Zeichen ł darstellt. Auf meinem Tablet ist das alles gar kein Problem. Aber bei meinen Notebook und PC schon.

Fragen über Fragen. Ich muss diese erst einmal alle für mich klären, aber gleichzeitig auch vermeiden, das diese Aufgabenstellung ungewollt zu einem größeren Problem mutiert, als es vielleicht in Wirklichkeit ist.

Wie gehe ich jetzt weiter vor :

Bevor ich mich mit der Sortierung weitergehend beschäftige, brauche ich erst einmal saubere Daten.

Code: Alles auswählen

a = '\xc5\x81\xc3\xb3d\xc5\xba' # ist gleich mit a = 'Łódź'
b = {a:a}       # b = {'\xc5\x81\xc3\xb3d\xc5\xba': '\xc5\x81\xc3\xb3d\xc5\xba'}
print b['Łódź'] # out : \xc5\x81\xc3\xb3d\xc5\xba
print b['\xc5\x81\xc3\xb3d\xc5\xba'] # out : \xc5\x81\xc3\xb3d\xc5\xba

Code: Alles auswählen

a = '&emsp;&emsp;\xc5\x81\xc3\xb3d\xc5\xba&emsp;&emsp;' # ist gleich mit a = '  Łódź  '
b = {a:a}       # b = {'&emsp;&emsp;\xc5\x81\xc3\xb3d\xc5\xba&emsp;&emsp;': '&emsp;&emsp;\xc5\x81\xc3\xb3d\xc5\xba&emsp;&emsp;'}
print b['Łódź'] # out : KeyError: '\xc5\x81\xc3\xb3d\xc5\xba'
print b['\xc5\x81\xc3\xb3d\xc5\xba'] # out : KeyError: '\xc5\x81\xc3\xb3d\xc5\xba'
Das Beispiel zeigt, das ich meine Daten in jedem Fall, von den HTML-Entitäten befreien muss und anschließend von ungewollten Leerzeichen.
Nachstehend nur mal eine Idee, ohne Funktionen und sonstigen Strukturen.

Code: Alles auswählen

entity = { '&nbsp;'  : ' ',  # erzwungenes Leerzeichen
           '&ensp'   : ' ',  # Leerzeichen Breite n
           '&emsp'   : ' '  # Leerzeichen Breite m
          }

decode  = dict((re.escape(k), v) for k, v in entity.iteritems())
pattern = re.compile("|".join(decode.keys()))

text = '&emsp;&emsp;\xc5\x81\xc3\xb3d\xc5\xba&emsp;&emsp;'

text = pattern.sub(lambda m: decode[re.escape(m.group(0))], text)

# Alle doppelten Leerzeichen, sowie die Leerzeichen am Anfang und am Ende entfernen.
text = ' '.join(text.split())
Ich weiß, dass ich auch gleich so etwas wie :

Code: Alles auswählen

re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
verwenden kann. Bitte seht mir hier eventuelle Fehler nach, ich muss mich mit re noch intensiver beschäftigen.

Warum ich mich gegen den vermeintlich einfacheren Weg entschieden habe :
Das ich die values und keys aus entity später einmal über eine GUI verwalten möchte.
Also nicht einfach fest in einem Modul. Ich habe irgendwo gelesen, das man dieses dann hardcoded nennt ?
Ist auch egal, ich möchtet das nicht irgendwo fest verdrahtet haben, sondern flexibel halten.

zum Beispiel kann ich dann aus Müll auch noch etwas sinnvolles machen.
'&emsp;&#204Berlin&xp&gst;' = 'Berlin'
ohne ständig den Code selber zu ändern.

Darüber hinaus stellt sich die Frage, wenn entity jetzt zum Beispiel 1000 Keys hat und ich dann 1, 10, 100 Million Textstrings damit verarbeite,
wie sieht das Laufzeitverhalten aus. Brauche ich eine Vorprüfung ? if '&' in text: then; oder nehme ich einfach alle Textstrings und
lasse diese durch die Routine laufen.
Ist das multiprocessing fähig und ab wie vielen Textstrings ist das überhaupt sinnvoll.
threads bringen unter Windows nichts, ausser ich möchte es langsamer machen als eigentlich wäre.
Ich werde das alles mal testen.

Der nächste Schritt wäre dann, der Umgang mit den Ortsbezeichnungen.

Ich schaue mir auch auf jeden Fall Eure Vorschläge alle an, z.B. habe ich locale noch nie verwendet. Da muss ich mal lesen.
Bei mir geht nichts verloren, aber ich brauche ein wenig Zeit zum Nachdenken, recherchieren, lesen, usw. um ein wenig Struktur hier rein zu bekommen.
Ich werde auf das Thema wieder zurück kommen.

Vielen Dank für Eure Anregungen und Mühen.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Daikoku: Warum erfindest Du Dir jetzt eine eigenes HTMLEntry-Unencode?
Schau doch, wie es andere machen: statt etliche verschieden Entities zu suchen, solltest Du einen generischen Ausdruck nehmen, und die unicode Codepoints unterstützt Du auch noch nicht:

Code: Alles auswählen

ENTITY_EXPR = re.compile('&#X[0-9A-F]+;|&#[0-9]+;|&\w+;', re.I)

def unescape(text):
    def replace(match):
        s = match.group(0)
        if s[1] == "#":
            if s[2] in "xX":
                c = int(s[2:], 16)
            else:
                c = int(s[1:])
            return unichr(c)
        else:
            return entity.get(s, s)
    return ENTITY_EXPR.sub(replace, text)
Antworten