0%

python3.7下使用第三方email扩展库flanker多进程批量解析eml格式文件信息到csv

python3.7下使用第三方email扩展库flanker多进程批量解析eml格式文件信息到csv

email解析库flanker

由mailgun开源的Flanker - email address and MIME parsing for Python是一个解析高效、容错率不错的python第三方扩展库。python 3也可以正常使用,安装通过pip install flanker即可。该库包含了邮件地址解析和邮件mime格式解析。

使用pool.map_async实现多进程并行任务

为提高处理效率,使用了python里面的多进程pool,需要注意的是相关代码需在main里执行.

#多进程处理代码
pool = Pool()
proxy_func = partial(解析eml的函数, 参数1)
pool.map_async(proxy_func, 参数2)
pool.close()
pool.join()

这里为了添加多个参数,使用了一个代理函数proxy_func.其中参数使用Manager来共享:

#存储配置到manager.dict中
mgr = Manager()
config_dict = mgr.dict()

解析eml格式文件

eml是特定格式的文本文件,内容为MIME格式,使用flanker来解析eml会非常简单,首先读取文件:

with open(emlfile, 'rb') as fhdl:
    raw_email = fhdl.read()
    eml = mime.from_string(raw_email)

这样就得到一个解析后的eml对象.

获取发信人地址及昵称

从字段From中获取,地址为address,昵称为display_name:

eml_header_from = eml.headers.get('From')
eml_from = address.parse(eml_header_from)
from_address = eml_from.address
from_display_name = eml_from.display_name                          

解析附件列表

一封email邮件可以有多个part,每个part可以有自己的格式,使用flanker可以快速简洁的解析出附件信息:

 eml_attachs = ';'.join(x.detected_file_name for x in eml.parts if x.detected_file_name)        

邮件正文

邮件正文要区别对待,属性为singlepart的,直接使用body属性即可取得.为multipart属性的,则需要递归处理.

if eml.content_type.is_singlepart(): 
    eml_body = eml.body       
else:
    for part in eml.parts:
        if part.content_type.is_multipart():
            eml_body, charset = 递归函数(part)
        else:
            if part.content_type.main == 'text':
                eml_body += part.body                        

收件人信息

其实就是解析eml文件里的To字段,多个地址的话,使用分号拼接:

eml_to = eml.headers.get('To')
eml_to_addr = address.parse_list(eml_to)
# 多个地址以;拼接显示  
if not type(eml_to_addr) == str:       
    to_display_name = ';'.join(x.display_name for x in eml_to_addr if x.display_name)
    to_address = ';'.join(x.address for x in eml_to_addr if x.address)

邮件主题

使用subject获取即可.

使用pandas转储信息到csv文件

以上获取的信息存储到一个字典dict_emls里面,然后使用pandas转换一下,存储到csv文件,如果想存为excel文件,则需要对一些字段做特殊处理,较为麻烦:

df = pd.DataFrame.from_dict({ key:pd.Series(value) for key, value in dict_emls.items() })
df.columns = [设置一下列名]
df.to_csv(outfile, index=False, encoding='utf_8_sig')

结束

在使用了python自带的email库及github上诸多第三方email解析库之后,最终选择了flanker这个优秀的邮件格式解析库,非常感谢mailgun开源这么优秀的代码.