對于編程來說,我期望的是并不僅僅用于make money,而是出于生活,融于生活。

最近炒股,每天都會有一封郵件發(fā)到我的QQ郵箱,里面有今天賬戶的結(jié)算信息,感覺這個(gè)挺有意義的,可以記錄每天的交易情況和相關(guān)費(fèi)用,但是我又不想每天去下載這個(gè)附件。于是乎花了一個(gè)晚上研究了一下python的poplib庫,完成了一個(gè)拉取QQ郵箱附件的程序。

二、實(shí)現(xiàn) 2.1 poplib是什么?

poplib是一個(gè)python的一個(gè)模塊,用于專門的處理郵箱的郵件,是基于pop3的協(xié)議。 使用的話用import poplib就可以了。 2.2 代碼說明

想要解析郵件分為幾個(gè)步驟:

第一步:創(chuàng)建鏈接

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庫創(chuàng)建一個(gè)SSL的鏈接,然后分別設(shè)置這個(gè)connect的幾個(gè)參數(shù),分別是: – debugmode:0為關(guān)閉,1為開啟。如果開啟的話,會顯示交互時(shí)的日志。 – username :郵箱的賬號 – password :郵箱的密碼 – host : 對應(yīng)的郵箱的pop3協(xié)議的host,qq郵箱是pop.qq.com

注:這里有個(gè)坑爹的東西,如果直接用qq密碼用作password的話,會提示這個(gè)報(bào)錯(cuò) poplib.error_proto: -ERR Please using authorized code to login.

跟著這個(gè)鏈接進(jìn)去看,是因?yàn)閝q出于安全的考慮,使用pop協(xié)議的時(shí)候,需要使用一個(gè)16位的密保來進(jìn)行操作。按照鏈接里面的提示設(shè)置好了密碼,再填入就可以使用了。

第二步:獲取郵件

幾個(gè)主要的API:

pop_conn.stat() pop_conn.list() pop_conn.retr()123

stat()用于獲取郵件的狀態(tài),例如:有46封郵件

Messages: 46. Size: 3819672

list()用于獲取郵件的列表狀態(tài):

(‘ OK’, [‘1 196394’, ‘2 35328’, ‘3 195761’, ‘4 19024’, ‘5 63952’, ‘6 196662’, ‘7 45720’, ‘8 197030’, ‘9 15565’, ‘10 36985’, ‘11 2550’, ‘12 31237’, ‘13 26712’, ‘14 18984’, ‘15 15990’, ‘16 12196’, ‘17 21966’, ‘18 194291’, ‘19 194885’, ‘20 126483’, ‘21 14534’, ‘22 29710’, ‘23 196006’, ‘24 13974’, ‘25 34424’, ‘26 195320’, ‘27 202168’, ‘28 24900’, ‘29 22061’, ‘30 7843’, ‘31 53405’, ‘32 7958’, ‘33 7913’, ‘34 200682’, ‘35 5349’, ‘36 15979’, ‘37 34286’, ‘38 53619’, ‘39 198150’, ‘40 25144’, ‘41 7366’, ‘42 196818’, ‘43 214880’, ‘44 196847’, ‘45 18007’, ‘46 194614’], 461)

pop_conn.retr()則是用于獲取每封郵件的狀態(tài)了

第三步:解析郵件

分為兩步:

1、先把pop_conn.retr()獲得的一封郵件格式化一下,把其中的分割符化成”n”(具體這一步的意義我沒有深究,應(yīng)該是方便email模塊去解析)

messages = ["n".join(mssg[1]) for mssg in messages] 12

注意每個(gè)郵件mssg里面只有mssg[1]是內(nèi)容。

2、然后對郵件進(jìn)行解析轉(zhuǎn)化成Message對象

messages = [Parser().parsestr(mssg) for mssg in messages] 12

3、然后就可以獲取到對應(yīng)的郵件內(nèi)容了

直接獲取了 主題:msg.get(\\\’subject\\\’) 時(shí)間:msg.get(\\\’Date\\\’) 發(fā)件人:email.utils.parseaddr(msg.get(\\\’from\\\’))[1] 收件人:email.utils.parseaddr(msg.get(\\\’to\\\’))[1]12345

不過這些我都不需要,我只需要里面的附件內(nèi)容。

4、保存附件

for part in msg.walk(): fileName = part.get_filename() # 保存附件 if fileName: 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,如果有附件就存下來,這里需要注意的是需要對文件的名字進(jìn)行解碼。

然后找個(gè)目錄存下來吧。

有個(gè)問題,不知道為什么只能取到最近的一個(gè)月的郵件,有點(diǎn)奇怪,不知道是不是QQ郵箱的限制了。

三、源碼

#!/usr/bin/python #-*- encoding: utf-8 -*- # @auth atany 347702498@qq.com # blog : http://blog.csdn.net/yang8456211 import poplib from email.parser import Parser from email.header import decode_header from email.utils import parseaddr import email import os import sys reload(sys) sys.setdefaultencoding(\\\’utf-8\\\’) # 默認(rèn)的編碼是ASCII.. class MailManager: # 測試的郵件數(shù)量 0為所有 testLimitMailCount = 0 def __init__(self, host, username, password, savePath, debugMode = 0): self.host = host self.user = username self.pass_ = password self.debugMode = debugMode self.savePath = savePath def _download_mail(self): print "…n============ Begin to DownLoad ============" 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\\\’, [\\\’1 12515\\\’, \\\’2 196394\\\’, \\\’3 35328\\\’, \\\’4 195761\\\’, \\\’5 19024\\\’], 471) print pop_conn.list() messages = [] for i in range(1, len(pop_conn.list()[1]) 1): #print pop_conn.retr(i) messages.append(pop_conn.retr(i)) # 太多了不好測試,限制一下 if 0 != self.testLimitMailCount and i >= self.testLimitMailCount: break # mssg[1]為內(nèi)容正文,加個(gè)回車換行把逗號分隔符,鏈接成一個(gè)完整字符串 messages = ["n".join(mssg[1]) for mssg in messages] # 轉(zhuǎn)化為郵件實(shí)例的Message對象 messages = [Parser().parsestr(mssg) for mssg in messages] #print messages for i in range(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"]) print mailName # mailName = "Mail[%d].log" % (index) # print mailName # print os.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" not in From: return for part in msg.walk(): fileName = part.get_filename() # contentType = part.get_content_type() # mycode=part.get_content_charset() # 保存附件 if fileName: 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() def decode_str(self, s): # # 下面的三行代碼只是為了解碼 # h = email.Header.Header(subject) # # dh:內(nèi)容 編碼[(\\\’xcdxf8xc9xcfxb9xbaxc6xb1xcfxb5xcdxb3-xd3xc3xbbxa7xd6xa7xb8xb6xcdxa8xd6xaa\\\’, \\\’gbk\\\’)] # dh = email.Header.decode_header(h) # if None != dh[0][1] and None != dh[0][0]: # subject = unicode(dh[0][0], dh[0][1]).encode(\\\’utf8\\\’) value, charset = decode_header(s)[0] if charset: value = value.decode(charset) return value def _display_email(self, msg): pass def _display_info(self): print "============ DisplayInfo Begin ============" print "username : " , self.user print "password : " , self.pass_ print "host : " , self.host print "============ DisplayInfo End ============" if __name__ == \\\’__main__\\\’: host = \\\’pop.qq.com\\\’ username = \\\’\\\’ # QQ郵箱這里改成16位的密保了,這里有個(gè)問題,一旦修改了密碼或者獨(dú)立密碼,需要重新去生成一下密保 # 這里輸入自己的密保就可以了 password = \\\’\\\’ # 不傳debugMode 就是默認(rèn)為0,不顯示服務(wù)器日志 debugMode = 0 #保存附件的位置 savePath = "/Users/yangguang/Documents/stock/" mailManager = MailManager(host, username, password, savePath, debugMode) mailManager._display_info() mailManager._download_mail()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 四、后續(xù)問題

1)可以是用定時(shí)任務(wù)做個(gè)每天定時(shí)拉取應(yīng)該不錯(cuò)。

2)關(guān)于文章中的一些轉(zhuǎn)碼問題還是頭疼了一小會,沒想到系統(tǒng)的defaultencoding是ASCII.. 所以要在文件頭加上

import sys reload(sys) sys.setdefaultencoding(\\\’utf-8\\\’) # 默認(rèn)的編碼是ASCII..123

關(guān)于解碼:

使用這個(gè)解碼方法解出dh也是可以的,dh[0][0]是內(nèi)容,dh [0][1]是當(dāng)前的編碼。

3)關(guān)于各個(gè)郵箱的pop協(xié)議的host可以自行百度

例如:

pop.163.com是網(wǎng)易的

pop.live.com是微軟的

 

 

 

更多關(guān)于云服務(wù)器,域名注冊,虛擬主機(jī)的問題,請?jiān)L問西部數(shù)碼官網(wǎng):bingfeng168.cn

贊(0)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享網(wǎng)絡(luò)內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-62778877-8306;郵箱:fanjiao@west.cn。本站原創(chuàng)內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明出處:西部數(shù)碼知識庫 » python想要保存QQ郵箱富途的附件

登錄

找回密碼

注冊