{{ v.name }}
{{ v.cls }}类
{{ v.price }} ¥{{ v.price }}
对于编程来说,我期望的是并不仅仅用于makemoney,而是出于生活,融于生活。最近炒股,每天都会有一封邮件发到我的qq邮箱,里面有今天账户的结算信息,感觉这个挺有意义的,可以记录每天的交易情况和相关费用,但是我又不想每天去下载这个附件。于是乎花了一个晚上研究了一下python的poplib库,完成了一个拉取qq邮箱附件的程序。
poplib是一个python的一个模块,用于专门的处理邮箱的邮件,是基于pop3的协议。使用的话用importpoplib就可以了。2.2代码说明
想要解析邮件分为几个步骤:
pop_conn=poplib.pop3_ssl(self.host)pop_conn.set_debuglevel(self.debugmode)pop_conn.user(self.user)pop_conn.pass_(self.pass_)1234
使用poplib库创建一个ssl的链接,然后分别设置这个connect的几个参数,分别是:-debugmode:0为关闭,1为开启。如果开启的话,会显示交互时的日志。-username:邮箱的账号-password:邮箱的密码-host:对应的邮箱的pop3协议的host,qq邮箱是pop.qq.com
注:这里有个坑爹的东西,如果直接用qq密码用作password的话,会提示这个报错poplib.error_proto:-errpleaseusingauthorizedcodetologin.
跟着这个链接进去看,是因为qq出于安全的考虑,使用pop协议的时候,需要使用一个16位的密保来进行操作。按照链接里面的提示设置好了密码,再填入就可以使用了。
几个主要的api:
pop_conn.stat()pop_conn.list()pop_conn.retr()123
stat()用于获取邮件的状态,例如:有46封邮件messages:46.size:3819672
list()用于获取邮件的列表状态:(‘+ok’,[‘1196394’,‘235328’,‘3195761’,‘419024’,‘563952’,‘6196662’,‘745720’,‘8197030’,‘915565’,‘1036985’,‘112550’,‘1231237’,‘1326712’,‘1418984’,‘1515990’,‘1612196’,‘1721966’,‘18194291’,‘19194885’,‘20126483’,‘2114534’,‘2229710’,‘23196006’,‘2413974’,‘2534424’,‘26195320’,‘27202168’,‘2824900’,‘2922061’,‘307843’,‘3153405’,‘327958’,‘337913’,‘34200682’,‘355349’,‘3615979’,‘3734286’,‘3853619’,‘39198150’,‘4025144’,‘417366’,‘42196818’,‘43214880’,‘44196847’,‘4518007’,‘46194614’],461)
pop_conn.retr()则是用于获取每封邮件的状态了
分为两步:1、先把pop_conn.retr()获得的一封邮件格式化一下,把其中的分割符化成”n”(具体这一步的意义我没有深究,应该是方便email模块去解析)
messages=["n".join(mssg[1])formssginmessages]12
注意每个邮件mssg里面只有mssg[1]是内容。
2、然后对邮件进行解析转化成message对象
messages=[parser().parsestr(mssg)formssginmessages]12
3、然后就可以获取到对应的邮件内容了
直接获取了主题:msg.get('subject')时间:msg.get('date')发件人:email.utils.parseaddr(msg.get('from'))[1]收件人:email.utils.parseaddr(msg.get('to'))[1]12345
不过这些我都不需要,我只需要里面的附件内容。
4、保存附件
forpartinmsg.walk():filename=part.get_filename()#保存附件iffilename:fname=self.decode_str(filename)fex=open("%s%s"%(self.savepath,fname),'wb')data=part.get_payload(decode=true)fex.write(data)fex.close()12345678910
遍历一下msg,如果有附件就存下来,这里需要注意的是需要对文件的名字进行解码。然后找个目录存下来吧。
有个问题,不知道为什么只能取到最近的一个月的邮件,有点奇怪,不知道是不是qq邮箱的限制了。
#!/usr/bin/python#-*-encoding:utf-8-*-#@authatany347702498@qq.com#blog:http://blog.csdn.net/yang8456211importpoplibfromemail.parserimportparserfromemail.headerimportdecode_headerfromemail.utilsimportparseaddrimportemailimportosimportsysreload(sys)sys.setdefaultencoding('utf-8')#默认的编码是ascii..classmailmanager:#测试的邮件数量0为所有testlimitmailcount=0def__init__(self,host,username,password,savepath,debugmode=0):self.host=hostself.user=usernameself.pass_=passwordself.debugmode=debugmodeself.savepath=savepathdef_download_mail(self):print"...n============begintodownload============"pop_conn=poplib.pop3_ssl(self.host)pop_conn.set_debuglevel(self.debugmode)pop_conn.user(self.user)pop_conn.pass_(self.pass_)print('messages:%s.size:%s'%pop_conn.stat())##格式('+ok',['112515','2196394','335328','4195761','519024'],471)printpop_conn.list()messages=[]foriinrange(1,len(pop_conn.list()[1])+1):#printpop_conn.retr(i)messages.append(pop_conn.retr(i))#太多了不好测试,限制一下if0!=self.testlimitmailcountandi>=self.testlimitmailcount:break#mssg[1]为内容正文,加个回车换行把逗号分隔符,链接成一个完整字符串messages=["n".join(mssg[1])formssginmessages]#转化为邮件实例的message对象messages=[parser().parsestr(mssg)formssginmessages]#printmessagesforiinrange(0,len(messages)):msg=messages[i]self._save_email(msg,i)def_save_email(self,msg,index):#其他的可能用到的属性mailname="mail[%d]-%s.log-%s"%(index,self.decode_str(msg.get('subject')),msg["date"])printmailname#mailname="mail[%d].log"%(index)#printmailname#printos.getcwd()#file_=open(mailname,'w')#print>>file_,"date:",msg["date"]#print>>file_,"from:",email.utils.parseaddr(msg.get('from'))[1]#print>>file_,"to:",email.utils.parseaddr(msg.get('to'))[1]#print>>file_,"subject:",self.decode_str(msg.get('subject'))#主题=?gbk?b?zfjjz7m6xrhptc2zldpdu6fwp7i2zajwqg==?=#print>>file_,"data:"#我只想要富途的附件from=email.utils.parseaddr(msg.get('from'))[1]if"@futu5.com"notinfrom:returnforpartinmsg.walk():filename=part.get_filename()#contenttype=part.get_content_type()#mycode=part.get_content_charset()#保存附件iffilename:fname=self.decode_str(filename)fex=open("%s%s"%(self.savepath,fname),'wb')data=part.get_payload(decode=true)fex.write(data)fex.close()#file_.close()defdecode_str(self,s):##下面的三行代码只是为了解码#h=email.header.header(subject)##dh:内容+编码[('xcdxf8xc9xcfxb9xbaxc6xb1xcfxb5xcdxb3-xd3xc3xbbxa7xd6xa7xb8xb6xcdxa8xd6xaa','gbk')]#dh=email.header.decode_header(h)#ifnone!=dh[0][1]andnone!=dh[0][0]:#subject=unicode(dh[0][0],dh[0][1]).encode('utf8')value,charset=decode_header(s)[0]ifcharset:value=value.decode(charset)returnvaluedef_display_email(self,msg):passdef_display_info(self):print"============displayinfobegin============"print"username:",self.userprint"password:",self.pass_print"host:",self.hostprint"============displayinfoend============"if__name__=='__main__':host='pop.qq.com'username=''#qq邮箱这里改成16位的密保了,这里有个问题,一旦修改了密码或者独立密码,需要重新去生成一下密保#这里输入自己的密保就可以了password=''#不传debugmode就是默认为0,不显示服务器日志debugmode=0#保存附件的位置savepath="/users/yangguang/documents/stock/"mailmanager=mailmanager(host,username,password,savepath,debugmode)mailmanager._display_info()mailmanager._download_mail()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134四、后续问题
1)可以是用定时任务做个每天定时拉取应该不错。2)关于文章中的一些转码问题还是头疼了一小会,没想到系统的defaultencoding是ascii..所以要在文件头加上
importsysreload(sys)sys.setdefaultencoding('utf-8')#默认的编码是ascii..123
关于解码:使用这个解码方法解出dh也是可以的,dh[0][0]是内容,dh[0][1]是当前的编码。
3)关于各个邮箱的pop协议的host可以自行百度例如:pop.163.com是网易的
pop.live.com是微软的