2012-04-20 2 views
10

Python новичок здесь. Я хочу пройти через большой файл mbox, анализируя сообщения электронной почты. Я могу сделать это с:Parsing mbox files in Python

import sys 
import mailbox 

def gen_summary(filename): 
    mbox = mailbox.mbox(filename) 
    for message in mbox: 
     subj = message['subject'] 
     print subj 

if __name__ == "__main__": 
    if len(sys.argv) != 2: 
     print 'Usage: python genarchivesum.py mbox' 
     sys.exit(1) 

    gen_summary(sys.argv[1]) 

Но мне нужно больше контроля. Мне нужно получить байт позиции начала данного письма в файле mbox, и мне также нужно получить количество байтов в сообщении (как представлено на диске). И затем, в будущем, вместо повторения с начала файла mbox, мне нужно иметь возможность искать данное сообщение и просто анализировать его (отсюда одна из потребностей получения позиции байта на диске). Это большие файлы mbox и эффективность.

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

+0

Я никогда не использовал 'mailbox', но я просто прочитал' help (mailbox.mbox) '. Не можете ли вы использовать метод '.iterkeys()' для получения итератора значений ключа, а затем использовать значения ключей для поиска сообщений? Почему вы хотите использовать байтовый индекс в качестве ключа для поиска сообщения вместо использования модуля ... пытались ли вы использовать модуль для индексирования сообщений по ключу? Если вы пробовали это, и это слишком медленно или что-то еще, скажите об этом. – steveha

+0

Скажем, у меня есть mbox из 10 000 писем. Я не хочу читать/разбирать/повторять более 9998 из них, когда мне просто нужно последнее электронное письмо. Я хотел бы найти эту точку в файле mbox и просто прочитать это сообщение. –

+0

@MarkFletcher DId вы получаете эту работу? Если это так, пожалуйста, дайте мне знать. – kingmakerking

ответ

8

Я не тестировал это, но что-то подобное может сработать для вас. Просто откройте файл (в двоичном режиме, чтобы ваш счетчик байтов был правильным) и просмотрите его, найдя сообщения.

def is_mail_start(line): 
    return line.startswith("From ") 

def build_index(fname): 
    with open(fname, "rb") as f: 
     i = 0 
     b = 0 
     # find start of first message 
     for line in f: 
      b += len(line) 
      if is_mail_start(line): 
       break 
     # find start of each message, and yield up (index, length) of previous message 
     for line in f: 
      if is_mail_start(line): 
       yield (i, b) 
       i += b 
       b = 0 
      b += len(line) 
     yield (i, b) # yield up (index, length) of last message 

# get index as a list 
mbox_index = list(build_index(fname)) 

После того как вы индекс, вы можете использовать метод .seek() на объект файла, чтобы искать там, и .read(length) на объект файла для чтения только один сообщение. Я не уверен, как вы будете использовать модуль mailbox со строкой; Я думаю, что он предназначен для работы с почтовым ящиком на месте. Возможно, есть другой модуль для разбора почты, который вы можете использовать.

+1

Хорошо, спасибо. Думаю, я буду использовать что-то вроде этой стратегии. Кстати, начало электронной почты в mbox начинается с «From» (без :). Я могу использовать email.Parser для анализа электронной почты. Благодарю. –

+0

Я отредактирую ответ, чтобы вынуть «:». Я * сказал, что я не тестировал его ... Удачи в вашем проекте и отличные выходные! – steveha

+0

Для чего это стоит, для будущих пользователей, это на самом деле оба, по крайней мере, на последней версии OSX. def is_mail_start (строка): \t return line.startswith («From»), а не line.startswith («From:») – adammenges