Wie Umlaute statt "komische Zeichen" anzeigen?

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.
Benutzeravatar
snafu
User
Beiträge: 5650
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mittwoch 17. September 2008, 18:10

Hi!

In einem Script scrape ich Daten von Myspace und bekomme im Fall von "unbekannten" Zeichen (z.B. Umlauten) Unicode zurück - ansonsten "reine" Strings. Anstatt einem ü hab ich z.B. ü. Ich habe schon encode('utf-8').decode('latin-1') ausprobiert, aber das Ergebnis bleibt leider das selbe. Wie also kann ich die Zeichen richtig darstellen?

Das Skript: http://paste.pocoo.org/show/85526/

Ich hoffe, ihr könnt es auch nachvollziehen, ohne Myspace nutzen zu müssen. :)

Gruß

Sebastian
sea-live
User
Beiträge: 440
Registriert: Montag 18. Februar 2008, 12:24
Wohnort: RP

Mittwoch 17. September 2008, 18:15

also das Ä1/4 kommt
hier her

Code: Alles auswählen

# -*- coding: cp1252 -*-
hate ich auch schonmal

wenn du utf-8 verwendest musst du auch u"xxxx" verwenden sonst wird das nix
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mittwoch 17. September 2008, 18:20

Das hier ist wirklich hilfreich (s. auch Thread weiter unten ;-) ):
[wiki]Von Umlauten, Unicode und Encodings?highlight=(umlaute)[/wiki]

Hat mich auch immer wieder beschäftigt Jahre lang - ich glaube so langsam hab ich das nun durchblickt, auch dank der Hilfe einiger Forummitglieder hier. Aber das wiki hat mir da wirklich sehr geholfen.

Sea-lives Beitrag vergisst Du lieber mal schnell ;-)
Benutzeravatar
snafu
User
Beiträge: 5650
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mittwoch 17. September 2008, 18:43

Hyperion hat geschrieben:Das hier ist wirklich hilfreich (s. auch Thread weiter unten ;-) ):
[wiki]Von Umlauten, Unicode und Encodings?highlight=(umlaute)[/wiki]
Jupp. Ich hatte den Beitrag abgeschickt bevor ich mir die aktuelle Übersichtsseite angeguckt habe und daher den besagten Thread nicht gesehen.

Habe jetzt an einer Zeile etwas rumgebastelt (ergibt sich aus dem Traceback) aber ich bekomme es immer noch nicht hin:

Code: Alles auswählen

>>> import mspdat
>>> msp = mspdat.Datagetter()
>>> msp.login('abc@xyz.de', 'pw123')
>>> print msp.get_moods(pretty=True)

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    print msp.get_moods(pretty=True)
  File "C:\Python25\mspdat.py", line 57, in get_moods
    return prettify_moods(data)
  File "C:\Python25\mspdat.py", line 92, in prettify_moods
    return '\n\n'.join(s).decode('iso-8859-1')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 190-191: ordinal not in range(128)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mittwoch 17. September 2008, 18:54

Dein Interpreter will standard mäßig ASCII ausgeben. Du bekommst aber eben Zeichen in Zeile 4 bei get_moods() zurück, die nicht in ASCII darstellbar sind. Du musst also mal gucken, dass Du beim print noch Kodierung angibst, die zur Ausgabe verwendet werden soll, also etwa so:

Code: Alles auswählen

print u"%s".encode("iso-8859-1") % msp.get_moods(pretty=True).decode("iso-8859-1")
BlackJack

Mittwoch 17. September 2008, 19:09

@snafu: Nicht rumbasteln sondern verstehen was da passiert und gezielt handeln.

@Hyperion: Das ist ziemlich unsinnig. Du nimmst eine Unicode-Zeichenkette u'%s' und kodierst die als ISO-8859-1 ─ das ist '%s' etwas komplizierter geschrieben. Dann formatierst Du eine Unicode-Zeichenkette in eine normale Zeichenkette, was dazu führt, das die normale Zeichenkette erst einmal nach Unicode umgewandelt wird ─ aus dem '%s' wird also wieder u'%s'. *Das* kann man auch einfacher haben. :roll:

Die Frage ist, warum von `get_moods()` überhaupt eine Zeichenkette kommt und kein Unicode-Objekt. Wenn man aus den Seiten Unicode bekommt muss das ja schon mal völlig unnötigerweise umkodiert worden sein.

Wenn Textdaten das Programm betreten, sollte man sie sofort in Unicode umwandeln. `BeautifulSoup` und XML-Bibliotheken machen das schon. Innerhalb des Programms arbeitet man immer mit Unicode und erst zum spätmöglichsten Zeitpunkt, kurz bevor die Daten das Programm als Bytes verlassen müssen, wandelt man wieder entsprechend um. Alles andere ist unnötig kompliziert.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 17. September 2008, 19:11

Das Print braucht doch kein String-Formatting.

Letztendlich ist es so: Man bekommt einen Bytestring rein, dekodiert den in Unicode und zur Ausgabe nutzt man wieder ein Encoding, das die Konsole versteht.

Wenn das so kompliziert ist, kannst du morgen zum Usertreffen in München kommen, genau das ist das Vortragsthema.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
snafu
User
Beiträge: 5650
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mittwoch 17. September 2008, 19:14

Leider das selbe Problem:

Code: Alles auswählen

>>> print u"%s".encode("iso-8859-1") % msp.get_moods(pretty=True).decode("iso-8859-1")

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    print u"%s".encode("iso-8859-1") % msp.get_moods(pretty=True).decode("iso-8859-1")
UnicodeEncodeError: 'ascii' codec can't encode characters in position 191-192: ordinal not in range(128)
Versuche ich die Position 191-192 anzuzeigen, kommt:

Code: Alles auswählen

>>> moods = msp.get_moods()
>>> from mspdat import prettify_moods as pretty
>>> print pretty(moods)[191:192]
Ã
Vielleicht hilft das ja irgendwie...
BlackJack

Mittwoch 17. September 2008, 19:34

Helfen würde die `repr()`-Form, damit man sieht was da *wirklich* heraus kommt und nicht wie Deine Konsole die Bytes interpretiert. Aber wie gesagt, `get_moods()` sollte Unicode oder Zeichenketten die nur ASCII enthalten zurück geben.

Und auch bei ``print`` musst Du Unicode-Objekte vorher entsprechend kodieren, damit es da keine Probleme gibt. Dass das in der Konsole meistens auf magische Weise klappt, ist keine Garantie.
Benutzeravatar
snafu
User
Beiträge: 5650
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mittwoch 17. September 2008, 19:35

BlackJack hat geschrieben:Die Frage ist, warum von `get_moods()` überhaupt eine Zeichenkette kommt und kein Unicode-Objekt. Wenn man aus den Seiten Unicode bekommt muss das ja schon mal völlig unnötigerweise umkodiert worden sein.
Tja, das frage ich mich auch.
BlackJack hat geschrieben:Wenn Textdaten das Programm betreten, sollte man sie sofort in Unicode umwandeln. `BeautifulSoup` und XML-Bibliotheken machen das schon.
Ist es denn möglich, mit BS zu parsen und dann mit der Syntax von lxml durch den Baum zu navigieren? Ich mag nämlich die Syntax von BS nicht so und befürchte, dass ich nicht mal so auf die Schnelle etwas äquivalentes zum jetzigen Code hinbekommen mit BS-Syntax hinbekommen würde.

//edit: Okay, ich könnte natürlich den von BS geparsten Code als String ausgeben lassen und dann nochmal mit lxml drübergehen. Aber es geht doch sicher auch effizienter, oder?
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 17. September 2008, 19:54

snafu hat geschrieben:Ist es denn möglich, mit BS zu parsen und dann mit der Syntax von lxml durch den Baum zu navigieren? Ich mag nämlich die Syntax von BS nicht so und befürchte, dass ich nicht mal so auf die Schnelle etwas äquivalentes zum jetzigen Code hinbekommen mit BS-Syntax hinbekommen würde.

//edit: Okay, ich könnte natürlich den von BS geparsten Code als String ausgeben lassen und dann nochmal mit lxml drübergehen. Aber es geht doch sicher auch effizienter, oder?
Und wozu das ganze? html5lib und lxml.html existieren.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mittwoch 17. September 2008, 20:10

BlackJack hat geschrieben: @Hyperion: Das ist ziemlich unsinnig. Du nimmst eine Unicode-Zeichenkette u'%s' und kodierst die als ISO-8859-1 ─ das ist '%s' etwas komplizierter geschrieben. Dann formatierst Du eine Unicode-Zeichenkette in eine normale Zeichenkette, was dazu führt, das die normale Zeichenkette erst einmal nach Unicode umgewandelt wird ─ aus dem '%s' wird also wieder u'%s'. *Das* kann man auch einfacher haben. :roll:
Hm ... ok ... ich versuche das mal grad nachzuvollziehen.
wiki hat geschrieben: Wenn man einen Text mit Umlauten an die Konsole (in unserem Fall STDOUT) schicken möchte, dann muss man diesen Text in das Encoding der Konsole umwandeln.
get_moods() liefert also def. einen Bytestring zurück, vermutlich iso-8859-1 encodiert. Die Konsole meckert wegen Zeichen, die die ASCII-Kodierung nicht darstellen kann. Also muss man doch print mitteilen, dass man kein ASCII sondern, iso-8859-1 Text ausgeben will. Ich dachte immer über ein

Code: Alles auswählen

u"irgend ein Text".encode("iso-8859-1")
kann ich das machen. Aber da irre ich wohl. Wie sieht denn hier ein gangbarer Weg aus? Wenn ich BlackJack richtig verstanden habe, so bewirkt der "%"-Operator ein implizites umkodieren in das Byteformat des Bytestrings?
Benutzeravatar
snafu
User
Beiträge: 5650
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mittwoch 17. September 2008, 20:13

Hyperion hat geschrieben:Wenn ich BlackJack richtig verstanden habe, so bewirkt der "%"-Operator ein implizites umkodieren in das Byteformat des Bytestrings?
%s ist einfach nur Teil des String-Formattings, was du dir - wie schon gesagt wurde - aber auch sparen kannst.
Benutzeravatar
snafu
User
Beiträge: 5650
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mittwoch 17. September 2008, 20:21

repr(pretty(moods)) liefert übrigens das zurück (Auszug) :

Code: Alles auswählen

<Assen> ........................................................ <Am 06.Aug.2008.>\\ntraurig\\n\\n<schmockefuckanalpropaganda(K\\xc3\\xb6nig)> ab in stadtgarten alle man(auf den hund gekommen) <Am 04.Aug.2008.>\\nquietschfidel\\n\\n<Ace L. Chuck> Dirty old Town... <Am 27.Jul.2008.>\\nerleichtert\\n\\n<The kid you never wanted around.> wohnt jezz auch wieder in schalke-ost! <Am 25.Jul.2008.>\\nersch\\xc3\\xb6pft\\n\\n<Dino> : wuff! <Am 15.Jul.2008.>\\nam Chillen\\n\\n<Philo> isst gerade. <Am 13.Jul.2008.>\\nam Rocken\\n\\n<Dirrrty Sanchez from Outta Space> quo <Am 22.Jun.2008.>\\ntriumphierend\\n\\n<Horst> endlich neue wohnung UND internet!!! <Am 10.Jun.2008.>\\naufgedreht\\n\\n<Elektro_Deluxe> : In Deinem erweiterten Netzwerk <Am 08.Mai.2008.>\\nritterlich\\n\\n
Benutzeravatar
snafu
User
Beiträge: 5650
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Mittwoch 17. September 2008, 20:59

Leonidas hat geschrieben:Und wozu das ganze? html5lib und lxml.html existieren.
Du meinst, ich soll mit lxml parsen (mit html5lib tu ich's ja schon und baue daraus einen lxml-Baum)? Das Problem ist, dass lxml wohl nicht so fehlertolerant ist. Zumindest bekomme bei dessen Parser nichts brauchbares zurück. :(
Antworten