Ich blick es leider nicht. Encode/decode/utf8/Umlaute

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.
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

Hallo Leute,

ich hatte vor Monaten schon einmal das Thema und irgendwie habe ich es damals geschafft.
Jetzt befasse ich mich wieder (nach Monaten) mit Python und habe wieder das selbe Problem.
Meine damaligen Scripte sind nicht mehr vorhanden und jetzt muss ich mich von Grund auf neu damit beschäftigen. (Sonst hättei ch ja geschwind nachschauen können obwohl das Verständnis wieder ausgeblieben wäre).

Ich habe eine HTML-Seite in beautifulsoup und wenn ich ein Content herausgefiltert habe um ihn testweise auszugeben, bekomme ich statt 'München' ein 'M\u03ccnchen'.

In meinem Python-Header habe ich

Code: Alles auswählen

# -*- coding: UTF-8 -*-
definiert.
Damit sollte ich also Unicode-Konform programmieren (das bedeutet das ja, oder liege ich da falsch?)

Ich weise einer Variable den Content aus BeautifulSoup zu und gebe diesen aus:

Code: Alles auswählen

stadt = soup.find("div", {"class": "irgendwas"}).find("a", {"class": "irgendwas"}).contents
print(stadt)
Das irgendwas ist selbstverständlich nur ein Platzhalter.

So, ich erwarte an dieser Stelle die Ausgabe München. Bekommen tu ich aber, wie oben gesagt, ein M\u03ccnchen.

Da ist natürlich in der 'Umsetzung' etwas falsch.
Aber jetzt die Frage:
Ist die Variable nun Unicode (dank der Header-Angabe) oder string?
Und muss ich jetzt den Unicode oder eben String encoden oder decoden?

Was ist das IST und wie komme ich zu dem SOLL?
Ist das IST das was im Header steht oder wie habe ich das zu verstehen?
Und was macht denn nun genau das decoden bzw. encoden?
Ich brauche ja nur eine Richtung vom aktuellen IST, richtig? (also unicode->latin-1 oder sowas in der Art)

Ich bin zwar überrascht daß ich wieder halbwegs python verstehe (nach so langer Zeit), aber damals habe ich das Ding mit den Codes nicht verstanden und jetzt erst recht nicht... leider...
Und ich merke das es etwas essentielleres ist als zuerst gedacht.

Kann mir hier mal jemand etwas unter die Arme greifen und mir das erklären? Auch anhand meines Beispieles wäre es echt toll.

Ich bedanke mich schon einmal im Voraus für eure Mühe.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Die Codezeile am Anfang besagt nur mit welcher Kodierung dein Script abgespeichert ist. Hat also mit der Verarbeitung nichts zu tun.
Wenn du da UTF-8 rein schreibst, solltest du jedoch sicher stellen, dass dein Editor auch wirklich UTF-8 speichert. Unter Windows ist das ja nicht selbstverständlich.

Interessant wäre welche Python Version du benutzt und die tatsächliche Ausgab des print-Statements. Also inklusive Anführungszeichen, etc. Daran erkennst du dann ob es ein Unicode-String ist - oder nicht.
BlackJack

@kaineanung: Von `contents` bekommst Du eine Liste und da steht eine Unicode-Zeichenkette drin. Du gibst da also gar nicht die Zeichenkette aus, sondern die *Liste*. Der Name `stadt` ist also nicht ganz richtig, beziehungsweise passt der Wert nicht zum Namen denn die Stadt ist das Element in der Liste. Listen geben sich selbst als Zeichenkette so zurück das man erkennen kann was darin gespeichert ist. Konkreter gesagt wandeln sie die einzelnen Elemente nicht mit `str()` in eine Zeichenkette um sondern mit `repr()`. Listen ausgeben ist etwas für Programmierer und nicht für Endbenutzer und Programmierer wollen wissen was in der Liste steht, und zwar *eindeutig* und auch unabhängig davon welche Kodierung das Programm erwartet das letztendlich die Liste als Text darstellt. Deshalb werden Zeichen ausserhalb von ASCII mit Escape-Sequenzen dargestestellt. Denn sonst würde man statt München vielleicht Mnchen oder M?nchen sehen wenn sich Python und das Ausgabeprogramm sich nicht darüber einig sind welche Kodierung verwendet werden soll. Oder Umgekehrt könnte man München ausgegeben bekommen obwohl die Zeichenkette eigentlich etwas anderes enthält wenn sich Kodierungsfehler gegenseitig aufheben. Aber dann hat man halt trotzdem fehlerhafte Daten, aber sieht es nicht einmal.

Ob ein Wert Unicode ist oder nicht sieht man an ihrem Typ. `str` bei Python 3 und `unicode` bei Python 2. Von HTML-Parsern würde ich Unicode erwarten, zumindest wenn die Zeichenkette etwas ausserhalb von ASCII enthält. (Wenn's nur ASCII ist, dann spielt es praktisch (fast) keine Rolle welchen Typ man dafür verwendet.)
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

kaineanung hat geschrieben:Und was macht denn nun genau das decoden bzw. encoden?
`.decode()` sollte auf Bytes aufgerufen werden, um Unicode zu erhalten. `.encode()` sollte auf Unicode aufgerufen werden, um Bytes zu erhalten. In beiden Fällen muss natürlich auf die Angabe der korrekten Kodierung geachtet werden. Auf die Vorbelegung von Python würde ich mich dabei nicht verlassen, denn diese hat sich von ASCII (Python 2) auf UTF-8 (Python 3) geändert. Da würde es also zu Problemen kommen, falls der Code in beiden Interpreter-Versionen laufen soll. Mal davon abgesehen, dass ASCII bei diesen Umwandlungen wohl eher selten gewünscht ist. Mit UTF-8 fährt man unter Linux ganz gut, oft jedoch nicht unter Windows.

Unicode ist besonders praktisch für die interne Verarbeitung von Texten mit Zeichen außerhalb von ASCII. Falls eine Ausgabe im Terminal oder das Schreiben in eine Datei oder Pipe gewünscht ist, dann wandelt man normalerweise wieder in Bytes um. Wenn man weiß, dass man garantiert innerhalb des ASCII-Zeichensatzes bleibt, dann reicht eigentlich auch das Hantieren mit Bytes aus. Ab Python 3 würde ich aufgrund der dortigen Änderungen aber trotzdem unabhängig von der Kodierung möglichst immer Unicode für die Textverarbeitung nutzen.

Weitere Besonderheiten: Die Angabe einer Zeichenkette (z.B. "spam") erzeugt unter Python 2 ein Bytes-Objekt und unter Python 3 ein Unicode-Objekt. Man kann mittels b"spam" bzw u"spam" aber explizit angeben, ob man Bytes oder Unicode haben möchte. Wobei zu beachten ist, dass ein b"späm" unter Python 2 angenommen und das "ä" konvertiert wird. Unter Python 3 hingegen wird alles, was außerhalb von ASCII liegt, mit einem Fehler abgewiesen, d.h. b"späm" funktioniert dort nicht.

Ich hoffe, ich konnte dir mit diesen Informationen etwas weiterhelfen.
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@Sparrow
Interessant wäre welche Python Version du benutzt und die tatsächliche Ausgab des print-Statements. Also inklusive Anführungszeichen, etc. Daran erkennst du dann ob es ein Unicode-String ist - oder
nicht.
Python 2.7
Und die Ausgabe des Content wäre:

Code: Alles auswählen

[u'M\03ccnchen']
(Und da hat BlakJack natürlich recht -> es ist ein Listelement wie man sieht...)

@BlackJack

Wenn du die Ausgabe so siehst, also das 'kodierte' 'ü' als '\03cc' dargestellt, ist das was genau? Und wie wandle ich das nun in 'ü' um um es auszugeben in eine Datei zu speichern oder in eine DB zu jagen?
Nachdem du selber sagt das es unicode sein sollte in der Liste, habe ich jetzt ein Verständnisproblem:
Unicode kann doch Umlaute darstellen? Aber sicherlich bin ich auf dem falschen Gleis...

@snafu
`.decode()` sollte auf Bytes aufgerufen werden, um Unicode zu erhalten. `.encode()` sollte auf Unicode aufgerufen werden, um Bytes zu erhalten. In beiden Fällen muss natürlich auf die Angabe der korrekten Kodierung geachtet werden.
Und Bytes ist dann tatsächlich kein darstellbares Zeichen sondern der Wert des Zeichens?
Wenn ich unicode habe: muss ich dann auf Unicode encoden damit ich dann das daraus resultirende nochmals in das 'richtige' umwandeln?
Also eine folgender Vorgang:
Unicode-Variable -> Byte-Variable -> Ascii-Variable (oder was auch immer um Umlaute richtig darstellen/verarbeiten zu können)?
Muss ich mir das so vorstellen?
BlackJack

@kaineanung: Das ist ein Unicode-Zeichenkettenliteral mit einer Escape-Sequenz für alle Codepoints die ausserhalb von ASCII sind, also alles was einen Wert grösser als 127 hat. Unter 128 werden ausserdem genau wie bei Byteketten alle nicht-druckbaren Zeichen als Escape-Sequenzen dargestellt.

Wie und ob überhaupt Du das umwandeln musst hängt davon ab was Du machen möchtest. Wenn es ein ``print`` auf eine Konsole ist von der Python die Kodierung ermitteln konnte musst Du nichts machen sondern halt einfach die Unicode-Zeichenkette ausgeben. Ansonsten musst Du wissen wie kodiert werden soll und das explizit *tun*, mit `encode()`. In eine Datenbank sollte man einfach das Unicode-Objekt speichern, also auch nichts besonderes machen.

Unicode kann gar nichts darstellen im Sinne von anzeigen, sondern Zeichen intern repräsentieren. Wie das angezeigt wird hängt von mehreren Faktoren ab. Du musst unterscheiden zwischen APIs denen man Unicode übergeben kann, und solchen die Bytes erwarten. Bei denen die Bytes erwarten muss man die Unicode-Zeichenkette vorher mit der Zeichenkodierung in Bytes umwandeln die von der ”Gegenseite” erwartet wird. Bei Konsolen kann Python das in der Regel richtig erraten, aber wenn man dort die Ausgabe in eine Pipe oder Datei umleitet, dann klappt das schon nicht mehr und das Programm fällt auf die Nase weil Python 2.x da dann einfach ASCII verwendet.

Irgendwie habe ich den Eindruck Du hast das mit der *Liste* immer noch nicht verstanden. Du gibst ja nicht das Unicode-Objekt aus sondern die Liste! Und die ruft mit jedem Element die `repr()`-Funktion auf und diese Darstellung ist eben die die ich schon mal beschrieben habe: Für Programmierer, auf ASCII beschränkt, so dass man genau sehen kann was in einer Zeichenkette, egal ob Byte oder Unicode, tatsächlich enthalten ist, ohne Gefahr zu laufen das die Kodierung der Konsole oder wo auch immer man sich dass dann letztendlich anschaut irgendwas verschluckt oder verschleiert.

Unicode enthält Zeichen, oder genauer Codepoints, die eine festgelegte Bedeutung haben, und es gibt genug davon um alle gängigen Zeichen (und auch viel exotisches) damit zu verarbeiten. Unicode legt aber nicht fest wie diese Codepoints intern gespeichert werden, darum kann man Unicode nicht speicher/laden oder über Netzwerkverbindungen schicken, denn in Dateien und über Netzwerkverbindungen gehen Bytes. Also muss man Unicode als Bytes kodieren mit einer Angabe einer Kodierung die sagt welche Bytewerte welches Zeichen kodieren. Und auch bei einem ``print`` muss das Unicode-Objekt kodiert werden, denn das ist ja ein schreiben in die Datei `sys.stdout`, die wie alle Dateien auch Bytes erwartet und das Programm auf der anderen Seite der Datei, zum Beispiel eine Konsole, erwartet dort Bytes in einer bestimmten Kodierung, damit die Konsole dann weiss welche Zeichen sie anzeigen muss. Und die Kodierung auf beiden Seiten muss die gleiche sein.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

kaineanung hat geschrieben:Wenn ich unicode habe: muss ich dann auf Unicode encoden damit ich dann das daraus resultirende nochmals in das 'richtige' umwandeln?
Also eine folgender Vorgang:
Unicode-Variable -> Byte-Variable -> Ascii-Variable (oder was auch immer um Umlaute richtig darstellen/verarbeiten zu können)?
Muss ich mir das so vorstellen?
Wie schon beschrieben, sollte Unicode nur für interne Darstellungen verwendet werden und Bytes für die Ausgabe. Bei einigen Ausgabearten denkt Python mit: So werden Umwandlungen von Unicode in Bytes bei der Ausgabe via `print()` für den ausgebenden Stream (meist STDOUT) automatisch im richtigen Encoding vorgenommen, sofern Python dieses Encoding ermitteln kann (schrieb BlackJack bereits). Auch für Operationen auf Dateien können entsprechende Wrapper genutzt werden, welche die nötigen Konvertierungen vornehmen, um dem Programmierer das Leben etwas leichter zu machen. Grundsätzlich muss man sich aber bewusst sein, dass letztlich fast immer Bytes in die Welt außerhalb von Python geschickt werden und dass es sich fast immer um Bytes handelt, wenn Python etwas von außerhalb einliest.

Den von dir beschriebenen Umwandlungspfad verstehe ich nicht so ganz. Wenn du Bytes verarbeitest, dann haben diese ein bestimmtes Encoding. Welches dies genau ist, musst du schon selbst ermitteln (sollte hoffentlich in der Dokumentation deiner "Bytes-Quelle" vermerkt sein) oder notfalls erraten (z.B. durch Nutzung geeigneter Tools). Und dann wandelst du von Bytes in Unicode eben unter Nutzung dieses Encodings um. Für den Weg von Unicode nach Bytes gilt der umgekehrte Weg: Man nimmt das Encoding des Ausgabemediums (Terminal, Datei, Pipe, Netzwerkverbindung, usw) und ruft ``mein_text.encode("mein_encoding")`` auf.

Das was du als ASCII-Variable bezeichnest, gibt es in dieser Form nicht. Am nahliegendsten wäre hier wohl ein Bytes-Objekt, welches mit ASCII kodiert wurde. Oder du hälst die von `repr()` zurückgelieferte Zeichenkette für ASCII. Wie dem auch sei: Vergiss am besten, dass es ASCII-Variablen gibt, sondern unterscheide besser nur zwischen Bytes und Unicode.

Bezüglich "Variablen in Python" könnte ich jetzt auch nochmal ein Fass aufmachen, aber das verkneife ich mir mal besser...
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

Ok, in Bytecode wird immer gearbeitet. Sei es die interne Speicherung der Variablen, sei es die Übermittlung über das Netzwerk oder auch lokal zu anderen Schnittstellen und der Gleichen.
Nur wenn ich es 'sichtbar', für den Menschen lesbar machen will, muss ich es entsprechend 'encodieren' (also nicht decodieren -> das war einer der Punkte wo ich nicht wusste wann encodiert und wann decodiert wird), richtig?

Ich habe also ein Listelement in welchem Bytes gespeichert sind. Wenn ich es jetzt in eine XML-Datei (und DAS ist das Ziel. Print dient mir monentan nur zum 'debuggen' / anschauen ob BS es 'gefunden' hat was ich suche) speichern will, muss ich es entsprechend encodieren?
Und zwar genau an der Stelle an dem ich den Inhalt wegschreibe (sei es nun das print() oder fobj.write() oder sonstwo)?

Ich habe ein Listelement 'Stadt' mit genau einem Element (in meinem Beispiel) mit dem Inhalt 'M\03ccnchen'.
Jetzt will ich es durch print ausgeben und zwar im richtig 'encodierten' Format.
also

Code: Alles auswählen

print(Stadt.encode("utf8"))
Habe ich das richtig verstanden?
Natürlich muss ich noch rausfinden in welchen Zeichensatz ich das encodieren muss.
Aber wie finde ich das heraus? Im Header der py-Datei habe ich utf8. Die PY-Datei ist auf einer Linux-Maschine gespeichert und wird auch dort ausgeführt (in der Shell per 'python ./dateiname.py')
Lediglich das 'Bearbeiten' der Datei (also programmieren) mache ich über UltraEdit32 von meiner Windows7-Maschine (Linux-Samba-Freigabe über das Netzwerk an der Linuxmashine wo das Script ist).
Muss ich auch darauf achten das UltraEdit das richtig speichert? Also sicherheitshalber die PY-Datei nach utf8 konvertieren oder bin ich da ganz falsch?

Mein Zeil ist es die gescprapten Inhalte von BS in eine XML-Datei zu speichern welche irgendwann mal dann durch ein anderes Python-Programm in eine mysql-DB gejagt wird. Ich denke also ich brauche da keine Bytecodierung sondern muss es 'lesbar' machen (schon alleine um es in der XML-Datei auch lesen zu können)
BlackJack

@kaineanung: Ich denke Du hast es immer noch falsch. Wenn Du Text in Form von Bytes hast, dann ist der ja bereits irgendwie kodiert, den muss man nicht kodieren, den kann man sogar gar nicht kodieren, jedenfalls nicht mit einer Zeichensatzkodierung. Du hast da ja auch keine Bytes sondern ein Unicode-Objekt (in einer Liste), wie man an dem u-Präfix leicht erkennen kann.

Wobei Deine Angabe ``u'M\03ccnchen'`` aus einem vorherigen Beitrag falsch ist, denn es müsste eigentlich ``u'M\xfcnchen'`` sein, sonst ist da vorher schon etwas schief gelaufen, beziehungsweise *kann* das gar nicht die Ausgabe sein, denn das ist nichts was der Python-Interpreter so ausgeben würde. Hatte ich vorher gar nicht drauf geachtet. Das ist eine unvollständige Oktal-Escapesequenz. Der Interpreter würde Oktal schon gar nicht ausgeben, der gibt Werte im Bytebereich immer als Hexadezimal-Escape-Sequenz aus wenn es dafür keine spezielle Escapesequenz gibt. Falls nach dem Backslash ein 'u' stehen sollte, dann ist das Mόnchen und nicht München.

Du hast kein Listelement mit einem Element sondern eine Liste mit einem Element. Und mir ist aus der Beschreibung nicht wirklich klar an was `Stadt` nun gebunden ist — die Liste oder das Element? Wenn das die Liste ist, dann geht das natürlich nicht weil Listen keine `encode()`-Methode haben.

Was als Kodierungskommentar in der Quelltextdatei steht bezieht sich nur auf den Quelltext in der Datei. Das hat nichts damit zu tun was mit Bytes/Zeichenketten passiert die während des Programmlaufs verarbeitet werden, nur was der Compiler aus Bytewerten ausserhalb des ASCII-Wertebereichs in der Quelltextdatei macht. Und die tatsächliche Kodierung der Quelltextdatei sollte natürlich mit der im Kommentar angegebenen übereinstimmen.

Welche Kodierung man verwenden muss oder will hängt davon ab was man mit den Bytes machen will. Da gibt's keine allgemeine Antwort darauf wie man das herausfindet. Das muss man halt *wissen*. Zum Beispiel weil man weiss was ein anderes Programm welches die Daten weiterverarbeiten soll als Kodierung erwartet.

XML wirst Du ja nicht ”von Hand” erstellen mit Zeichenketten-Operationen sondern eine XML-Bibliothek verwenden. Da die Spezifikation für XML-Dokumente auf Unicode aufbaut brauchst und solltest Du da nichts kodieren sondern der API von der verwendeten Bibliothek einfach die Unicode-Objekte übergeben. Für das serialisieren von XML ist auch eine Kodierung vorgegeben und es ist vorgesehen das man davon abweichen kann wenn die Kodierung entsprechend in der XML-Datei angegeben ist. Aber normalerweise muss man sich da gar nicht drum kümmern, das macht alles die XML-Bibliothek. `xml.etree` aus der Standardbibliothek oder `lxml` wenn es etwas externes sein darf, würde ich da empfehlen. Beide verwenden die gleiche API, `lxml` mit ein paar Erweiterungen.
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@BlackJack

Ich mache folgendes:
mit der liburl2 hole ich eine HTML-Seite von einem Webserver.
Dann hole ich mir das Ergebnis in BS und filtere/suche nach bestimmten Tags (DIV-Container mit bestimmter Class und dann ein a-Tag (a href) mit bestimmter Class.
Daraufhin weise ich das Ergebnis einer Variable (wie wir festgestellt haben wird daraus eine Liste weil wohl das BS eine Liste beinhaltet mit den Contents -> in meinem Fall eben nur ein Content) zu.
Diese Variable, hier genannt 'Stadt', will ich nun ausgeben als auch später in eine XML-Datei schreiben.
Und diese Variable/Liste hat Unicode mit bereits falscher Kodeirung wie du es schön beschrieben hast.
So, wo sollte ich dann in diesem Ablauf ansetzen um die richtige Kodierung in der Liste zu haben und wie/wo kodiere ich es dann bei der 'Ausgabe' um damit ich dann lesbaren Text erhalte (die Umlaute also)?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@kaineanung: In diesem ganzen Prozess mußt Du überhaupt nichts kodieren oder encodieren. BS liest die Kodierinformation aus den HTML-Daten und liefert Dir Unicode. Wenn Du also Mόnchen erhältst, dann liefert die Webseite schon ein falsches Encoding mit, ISO 8859-7 statt ISO 8859-1. Um das zu reparieren, muß man ziemlich viel herumklemptnern, also BS ein alternatives Encoding unterschieben.
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@sirius3

Wenn ich es dann nicht BS unterjublen soll, kann ich es im Nachhinen dann 'reparieren'?
Wenn es also schon in einer Liste oder STR/UNICODE-Variable ist?
BlackJack

@kaineanung: Ich würde erst einmal schauen ob der Webserver vielleicht die Kodierung in den Headern übermittelt und die dann BS mitzuteilen (`from_encoding`-Argument).
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@BlackJack

Meinst du das:

Code: Alles auswählen

<head>
	<meta charset="utf-8" />
        .
        .
</head>
?

Ist wohl utf-8..
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@kaineanung: So wie BlackJack das formuliert hatte, würde ich eher an das "Content-Type"-Attribut aus dem HTTP-Header denken. Dieses ermittelst du beim Abfragen der Daten vom Server. Und das macht ja auch deutlich mehr Sinn, da der Vorschlag ja war, dieses Encoding BeautifulSoup zum Parsen mitzugeben. Also sollte man das sinnvollerweise schon kennen, bevor man die Seite durch den HTML-Parser jagt.
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@snafu

Und wo steht dieser Content-Type im HTML-Dokument?
Ich habe den Quellcode der Seite durchsucht und da steht nichts von einem Content-Type?
Steht dieser im <head>-Tag oder davor oder nirgends und ich muss es anders herausfinden?
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der steht ueblicherweise im Header des HTTP-Requests. Den kannst du dir zB im Debugger im Browser anschauen. Fuer dieses Request hier, das ich gemacht habe um dir zu antworten, steht da zB

Code: Alles auswählen

Cache-Control:private, no-cache="set-cookie"
Connection:Keep-Alive
Content-Encoding:gzip
Content-Type:text/html; charset=UTF-8
Date:Mon, 19 Oct 2015 15:18:50 GMT
Expires:0
Keep-Alive:timeout=5, max=100
Pragma:no-cache
Server:Apache/2.2.31
Transfer-Encoding:chunked
Vary:Accept-Encoding
X-Powered-By:PHP/5.3.29
Und siehe da: UTF-8, gleich im content-type header.
BlackJack

Wobei es schon ziemlich fies ist wenn die Webseite ein ``<meta charset="utf-8" />`` enthält, der Webserver dann aber eine andere Kodierung beim `Content-Type` angibt. Denn irrwitzigerweise hat der Webserver das letzte Wort in dieser Angelegenheit, obwohl man doch annehmen möchte der Autor des jeweiligen Dokuments wüsste besser wie das kodiert ist. Wobei wenn da bei Deinem Dokument wirklich UTF-8 steht, frage ich mich wie Mόnchen zustande gekommen ist. Sehr verwirrend alles. Da werde ich ja fast neugierig welche Webseite das ist und was da tatsächlich ausgeliefert wird.
rmp

Nö. Es ist einerseits simpler und andererseits komplizierter.

Also: In einem Programm wird letztlich mit Bytes gearbeitet, egal ob 1 oder 2 oder 4 (je nach Sprache/Interpreter/Compiler). Allerdings sind Bedeutungen da (in aller Regel; es gibt Ausnahmen) schnurz. Für uns Menschen hat "g" eine Bedeutung und "z" auch. Für den Prozessor nicht; für den sind das nur Bytes.

Und genau darum geht's bei En/Decoding, Um Bedeutung für Menschen.

Beim Decodieren sagst Python sozusagen, dass z.B. beim Lesen einer Datei die (bedeutungsbehafteten) Zeichen mit der Codierung windows 1252 oder iso 8859-1 vorhanden sind. daraus muss der Python Interpreter dann durch Decodieren Bytefolgen machen, mit denen er intern arbeitet. genauso, nur andersrum, ist es beim Schreiben einer (Text)Datei. Dann muss der Interpreter aus den Bytefolgen wieder (bedeutungsbehaftete) codierte Zeichen machen.

Das mit dem webserver ist im Grunde eine Fortsetzung dieser Suppe, nur mit zusätzlichen Fallen. Der server (letztlich ja auch ein Programm, das mit Bytefolgen operiert) kann ja nicht riechen, wie das ihm zugelieferte Material kodiert ist. Also spuckt er entweder alles in einer konfigurierten Kodierung raus (meist UTF-8) oder er liest die Info aus der hmtl Datei (bzw. kriegt sie vom Produzenten, also der "app", die sie liefert). Im hiesigen Forum z.B. liefert die Forensoftware dem web server als eine der ersten Zeilen '<meta http-equiv="content-type" content="text/html; charset=UTF-8" />', so dass der weiss, dass das UTF-8 codiert ist.

Problematisch wird das dann, wenn der web server "belogen wird" und z.B. eine auf Windows erstellte html Datei mit win-1252 Kodierung kriegt, der web server sie aber treuherzig als UTF-8 ausgibt ... und der Browser das wiederum treuherzig glaubt und entsprechend - falsch - anzeigt.
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@__deets__

Also ich habe die Seite im Mozilla geladen und dann 'Wuelltext anzeigen' lassen.
Das nun wiederrum kopiert und in den UE eingefügt.
Wenn ich mir alles anschaue (und natürlich danach suche wobei es bei einer HTML-Seite ja nur im Kopf stehen dürfte) sehe ich leider nichts dergleichen.

Ich habe nach charset gesucht und lediglich die eine Angabe gefunden:
<meta charset="utf-8" />
Natürlich habe ich noch nach 'utf' und 'charset' gesucht (und nebenbei noch weitere wie latin, iso usw..) und nur das bereits gepostete gefunden.

In der folgenden Zeile noch ein
<meta http-equiv="x-ua-compatible" content="IE=edge">

(Poste ich nur weil @rmp "'<meta http-equiv="content-type" content="text/html; charset=UTF-8" />" gepostet hat und ich auch nach equiv gesuchth abe und auch nur das gefunden habe).

Somit steht lediglich im Header das charset utf-8! Und BlackJack hat ja bereits etwas von wegen 'gelogen' gesagt.

@BlackJack
Nur mal so: es ist eine halbwegs bekannte und auch sicherlich gut besuchte Seite...


Aber ein anderer Ansatz dann:
kann ich nicht die gängigen deutschen Codierungen 'ausprobieren' bis mir München geliefert wird? Ein 'reversed engeneering' sozusagen?
Wo setze ich die 'Quellcodierung' beim BS und welche wären denn 'gängig'? utf-8, ISO 8859-1 und was noch?
Antworten