2012-04-20 21 views
10

Python newbie here。私は電子メールメッセージを解析して、大きなmboxファイルを歩きたい。私はそれを行うことができます:Pythonでmboxファイルを解析する

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

私は1万の電子メールのmboxを持っていると言います。最後の電子メールがほしいと思ったときに、9,998以上の/ parse/iterateを読み込む必要はありません。私はmboxファイルのその時点まで探して、そのメッセージを読むだけです。 –

+0

@MarkFletcherあなたはこれを稼働させましたか?もしそうなら、私に知らせてください。 – 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

よろしくお願いいたします。私はこの戦略のようなものを使うつもりだと思う。 btw、mbox内のメールの開始は 'From'(:)なしで始まります。 email.Parserを使用して電子メールを解析できます。ありがとう。 –

+0

答えを編集して ':'を取り出します。私は*私はそれをテストしていないと言った...あなたのプロジェクトで幸運、素晴らしい週末を持っている! – steveha

+0

将来のユーザーにとっては、少なくとも最新バージョンのOSXでは、実際には両方の価値があります。 def is_mail_start(line): \t return line.startswith( "From")ではなく、line.startswith( "From:") – adammenges