• Hallo liebe Userinnen und User,

    nach bereits längeren Planungen und Vorbereitungen sind wir nun von vBulletin auf Xenforo umgestiegen. Die Umstellung musste leider aufgrund der Serverprobleme der letzten Tage notgedrungen vorverlegt werden. Das neue Forum ist soweit voll funktionsfähig, allerdings sind noch nicht alle der gewohnten Funktionen vorhanden. Nach Möglichkeit werden wir sie in den nächsten Wochen nachrüsten. Dafür sollte es nun einige der Probleme lösen, die wir in den letzten Tagen, Wochen und Monaten hatten. Auch der Server ist nun potenter als bei unserem alten Hoster, wodurch wir nun langfristig den Tank mit Bytes vollgetankt haben.

    Anfangs mag die neue Boardsoftware etwas ungewohnt sein, aber man findet sich recht schnell ein. Wir wissen, dass ihr alle Gewohnheitstiere seid, aber gebt dem neuen Board eine Chance.
    Sollte etwas der neuen oder auch gewohnten Funktionen unklar sein, könnt ihr den "Wo issn da der Button zu"-Thread im Feedback nutzen. Bugs meldet ihr bitte im Bugtracker, es wird sicher welche geben die uns noch nicht aufgefallen sind. Ich werde das dann versuchen, halbwegs im Startbeitrag übersichtlich zu halten, was an Arbeit noch aussteht.

    Neu ist, dass die Boardsoftware deutlich besser für Mobiltelefone und diverse Endgeräte geeignet ist und nun auch im mobilen Style alle Funktionen verfügbar sind. Am Desktop findet ihr oben rechts sowohl den Umschalter zwischen hellem und dunklem Style. Am Handy ist der Hell-/Dunkelschalter am Ende der Seite. Damit sollte zukünftig jeder sein Board so konfigurieren können, wie es ihm am liebsten ist.


    Die restlichen Funktionen sollten eigentlich soweit wie gewohnt funktionieren. Einfach mal ein wenig damit spielen oder bei Unklarheiten im Thread nachfragen. Viel Spaß im ngb 2.0.

[Python] Email vernünftig decodieren

Roin

Freier Denker

Registriert
22 Juli 2013
Beiträge
581
Hallo Leute,

ich muss für ein Projekt ein Programm in Python schreiben.
Als einer der ersten Schritte muss ich Dateien einlesen (.eml) und einige Zeilen daraus extrahieren.

Klappt auch mit einer kleinen for-Schleife.

Einziges Problem dabei ist, dass ich die Zeichenketten nicht vernünftig decodiert kriege.

Der Header der Emails sieht wie folgt aus:

Return-Path: <*>
Received: from * (*)
by * (Cyrus v2.4.16-Debian-2.4.16-4+deb7u1) with LMTPA;
Sun, 29 Mar 2015 16:16:14 +0200
X-Sieve: CMU Sieve 2.4
Received: from * ([*] helo=*)
by * with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:256)
(Exim 4.80 nylar)
id 1YcE0b-0006Li-NL
for *; Sun, 29 Mar 2015 16:16:13 +0200
To: * <*>
Subject: Betreff
From: * <*>
ReplyTo: * <*>
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
Date: Sun, 29 Mar 2015 16:16:11 +0200 (CEST)
Message-Id: <*>
X-IMT-Spam-Score: 0.8 ()
X-PMX-Version: 6.2.0.2453472, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2015.3.29.140620
X-PerlMx-Spam: Gauge=IIIIIIII, Probability=8%, Report='
FROM_NAME_ONE_WORD 0.05, HTML_00_01 0.05, HTML_00_10 0.05, SUPERLONG_LINE 0.05, URI_ENDS_IN_HTML 0, __ANY_URI 0, __CANPHARM_UNSUB_LINK 0, __CP_URI_IN_BODY 0, __CT 0, __CTE 0, __CT_TEXT_PLAIN 0, __FRAUD_INTRO 0, __HAS_FROM 0, __HAS_MSGID 0, __HIGHBITS 0, __MIME_TEXT_ONLY 0, __SANE_MSGID 0, __STOCK_PHRASE_7 0, __TO_MALFORMED_2 0, __URI_NS '
X-IMT-Authenticated-Sender:
(Sterne ersetzten diverse sensible Daten)

Ein einfaches einlesen mit UTF-8 als Codierung funktioniert leider nicht. Dann ist weiterhin alles "quoted-printable", also alle Sonderzeichen mit =xx ersetzt und das '=' mit =3D ersetzt.


[src=python]import codecs
import quopri
from email import quoprimime

def load(filename):
file = codecs.open(filename, "r", "utf-8");
# file = open(filename)
#
dec_file = ""
lines = ""
for line in file:
lines += line
#
dec_file = quopri.decodestring(lines)
# dec_file = quoprimime.decode(lines)
#
#
print dec_file[/src]
Damit sind zwar die '=' wieder in Ordnung, aber die Umlaute sind "kaputt"
ü = ü, ° = °
und so weiter ...

Gibt es da eine Möglichkeit das vernünftig zu machen oder muss ich mir die entsprechenden Ersetzungen durch dieses quoted-printable raussuchen und selbstständig ersetzten lassen?
 

exomo

NGBler

Registriert
1 Aug. 2015
Beiträge
129
Das scheint mir auf den ersten Blick nicht falsch zu sein. Das ist wie im Header angegeben die UTF-8 kodierung von "ü", wenn man es fälschlicherweise als ASCII interpretiert. Dein Problem ist also eher, dass print mit UTF-8 nichts anfangen kann. Der String an sich ist korrekt.
Um den String in das "default encoding" zu übersetzen kannst du eventuell sie String .decode() Methode verwenden:
http://www.tutorialspoint.com/python/string_decode.htm (mit Beispiel für UTF-8)
 

Roin

Freier Denker

Registriert
22 Juli 2013
Beiträge
581
  • Thread Starter Thread Starter
  • #3
Wenn ich bei der Ausgabe oder auch bereits vorher die .decode("UFT-8")-Methode nutze, bekomme ich allerdings immernoch keine vernünftige Ausgabe.

Nun werden alle Sonderzeichen und Umlaute als Kästchen dargestellt.
Scheint also auch nicht zu klappen.
 

darksider3

NGBler

Registriert
18 Sep. 2013
Beiträge
393
Ort
/dev/sda
UTF-8 oder Windows CP-*(Whatever) Codepages?
Wenn man das unter Windows versucht macht es halt mal schnell "boom" :D

Edit:
Code:
locale charmap
zeigt Dir das aktuelle Encoding ... (Manpages mussten berufen werden..) auf Linux/UNIX/BSD an.
 

Roin

Freier Denker

Registriert
22 Juli 2013
Beiträge
581
  • Thread Starter Thread Starter
  • #5
Wenn ich in der Konsole [src=python]locale.getdefaultlocale()[/src] aufrufe bekomme ich
('de_DE', 'cp1252')

Wenn ich nun allerdings in meinem Code den String mit dem Encoding ausgeben will, passiert da noch mehr Unfug mit.

Falls es hilft: Ich benutze Netbeans 8.1 mit dem Plugin Jython 2.7.x


EDIT:
Ich habe gerade einfach mal meinen Code in der Console Zeile für Zeile eingegeben, wie ich da gesehen habe, scheint es richtig ausgeführt zu werden.
Hat Netbeans irgendwo im Hintergrund eine Standard-Kodierung angegeben, mit der es alles kaputt macht?

EDIT2:
Wie kann ich nun den decodierten String "Zeilenweise" durchgehen?
Mit der obigen for-Schleife geht der ja Zeichenweise durch.
Müsste ich in der oben for-Schleife noch Umbrüche einfügen lassen?
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.573
Schreib mal folgende Zeile:
[src=python]dec_file = quopri.decodestring(lines)[/src]

zu folgendem um:

[src=python]dec_file = quopri.decodestring( codecs.encode(lines, "utf-8") )[/src]

Da du sonst im normalen Python Interpreter folgende Fehlermeldung bekommen wirst, in Python 2.7.x.

Zum Beispiel:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1613-1614: ordinal not in range(128)

Das bekomme ich beispielsweise in dieser Zeile ohne das zusätzliche codecs.encode(lines, "utf8")
[src=python]dec_file = quopri.decodestring(lines)[/src]

Bei mir funktioniert die Ausgabe mit print lines bzw. print dec_file allerdings dann bestens als UTF-8, checke ich gerade mit einer EML-Datei - allerdings erst nach dem Codecs fix.

Ist in Idle unter Linux alles korrekt.

---

Ich würde dir vorschlagen, installiere dir die normale Windows Version von Python 2.7.x und arbeite, so naiv es sich anhört, mit Idle.
Bei einem kleinen Skript tut das nicht weh und du hast auch nicht die Probleme das Netbeans oder Jython irgendwas verhunzen was nicht in einer normalen Python Installation der Fall wäre.
 

exomo

NGBler

Registriert
1 Aug. 2015
Beiträge
129
Die Linux Konsole kann im Gegensatz zu Windows mit Unicode umgehen.
Python verwendet wohl intern Unicode für strings. Für Windows könnte es vielleicht auch helfen vor der Ausgabe explizit auf cp1252 zu kodieren.
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.573
Unicode für Strings gibt es erst ab Version 3. Python 2.7.x hat als Standard noch Ascii.

Die Ausgabe war jetzt aber nicht in der Konsole, sondern im Shell-Ausgabefenster von Idle, in meinem Testdurchlauf.
 

Roin

Freier Denker

Registriert
22 Juli 2013
Beiträge
581
  • Thread Starter Thread Starter
  • #9
[src=python]# -*- coding: utf-8 -*-

import codecs
import quopri
from email import quoprimime

def load(filename):
# Datei einlesen
file = codecs.open(filename, "r", "utf-8");
# file = open(filename)
#
dec_file = ""
txt = ""
# txt = file.readlines()

# Zusammenhängenden Text aus der Email machen
for line in file:
# print line
if line.strip().endswith("="):
txt += line.strip()[:-1]
else:
txt += line.strip() + "\r\n"
# Quoted-Pintable entfernen
dec_file = quopri.decodestring(codecs.encode(txt, "utf-8"))

# dec_file = dec_file.decode('UTF-8', 'strict')
# dec_file = quoprimime.decode(lines)
#
#
# dec_file = dec_file.decode("UTF-8", "ignore")

# Text nun zeilenweise verarbeiten
lines = dec_file.split("\r\n")

print lines
print dec_file

curr_line = 0
first_line = 0
last_line = 0
significant_lines = []

# print len(lines)


for line in lines[:]:
# Leere Zeilen entfernen
if line == u"":
lines.remove(line)
curr_line = curr_line - 1

# Erste Zeile bestimmen
elif "Wettermeldungen" in line:
first_line = curr_line + 1

# Letzte Zeile bestimmen
elif first_line > 0 and last_line == 0 and "=" in line:
last_line = curr_line - 1
# if "ü".decode("utf-8") in line:
# print line

curr_line = curr_line + 1

# print len(lines)
# print first_line
# print last_line

# Interessante Zeilen in eine Liste einlesen
significant_lines = lines[first_line:last_line+1]

# print len(significant_lines)
print significant_lines[/src]

Die Ausgabe von dec_file sieht jetzt gut aus.
Die Ausgabe von significant_lines sieht halt jetzt wie ne Liste aus, in der die Umlaute noch als \xc3 oder so stehen, aber solange der damit vernünfig arbeiten kann, bin ich erstmal zufrieden.

Damit habe ich dann schonmal aus ein paar Millionen Zeilen nur noch ein paar Tausend gemacht. (Ich muss über 2000 Emails mit den Datensätzen durch das Programm durchjagen).
Die Daten dann weiter zu extrahieren sollte erstmal kein weiteres Problem sein.

Ist es eventuell sinnvoll, die Daten noch weiter explizit auf eine Codierung festzulegen?
Da Netbeans ja anscheinend kein Python 3.x als Plugin hat, muss ich wohl vorerst in 2.7 programmieren, da ich auf meine gewohnte Umgebung erstmal nicht verzichten möchte.
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.573
Was dir vielleicht noch etwas entgegenkommt, das hier zu überfliegen:
https://docs.python.org/2/howto/unicode.html

Speziell hier dieser Part:
https://docs.python.org/2/howto/unicode.html#the-unicode-type

Ein minimaler Auszug:
Much Python code that operates on strings will therefore work with Unicode strings without requiring any changes to the code. (Input and output code needs more updating for Unicode; more on this later.)

Beantwortet das deine Frage bezüglich einer festgelegten Kodierung?
 

Roin

Freier Denker

Registriert
22 Juli 2013
Beiträge
581
  • Thread Starter Thread Starter
  • #11
Also muss ich im Endeffekt einmal beim Einlesen von Daten sagen, dass das auch in UTF-8 sein soll (wenn die Text-Datei anders kodiert sein sollte) und das wars dann. Klingt doch nicht schlecht. :)
 
Oben