Разбор адресов "From" из текста письма - PullRequest
12 голосов
/ 15 февраля 2009

Я пытаюсь извлечь адреса электронной почты из текстовых расшифровок электронных писем. Я собрал немного кода, чтобы найти сами адреса, но я не знаю, как заставить их различать; сейчас он просто выплевывает все адреса электронной почты в файле. Я хотел бы сделать так, чтобы он только выплевывал адреса, которым предшествует «От:» и несколько подстановочных знаков, и заканчивающийся «>» (потому что электронные письма настроены как От [имя] <[электронная почта]> ).

Вот код сейчас:

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

mailsrch = re.compile(r'[\w\-][\w\-\.]+@[\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

Ответы [ 8 ]

35 голосов
/ 15 февраля 2009

Попробуйте это:

>>> from email.utils import parseaddr

>>> parseaddr('From: vg@m.com')
('', 'vg@m.com')

>>> parseaddr('From: Van Gale <vg@m.com>')
('Van Gale', 'vg@m.com')

>>> parseaddr('    From: Van Gale <vg@m.com>   ')
('Van Gale', 'vg@m.com')

>>> parseaddr('blah abdf    From: Van Gale <vg@m.com>   and this')
('Van Gale', 'vg@m.com')

К сожалению, он находит только первое электронное письмо в каждой строке, потому что ожидает строки заголовка, но, может, это нормально?

9 голосов
/ 15 февраля 2009
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'])
3 голосов
/ 15 февраля 2009

Если ваша цель на самом деле извлечь адреса электронной почты из текста, вы должны использовать библиотеку, созданную для этой цели. Регулярные выражения плохо подходят для сопоставления произвольных адресов электронной почты.

Но если вы делаете это как упражнение для лучшего понимания регулярных выражений, я бы воспользовался подходом расширения используемого вами выражения, чтобы включить дополнительный текст, который вы хотите сопоставить. Итак, сначала позвольте мне объяснить, что делает это регулярное выражение:

[\w\-][\w\-\.]+@[\w\-][\w\-\.]+[a-zA-Z]{1,4}
  • [\w\-] соответствует любому «словесному» символу (букве, цифре или подчеркиванию), или дефису
  • [\w\-\.]+ совпадений (любой символ слова или дефис или точка) один или несколько раз
  • @ соответствует буквальному '@'
  • [\w\-] соответствует любому символу слова или дефис
  • [\w\-\.]+ совпадений (любой символ слова или дефис или точка) один или несколько раз
  • [a-zA-Z]{1,4} соответствует 1, 2, 3 или 4 строчным или прописным буквам

Таким образом, это соответствует последовательности «слова», которая может содержать дефисы или точки, но не начинается с точки, за которой следует знак @, за которым следует другое «слово» (в том же смысле, что и раньше), которое заканчивается с буквой.

Теперь, чтобы изменить это для ваших целей, давайте добавим части регулярного выражения, чтобы они соответствовали «От», имени и угловым скобкам:

From: [\w\s]+?<([\w\-][\w\-\.]+@[\w\-][\w\-\.]+[a-zA-Z]{1,4})>
  • From: соответствует буквальному тексту "From:"
  • [\w\s]+? соответствует одному или нескольким последовательным символам слова или пробелам. Знак вопроса делает сопоставление нежадным, поэтому оно будет соответствовать как можно меньшему количеству символов, в то же время позволяя сопоставлять все регулярное выражение (в этом случае, вероятно, это не является необходимым, но оно делает сопоставление более эффективным, поскольку приходит сразу после этого не является символом слова или пробела).
  • < соответствует буквальному знаку «меньше» (открывающая угловая скобка)
  • То же регулярное выражение, которое вы имели раньше, теперь заключено в скобки. Это делает группу захвата , поэтому вы можете позвонить m.group(1), чтобы получить текст, соответствующий этой части регулярного выражения.
  • > соответствует буквальному значению больше, чем

Поскольку регулярное выражение теперь использует группы захвата, ваш код также должен немного измениться:

import re
foundemail = []

mailsrch = re.compile(r'From: [\w\s]+?<([\w\-][\w\-\.]+@[\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

Код [m.group(1) for m in mailsrch.finditer(line)] создает список из первой группы захвата (помните, это была часть в скобках) из каждого совпадения, найденного регулярным выражением.

2 голосов
/ 15 февраля 2009

Используйте пакеты электронной почты и почтовых ящиков для анализа текстовой версии электронной почты. Это преобразует его в объект, который позволит извлечь все адреса в поле «От».

Вы также можете выполнить много других анализов сообщения, если вам нужно обработать другие поля заголовка или текст сообщения.

В качестве быстрого примера следующий (непроверенный) код должен прочитать все сообщения в почтовом ящике в стиле Unix и распечатать все заголовки «from».

import mailbox
import email

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

for msg in mbox:
   from = msg['From']
   print from
2 голосов
/ 15 февраля 2009
mailsrch = re.compile(r'[\w\-][\w\-\.]+@[\w\-][\w\-\.]+[a-zA-Z]{1,4}')

Разбивка выражения:

[\w-]: любой символ слова (буквенно-цифровой, плюс подчеркивание) или тире

[\w-.]+: любой символ слова, тире или точка / точка, один или несколько раз

@: буквальный символ @

[\w-][\w-.]+: любое слово char или тире, за которым следует любое слово char, тире или точка один или несколько раз.

[a-zA-Z]{1,4}: любой буквенный символ 1-4 раза.

Чтобы сделать это соответствие только строкам, начинающимся с From: и заключенным в символы <и>:

import re

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

print foundemail
1 голос
/ 15 февраля 2009

Грубо говоря, вы можете:

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

При этом используется встроенная функция pyse parseaddr для анализа адреса вне строки (как показано в других ответах), без необходимости обработки всего сообщения (например, с использованием более полнофункциональных пакетов электронной почты и почтовых ящиков ). Сценарий здесь просто пропускает любые строки, которые не начинаются с «From:». То, насколько важны для вас накладные расходы, зависит от того, насколько велик ваш вклад и как часто вы будете выполнять эту операцию.

0 голосов
/ 15 февраля 2009

"[материал] @ [материал] [вещи1-4 буквы]" примерно так, но если вы хотите, вы можете декодировать регулярное выражение с помощью трюка, о котором я только что узнал, здесь . Выполните compile () в интерактивном сеансе Python следующим образом:

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

Будет распечатано следующее:

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)

Который, если вы можете как-то привыкнуть, показывает вам, как именно работает RE.

0 голосов
/ 15 февраля 2009

, если вы можете быть уверены, что строки, содержащие эти адреса электронной почты, начинаются с пробела, за которым следует «От:», вы можете просто сделать это:

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

затем позже - или добавив их в список - вы можете уточнить элементы адресных линий, чтобы выдавать именно то, что вы хотите

...