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开源这么优秀的代码.