UTF-8 und CP1252 Probleme

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
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Dienstag 16. März 2010, 01:42

Hi Community,

ich lese Daten aus einer Webseite ein, die offentsichlich selbst Probleme mit ihrer Encodierung hat.

Die eingelesen Daten sehen unter anderem so aus:
daughter’s

Ich wandle diese so früh wie möglich in utf8 um und speicher sie selbst in eine Datei. Dort wird ein Sonderzeichen als \u03a3 (so ähnlich) abgebildet.

Wenn ich diese probier über die Konsole auszugebene, die mit cp1252 enkodiert ist, so bekomme ich ein UnicodeDecodeError.

Das gleiche Verhalten tritt auf, wenn ich

Code: Alles auswählen

print u"\u03a3"
ausführe.

Wie kann ich diese falsch kodierte Unicode erkennen und korrigieren bzw. wie löse ich das Problem generell? Manche Zeichen stellen ja legale kodierungen da bzw. können von cp1252 dargestellt werden.

Fehlermeldung:
File "C:\Python26\lib\encodings\cp1252.py", line 12, in encode
return codecs.charmap_encode(input,errors,encoding_table)
UnicodeEncodeError: 'charmap' codec can't encode characters in position 3-4: character maps to <undefined>

Grüße,
anogayales
BlackJack

Dienstag 16. März 2010, 02:15

@anogayales: Das ist ein wenig schwammig insbesondere da Du ja keine konkreten Daten zeigst, aber vielleicht enthält die Webseite tatsächlich Zeichen, die in 'cp1252' nicht darstellbar sind!?

Was heisst die eingelesenen Daten sehen so 'daughter’s' aus? Wo darsgestellt? Mit welcher Kodierung ausgegeben? Welche Kodierung erwartet(e) das Programm, dass Dir den Text so dargestellt hat? Hier macht eine `repr()`-Darstellung mehr Sinn, wenn man sehen will was *wirklich* an Bytewerten vorliegt.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Dienstag 16. März 2010, 09:20

anogayales hat geschrieben:Ich wandle diese so früh wie möglich in utf8 um und speicher sie selbst in eine Datei. Dort wird ein Sonderzeichen als \u03a3 (so ähnlich) abgebildet.
Grober Fehler. Du kannst nicht einfach Text der in irgendeiner Kodierung vorliegt, in UTF8 umwandeln. Dass dann noch größerer Mist rauskommt, sollte nicht verwundern. Du musst zunächst einmal feststellen, was da wirklich bei dir ankommt. Dazu darfst du an keiner Stelle irgendwo rumkonvertieren arbeiten. Du brauchst die Bytes, die der Webserver an dich sendet, unverändert. Erst dann kannst du anfangen zu raten.

Was du da gepostet hast, erhält man typischer Weise, wenn man UTF8 als irgendeine andere Kodierung interpretiert. Dazu musst du jetzt erst einmal feststellen ob die Rohbytes gültiges UTF8 sind oder ob sie irgendwas anderes sind(z.B. als UTF8-kodiertes vorher als cp1252 dekodiertes utf8). Diese drei Zeichen, die du da siehst, entsprechen nämlich genau den Zeichen, die man erhält, wenn man "’" als utf8 kodiert und dann die drei Bytes als cp1252-Kodierten Text interpretiert.
Wenn ich diese probier über die Konsole auszugebene, die mit cp1252 enkodiert ist, so bekomme ich ein UnicodeDecodeError.
Das verwundert nicht, denn \u03a3 entspricht einem Summenzeichen und das ist wohl kaum in cp1252 enthalten. Da ein Summenzeichen in dem Kontext von „daughter“ so überhaupt keinen Sinn macht ist davor schon was falsch gelaufen(s. oben). \u03a3 selbst ist übrigens sicherlich kein utf8. Also hast du da mal wieder irgendwas rumkodiert (in diesem Fall wohl als utf8 dekodiert damit du einen Unicode-String erhältst).
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Dienstag 16. März 2010, 13:38

Ich möchte Anmerken, dass daugther und das Summenzeichen nichts mit eindander zu tun haben.

Das Summenzeichen soll auch am Ende rauskommen, da bin ich mir sicher,
wie kann ich den meine python konsole auf utf-8 umstellen? Geht das einfach so?

So, also ich hab ein wenig recherchiert:

Urllib spuckt mir folgenden String raus, sprich, ich les die Zeile ein und printe es:
father\xe2\x80\x99s

Wie soll ich weiter vorgehen?
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

Dienstag 16. März 2010, 16:54

Lies (bitte) erstmal [wiki=Von Umlauten, Unicode und Encodings]diesen sehr guten und wichtigen Artikel[/wiki]
Und evtl. bringt dir dann folgendes die entscheidende Erkenntnis:

Code: Alles auswählen

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> txt = "father\xe2\x80\x99s"
>>> print txt
father’s
>>> print txt.decode("cp1252")
father’s  # <-- cp1252 ist offensichtlich nicht die original-codierung
>>> print txt.decode("utf-8")
father’s # SIeht doch viel besser aus
#           - mein Terminal (Linux/ubuntu) beherrscht allerdings UTF-8
>>> u =  txt.decode("utf-8")[-2]
>>> u
u'\u2019' #das ist jetz 'unicode' und NICHT (utf-8-) codiert
>>> import unicodedata as ud
>>> ud.name(u)
'RIGHT SINGLE QUOTATION MARK'
hth, Jörg
Wir haben schon 10% vom 21. Jahrhundert hinter uns!
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Dienstag 16. März 2010, 18:07

Hinweis: Für Unicode-prints unter Windows kannst du IDLE verwenden, das kann utf-8 decoden.
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Dienstag 16. März 2010, 18:44

Ich bin noch am fleißig am Durchlesen.

Liege ich richtig in der Annahme, dass es ein generelles Problem ist, Unicode Zeichen auszugeben, die von der verwendeten Kodierung nicht unterstützt werden?

Nicht mal ipython unter Windows schafft es u'\u2019' auszugeben. Ipython benutzt bei mir cp850.
BlackJack

Dienstag 16. März 2010, 19:03

@anogayales: Mit der Annahme liegst Du richtig. Unicode kennt deutlich mehr als 10.000 Zeichen und die ganzen cp-Irgendwas jeweils nur maximal 256. Das lässt sich halt nicht verlustfrei abbilden.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Mittwoch 17. März 2010, 11:43

Übrigens sagt der Webserver einem in der Regel die Kodierung. Standardmäßig liegt einen HTML-Seite in ISO-8859-1 vor. Ist das anders, hat der Server die Chance, das als charset im content-type-Header anzugeben. Verpasst er diese Chance, musst du die HTML-Seite als ISO-8859-1 auffassen und parsen und schauen, ob da ein META-HTTP-EQUIV-Element zu finden ist, das den Content-Type des Server überschreibt.

Anzumerken ist noch, das XHTML-Seiten standardmäßig UTF-8-kodiert sind, denn das ist der Standard für XML. Dort definiert eine <?xml?>-Processing-Instruction eine Abweichung von der Regel.

Leider halten sich viele Leute nicht an diese Vorgaben und liefern Mist aus, bei dem der Webbrowser dann raten muss, was es wohl sein könnte. Es gibt Bibliotheken, die Heuristiken benutzen, um die Kodierung zu raten. Das ist jedoch nur ein schwacher Ersatz für es zu wissen.

Stefan
Antworten