2009-02-14 30 views
10

Estoy tratando de extraer direcciones de correo electrónico de transcripciones de texto sin formato de correos electrónicos. He improvisado un poco de código para encontrar las direcciones, pero no sé cómo hacer que discrimine entre ellas; en este momento solo escupe todas las direcciones de correo electrónico en el archivo. Me gustaría hacerlo, así que solo arroja direcciones que están precedidas por "De:" y algunos caracteres comodín, y termina con ">" (porque los correos electrónicos están configurados como De [nombre] < [correo electrónico]>)Analizando direcciones "desde" del texto del correo electrónico

Aquí está el código ahora:

import re #allows program to use regular expressions 
foundemail = [] 
#this is an empty list 

mailsrch = re.compile(r'[\w\-][\w\-\.][email protected][\w\-][\w\-\.]+[a-zA-Z]{1,4}') 
#do not currently know exact meaning of this expression but assuming 
#it means something like "[stuff]@[stuff][stuff1-4 letters]" 

     # "line" is a variable is set to a single line read from the file 
# ("text.txt"): 
for line in open("text.txt"): 

    foundemail.extend(mailsrch.findall(line)) 

    # this extends the previously named list via the "mailsrch" variable 
     #which was named before 

print foundemail 

Respuesta

2

Lo haría expandiendo la expresión regular que está utilizando para incluir el texto adicional que desea emparejar.Así que en primer lugar, permítanme explicar lo que hace que la expresión regular:

[\w\-][\w\-\.][email protected][\w\-][\w\-\.]+[a-zA-Z]{1,4} 
  • [\w\-] coincide con cualquier "palabra" carácter (letra, número o guión), o un guión
  • [\w\-\.]+ partidos (cualquier carácter de palabra o guión o periodo) una o más veces
  • @ coincide con un literal '@'
  • [\w\-] coincide con un carácter de palabra o guión
  • [\w\-\.]+ partidos uno o más caracteres de texto, guiones y/o períodos
  • [a-zA-Z]{1,4} partidos 1, 2, 3, o 4 minúsculas o letras mayúsculas

ahora, a modificar esto para sus propósitos, vamos a añadir partes de expresiones regulares para que coincida con "de", el nombre y los paréntesis angulares:

From: [\w\s]+?<([\w\-][\w\-\.][email protected][\w\-][\w\-\.]+[a-zA-Z]{1,4})> 
  • From: partidos es el texto literal "De:"
  • [\w\s]+? coincide con uno o más caracteres de palabras consecutivos o caracteres de espacio. El signo de interrogación hace que el partido no sea codicioso, por lo que coincidirá con el menor número posible de personajes al tiempo que permite que coincida toda la expresión regular (en este caso, probablemente no sea necesario, pero hace que el partido sea más eficiente ya que viene inmediatamente después no es un carácter de palabra o personaje espacial).
  • < coincide con un signo de menos literal (ángulo de apertura)
  • La misma expresión regular que tenía antes ahora está rodeada por paréntesis. Esto lo convierte en un grupo de captura de , por lo que puede llamar al m.group(1) para obtener el texto que coincide con esa parte de la expresión regular.
  • > coincide con un literal signo mayor que

Dado que la expresión regular ahora utiliza grupos de captura, el código tendrá que cambiar un poco así:

import re 
foundemail = [] 

mailsrch = re.compile(r'From: [\w\s]+?<([\w\-][\w\-\.][email protected][\w\-][\w\-\.]+[a-zA-Z]{1,4})>') 

for line in open("text.txt"): 
    foundemail.extend([m.group(1) for m in mailsrch.finditer(line)]) 

print foundemail 

El código [m.group(1) for m in mailsrch.finditer(line)] produce una lista cabo del primer grupo de captura (recuerde, esa fue la parte entre paréntesis) de cada partida encontrada por la expresión regular.

+0

heh, parece publicado mientras aún escribía el mío. Obtuvimos el mismo resultado final, pero puede usar mailsrc.findall() aún; si solo hay un grupo, devuelve una lista de coincidencias para ese grupo, por lo que se evita la necesidad de una comprensión de la lista. – Jay

+0

esto es perfecto, gracias! También probaré con Jay para poder obtener algunas versiones diferentes. Gracias también por la extensa explicación. –

+0

Interesante, no sabía eso ... de alguna manera extraña para que la función actúe:? –

0

si usted puede estar razonablemente seguro de que las líneas que contienen estas direcciones de correo electrónico comienzan con un espacio en blanco seguido de "De:" simplemente puede hacer esto:

addresslines = [] 
for line in open("text.txt"): 
    if line.strip().startswith("From:"): 
     addresslines.append(line) 

luego, o al agregarlos a la lista, puede refinar los elementos de las líneas de dirección para dar exactamente lo que quiere

+0

Hm, debo implementar esto incorrectamente ... Se queda en blanco o muestra toda la lista que obtenía antes. –

0

"[cosas] @ [cosas] [cosas1-4 letras]" es sobre la plataforma ht, pero si quisieras podrías decodificar la expresión regular usando un truco que acabo de descubrir, here. Hacer la compilación() en una sesión de Python interactiva de esta manera:

mailsrch = re.compile(r'[\w\-][\w\-\.][email protected][\w\-][\w\-\.]+[a-zA-Z]{1,4}', 128) 

Se imprimirá el siguiente:

in 
    category category_word 
    literal 45 
max_repeat 1 65535 
    in 
    category category_word 
    literal 45 
    literal 46 
literal 64 
in 
    category category_word 
    literal 45 
max_repeat 1 65535 
    in 
    category category_word 
    literal 45 
    literal 46 
max_repeat 1 4 
    in 
    range (97, 122) 
    range (65, 90) 

Lo cual, si la clase de puede acostumbrarse a ella, le muestra exactamente cómo el RE funciona

+0

No acaba de responder la pregunta, pero es un truco perfecto ... gracias por señalar eso :-) –

32

Trate de hacer esto:

>>> from email.utils import parseaddr 

>>> parseaddr('From: [email protected]') 
('', '[email protected]') 

>>> parseaddr('From: Van Gale <[email protected]>') 
('Van Gale', '[email protected]') 

>>> parseaddr(' From: Van Gale <[email protected]> ') 
('Van Gale', '[email protected]') 

>>> parseaddr('blah abdf From: Van Gale <[email protected]> and this') 
('Van Gale', '[email protected]') 

Por desgracia, sólo se encuentra el primer correo electrónico en cada línea, ya que está esperando líneas de cabecera, pero tal vez eso está bien?

+1

parseaddr es realmente sólo AddressList (addr) .dresslist [0] por lo que puede hacer AddressList (addr) .addresslist para obtener todos ellos –

2
mailsrch = re.compile(r'[\w\-][\w\-\.][email protected][\w\-][\w\-\.]+[a-zA-Z]{1,4}') 

desglose de expresión:

[\w-]: cualquier carácter de palabra (alfanuméricos, además de subrayar) o un guión

[\w-.]+: cualquier carácter de palabra, un guión, o un período/punto, uno o más

veces

@: @ símbolo literal

[\w-][\w-.]+: palabra CHAR o das h, seguido de cualquier palabra char, dash o period una o más veces.

[a-zA-Z]{1,4}: cualquier carácter alfabético 1-4 veces.

Para hacer que este partido sólo las líneas que comienzan con From:, y envuelto en <y> símbolos:

import re 

foundemail = [] 
mailsrch = re.compile(r'^From:\s+.*<([\w\-][\w\-\.][email protected][\w\-][\w\-\.]+[a-zA-Z]{1,4})>', re.I | re.M) 
foundemail.extend(mailsrch.findall(open('text.txt').read())) 

print foundemail 
2

utilizar los paquetes de correo electrónico y buzones para analizar la versión de texto del correo electrónico. Esto lo convertirá en un objeto que permitirá extraer todas las direcciones en el campo 'De'.

También puede hacer muchos otros análisis sobre el mensaje, si necesita procesar otros campos de encabezado, o el cuerpo del mensaje.

Como un ejemplo rápido, el siguiente código (no probado) debe leer todo el mensaje en un buzón de correo de estilo Unix e imprimir todos los encabezados 'de'.

import mailbox 
import email 

mbox = mailbox.PortableUnixMailbox(open(filename, 'rU'), email.message_from_file) 

for msg in mbox: 
    from = msg['From'] 
    print from 
8
import email 
msg = email.message_from_string(str) 

# or 
# f = open(file) 
# msg = email.message_from_file(f) 

msg['from'] 

# and optionally 
from email.utils import parseaddr 
addr = parseaddr(msg['from']) 
1

En términos generales, se puede:

from email.utils import parseaddr 

foundemail = [] 
for line in open("text.txt"): 
    if not line.startswith("From:"): continue 
    n, e = parseaddr(line) 
    foundemail.append(e) 
print foundemail 

Este utiliza la función integrada de pitón parseaddr para analizar la dirección de la de la línea (como se ha demostrado por otras respuestas), sin la sobrecarga necesariamente de analizar todo el mensaje (por ejemplo, mediante el uso de los paquetes de buzón de correo electrónico y más completos). La secuencia de comandos aquí simplemente omite las líneas que no comienzan con "De:". Si los gastos generales le importan depende de qué tan grande sea su entrada y con qué frecuencia realizará esta operación.

Cuestiones relacionadas