Suche nach Mail-Adressen

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
Benutzeravatar
HL
User
Beiträge: 14
Registriert: Donnerstag 20. März 2008, 01:05
Kontaktdaten:

Hallo,

in einem String suche ich nach "@domain.tld".

Ich bekommen das @-Zeichen allerdings als extra Treffer zurück?! Wie kann ich das verhindern?
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

._.

Code: Alles auswählen

In [1]: text = "lorem ipSUm blabla@domain.de blabla bla@domain.de"

In [2]: emailadressen = [x for x in text.split() if "@domain.de" in x]

In [3]: emailadressen
Out[3]: ['blabla@domain.de', 'bla@domain.de']
(Ich mag' immer noch keine regulären Ausdrücke...)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

HL hat geschrieben:in einem String suche ich nach "@domain.tld".

Ich bekommen das @-Zeichen allerdings als extra Treffer zurück?! Wie kann ich das verhindern?
Anders suchen.

Mal ehrlich, erwartest du, dass wir erraten wie du danach suchst? Wenn du Code stellst, dann kann man eine Aussage treffen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
HL
User
Beiträge: 14
Registriert: Donnerstag 20. März 2008, 01:05
Kontaktdaten:

@Leonidas: Nein, das habe ich nicht erwartet. Eher erwartete ich so etwas wie "Das @ muss so uns so maskiert werden" oder ähnliches, da ich mir mit meinem Code eigentlich sicher war.

Was sich dann später rausstellte war, dass ich in der "DateiMitDomainsZumSuchen.txt" eine Zeile übersehen hatte in der tatsächlich nur ein @ stand... hatte mir also selbst ein Bein gestellt :?

Hier aber dennoch der Code:

Code: Alles auswählen

file1 = open("DateiMitTextUndMailAdressen.txt","r")
for line1 in file1: 
    line1 = line1.strip()
        
    file2 = open("DateiMitDomainsZumSuchen.txt", "r")
    for line2 in file2:
        line2 = line2.strip()
        
        if line2 in line1:
            print line1
            
    file2.close()
file1.close()
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Du bist dir sicher, dass du den Code so haben willst? D.h. bei jeder Zeile die Datei mit den Domains komplett neu einlesen?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Dem stimme ich zu, die willst du vermutlich lieber im Speicher halten.

Zudem empfehle ich dir einen Blick auf das `with`-Statement.
shakebox
User
Beiträge: 175
Registriert: Montag 31. März 2008, 17:01

@Y0Gi

Wenn ich da mal rein aus Interesse zwischengraetschen darf: was meinst Du denn mit dem "with"-Statement? Das finde ich weder per help() noch taucht das im Index meines Exemplares der Python Essential Reference auf.

Bin ja auch neu in Python und versuche deshalb hier bei allen Tipps und Hinweisen mitzulernen :)

Danke!
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

@shakebox: Dann zieh doch einfach mal die Dokumentation zur Hilfe ;-) Und ein Statement kannst du mit "help" natürlich nicht finden.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beispiel vorher:

Code: Alles auswählen

f = open('foo.txt')
for line in f:
    print line
f.close()
Beispiel nachher:

Code: Alles auswählen

from __future__ import with_statement  # in Python 2.5

with open('foo.txt') as f:
    for line in f:
        print line
Dabei wird die Datei automatisch beim Verlassen des `with`-Blocks geschlossen, auch wenn ein Fehler aufgetreten ist (sonst müsste man da mit `try`/`finally` ran - etwas unschön).


P.S.: Das `with`-Statement kann auch in anderen Bereichen verwendet werden, z.B. mit Locks oder Sockets. Leider sind diese nicht immer entsprechend vorbereitet (ich hoffe, das wird in Python 2.6 so sein?!), so dass man mit `contextlib.closing` den Aufruf erst noch wrappen muss.
Benutzeravatar
HL
User
Beiträge: 14
Registriert: Donnerstag 20. März 2008, 01:05
Kontaktdaten:

Hey, Danke für die Tipps! Als Anfänger kann ich die sehr gut gebrauchen!

Mein Code sieht jetzt wie folgt aus und läuft 4x schneller:

Code: Alles auswählen

#!/usr/bin/env python2.5

from __future__ import with_statement

domains = []

with open('domains.txt', "r") as dfile:
    for line in dfile:
        line = line.strip()
        domains.append(line)
    dfile.close()

with open("DateiMitDomainsZumSuchen.txt", "r") as f:
    for line in f: 
        line = line.strip()

        for domain in domains:
            if domain in line:
                print line
    f.close()
Habe ich die Tipps richtig verstanden?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Code: Alles auswählen

#!/usr/bin/env python2.5

from __future__ import with_statement

def extract_domains(domain_file, source_file):
    with open(domain_file, "r") as dfile:
        domains = set(x.strip() for x in dfile)

    with open(source_file"r") as fp:
        lines = set(line.strip() for line if fp for d in domains if d in line.strip())

    return lines
Ich habe deinen Code mal noch etwas gekürzt. Das Schließen der Dateien wird durchdie with-Statements überflüssig.

Das doppelte "line.strip()" könnte man noch durch "imap" im Modul "intertools" eleminieren.
Benutzeravatar
HL
User
Beiträge: 14
Registriert: Donnerstag 20. März 2008, 01:05
Kontaktdaten:

Danke, aber ich finde Deine Variante nicht sehr übersichtlich bzw. nicht gut lesbar. Dir ging es vermutlich ähnlich, denn es hat sich auch ein kleiner Fehler eingeschlichen ;-)

Code: Alles auswählen

lines = set(line.strip() for line if fp for d in domains if d in line.strip())

Code: Alles auswählen

lines = set(line.strip() for line in fp for d in domains if d in line.strip())
Hat Deine Variante, ausser dass sie kürzer ist, noch weitere Vorteile?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

HL hat geschrieben:Danke, aber ich finde Deine Variante nicht sehr übersichtlich bzw. nicht gut lesbar.
Ich hingegen finds gut. Der erste Teil gibt dir eine Menge an Domains zurück (denn eigentlich willst du ja eine Menge, keine Liste). Dabei wird die Datei komplett durchlaufen, die Zeilen gestrippt und in eine Menge konvertiert und der zweite Teil... hmm, ja die ist schon etwas unübersichtlicher, da würde ich wohl auch auf mehrere Zeilen ausweichen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

So ein in/if-Dreher kann schon mal passieren, ich teste den Code nach nicht vor dem Posten. Man kann natürlich auch den Generator in mehreren Zeilen schreiben:

Code: Alles auswählen

lines = set(line.strip() for line in fp 
                         for d in domains
                         if d in line.strip())
Benutzeravatar
HL
User
Beiträge: 14
Registriert: Donnerstag 20. März 2008, 01:05
Kontaktdaten:

Sorry, ich wollte nicht besserwisserisch oder unfreundlich rüberkommen - falls dieser Eindruck entstanden sein sollte.

Das mit der Menge und auch mit set, verstehe ich noch nicht ganz, ich muss halt noch viel lernen und bin Dankbar um jeden Zaunpfahl ;)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

HL hat geschrieben:Sorry, ich wollte nicht besserwisserisch oder unfreundlich rüberkommen - falls dieser Eindruck entstanden sein sollte.
Kamst du für mich gar nicht, die Einwände sind ja auch durchaus berechtigt.
HL hat geschrieben:Das mit der Menge und auch mit set, verstehe ich noch nicht ganz, ich muss halt noch viel lernen und bin Dankbar um jeden Zaunpfahl ;)
Der Vorteil an einer Menge ist, dass Elemente darin nur einmal enthalten sind. In einer Liste kannst du die selbe E-Mail-Adresse mehrfach ablegen in einer Menge geht das nicht mehr. Darauf kann eine Datenstruktur dann natürlich optimiert werden. Das bringt u.U. mehr Geschwindigkeit beim Prüfen, ob ein Element in der Liste vorhanden ist. Das macht sich zwar nur bei sehr vielen Tests bemerkbar, aber die Menge ist in diesem Fall halt die richtige Datenstruktur.

Und lass dich von dem Generator zwischen den Klammern beim "set" nicht irritieren. Es funktioniert z.B. auch "set([1,2,3,2,1])". Am besten schaust du mal in die Doku.
Antworten