日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

字典写入excel_使用Python扫描邮件/填写Excel表格实现办公自动化

發(fā)布時間:2025/6/17 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 字典写入excel_使用Python扫描邮件/填写Excel表格实现办公自动化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題圖:希臘德爾斐(Delphi)神廟遺址。傳說此地原為巨蟒Python盤踞,阿波羅來到此地射殺Python后建立起神廟,成為古希臘的精神圣地。

關(guān)鍵詞:Python, 郵件掃描, yaml配置文件,郵件附件編解碼,Excel自動處理?

一 、前言

? ? ? ?作為一只二級市場資管狗,平時少不了向各相關(guān)方匯報產(chǎn)品數(shù)據(jù),不論領(lǐng)導(dǎo)、風控部門同事、市場人員或者客戶,經(jīng)常會要求我們按照一定頻率披露相關(guān)數(shù)據(jù)(工作年頭一長,感覺需要匯報的人越來越多)。資管產(chǎn)品最準確的數(shù)據(jù)來源就是每個交易日收盤后,經(jīng)過估值清算生成的估值表。但是這些估值服務(wù)供應(yīng)商不同,表格格式差別較大,內(nèi)容也比較繁雜,不論從可讀性和信息保密方面考慮,都不應(yīng)該隨意將估值表提供給對方。比較合適的做法是將對方感興趣的且允許披露的內(nèi)容提取出來,放到一個匯總報告中。

? ? ? ?靠手工完成這類簡單重復(fù)工作比較耗時,且容易讓人感覺枯燥導(dǎo)致出錯,這里我用Python實現(xiàn)了一個工具,能夠自動掃描郵件,下載Excel電子表格附件,抽取所需信息并匯總,再將報告自動發(fā)送到指定郵件帳戶。看似簡單的功能,里面還需要不少技巧,完工后順便寫篇帖子總結(jié)一下經(jīng)驗。

二、系統(tǒng)設(shè)計

? ? ? 圖1. 所示是系統(tǒng)設(shè)計。因為是凈值(Net Asset Value)報告程序,整個程序的入口類叫做NavReporter。頂層模塊下面實現(xiàn)了6個功能模塊,每個功能模塊都以單例(Singleton)模式實現(xiàn)。分別完成配置信息解析(Config),日期文件解析和簡單日期函數(shù)(Calendar),郵箱掃描定位目標郵件并下載附件(EmailScanner),估值表電子表格解析和信息提取(NavParser),匯總報告表格自動填寫(ReportFiller)以及報告發(fā)送(ReportSender)等幾塊功能。分成多模塊實現(xiàn)目標是每個類盡量爭取做到單獨可用,這樣郵件附件下載后,可以根據(jù)不同需求解析不同信息,填寫不同格式報告,發(fā)送給不同接收人。

????????????????????圖1. 系統(tǒng)結(jié)構(gòu)圖

三、功能實現(xiàn)

? ?1. Config模塊

? ? ? ?這個模塊實現(xiàn)比較簡單,主要使用了yaml庫解析yaml格式的配置文件。我原本打算使用json格式文件作為配置文件,但是發(fā)現(xiàn)手動編輯的json文件總是出現(xiàn)莫名的解析錯誤。看到一些經(jīng)驗分享文章也不推薦使用json作為配置文件。json本身設(shè)計目的是作為一種數(shù)據(jù)交換格式,對于注釋信息支持較差,自身語法格式規(guī)范也很嚴格(大概是我手動編輯引發(fā)解析錯誤的原因),不太適合作為配置文件使用。

? ? ? 這里推薦使用yaml庫,文件格式結(jié)構(gòu)與json接近,層次關(guān)系省略了json大量使用的花括號,代之以縮進方式。對于yaml格式配置文件,yaml.load()一個方法就能把文件讀入,并解析成字典格式,非常方便。

? ? ? ?yaml庫解析出來的內(nèi)容,會放到一個字典結(jié)構(gòu)中,因為配置項存在嵌套關(guān)系,返回的字典也會是嵌套結(jié)構(gòu),訪問一個深層次配置項會有 config_info['TopLev']['MidLev']['BotLev']這種情況。針對此我引入屬性字典結(jié)構(gòu),把這種嵌套字典都映射成不同層次的屬性,提高了可讀性,至少也可以省略多個中括號和引號。映射成屬性字典后,訪問一個層次嵌套屬性會變成如下形式:config_info.TopLev.MidLev.BotLev。實現(xiàn)這種功能只需要一個深度優(yōu)先遞歸遍歷字典結(jié)構(gòu)并更新Python的類成員self.__dict__操作。圖2是這部分的關(guān)鍵代碼。

圖2.?遞歸更新self.__dict__成員實現(xiàn)屬性字典

? ?2. Calendar模塊

? ? ? ?日期模塊功能也很簡單。日期模塊功能依賴于初始化時候讀入事先設(shè)置好的日歷文件,包含了交易日信息,通常只有在交易日才會有新的估值信息。日期模塊提供了交易日判斷功能,判斷傳入的日期是否是交易日,如果不是,程序可以直接退出,無需做任何工作。另外,這個模塊還提供了方法獲得指定的交易日。假設(shè)當前是T日,多數(shù)情況下,T日只能獲得T-1日或者T-2日的估值信息,所以模塊提供了get_prev_trading_day()方法獲得前一個交易日信息。

? ? 3. EmailScanner模塊

? ? ? ?郵件掃描先要登錄郵箱,通過配置文件提供的POP3服務(wù)器地址、用戶名和密碼,調(diào)用Python的poplib庫就可以登錄郵件服務(wù)器,獲得郵箱內(nèi)郵件信息。圖3所示登錄代碼片斷。

圖3. 登錄POP3服務(wù)器

? ? ? 登錄成功后,按照由新及舊的順序,逐個掃描郵件。先解析郵件頭信息,然后查看發(fā)件人,如果發(fā)件人不是估值表提供商,則循環(huán)到下一個郵件。匹配發(fā)件人成功的郵件,還要檢查是否存在附件,如果存在附件,則檢查附件名是否是所需要文件,只有以上規(guī)則都匹配,才將附件下載,否則就跳到下一個郵件。提取附件時候,郵件解碼是個容易出錯問題,具體內(nèi)容在下一節(jié)避坑指南中介紹。圖4是郵件掃描流程圖。

圖4.?郵件掃描流程

? ?4.?NavParser解析Excel電子表格

????? ?Python提供了多個能處理Excel電子表格的庫,這里采用操作比較簡單xlrd庫對文件進行讀取解析。操作步驟是:

????????1).?打開工作表文件

????????2).?獲取表單(Sheet)列表名稱或者索引

????????3).?根據(jù)名稱或者索引取得當前表單

????????4). 逐行、逐列遍歷Excel表格單元,查找所需要的內(nèi)容

???????圖5的代碼片斷就是解析文件的過程,掃描電子表格的每個單元,提取出單位凈值、累計收益率等信息,然后返回一個字典結(jié)構(gòu),字典鍵就是產(chǎn)品名,數(shù)據(jù)就是提取到的凈值、規(guī)模、收益率數(shù)據(jù)。提取數(shù)據(jù)的幾個方法這里我都實現(xiàn)成私有方法(函數(shù)名前有2個下劃線)。

圖5. 解析電子表格文件

? ?5.?ReportFiller模塊

??????讀完表后就開始填表。Python對Excel操作的庫實現(xiàn)得比較擰巴,xlrd和xlwt兩個模塊一個只負責讀,一個只負責寫,并且,負責寫的模塊只支持新建寫入文件,不能直接在原有文件上覆蓋寫入,以至于對報告進行每日增量更新比較麻煩。還好有人提供了一個xlutils庫,實際上是在xlrd和xlwt上加了一層管道,把二者結(jié)合起來,但使用起來依然不是那么順手。另外,這里面關(guān)于寫入文件如何保持原有文件格式也需要一個技巧,在下一部分避坑指南中會詳細介紹。最后,這些操作只能支持.xls格式的Excel文件,對于較新的.xlsx格式文件尚不支持。

?????? ReportFiller使用xlrd和xlutils兩個庫結(jié)合實現(xiàn)原Excel表格文件的增量更新。如果要保留原來文件格式,需要在打開工作簿時候,設(shè)置參數(shù)formatting_info=True。xlutils會復(fù)制一個工作簿進行修改工作,修改完畢后將工作簿寫回原來文件。圖6是填寫工作簿的代碼片段。

????? 從圖中代碼示例可見,使用xlrd.open_workbook()方法時候,參數(shù)formatting_info被設(shè)置為True。第54行是xlutils的拷貝操作,其內(nèi)部本質(zhì)還是調(diào)用了xlwt模塊方法,因為xlwt模塊不支持在原有Excel文件上直接修改,這個拷貝操作實際上是創(chuàng)建了一個新的工作簿。循環(huán)體中的操作是先從原工作簿中定位到需要填寫的Excel單元行、列坐標,然后將要寫入的內(nèi)容填寫到新拷貝的工作簿中。注意最后文件保存操作wrt_wb.save()是在with語句之外。這是因為with語句結(jié)束后才會釋放資源(讀寫鎖),關(guān)閉被打開的文件。這樣保存操作才會成功將原報告文件覆蓋,否則可能會引發(fā)無法寫入已打開文件的錯誤。

圖6. 填寫Excel電子表格代碼片段?

??6. ReportSender模塊

??????相比前面掃描郵件、讀寫電子表格,ReportSender模塊功能就簡單多了——創(chuàng)建一個電子郵件,把填寫好的報告作為附件發(fā)送給相關(guān)人員。?創(chuàng)建郵件體使用email.mime類中提供的各種方法,然后使用smtplib模塊,登錄smtp服務(wù)器,將郵件發(fā)送出去即可。圖7是整個郵件發(fā)送的核心代碼。? ?

圖7.?使用Python的smtplib發(fā)送電子郵件

四、技巧和避坑指南

??? ? 最開始編寫這個程序,我的初衷就是實現(xiàn)一個提高工作效率的小工具,預(yù)計差不多半天到一天就可以完成,結(jié)果沒想到中間還踩了幾個坑,花了大概三天左右時間才初步完成,中間也學習到一些技巧,有了一些收獲,這里把有意思的干貨總結(jié)一下。

? ?1. 如何優(yōu)雅的跳出兩層循環(huán)

??????在遍歷掃描Excel表格時候,通常采用先按行再按列的雙層循環(huán)結(jié)構(gòu),找到目標單元后,需要結(jié)束循環(huán),進入下一步操作。如果在最內(nèi)層循環(huán)調(diào)用break,只能中斷最內(nèi)層循環(huán),外面一層還會繼續(xù)。如果設(shè)置一個標識變量,比如loop_flag,中斷內(nèi)層循環(huán)后設(shè)置標識,外層再判斷這個標識決定是否中斷。感覺這樣實現(xiàn)起來實在不夠“優(yōu)雅”或者“Pythonic”,有什么辦法能夠看起來更“舒適”一些呢?

??????我發(fā)現(xiàn)使用Python語言的一個特性可以實現(xiàn),就是循環(huán)結(jié)束后的“else”語句。具體實現(xiàn)如圖8代碼所示。

圖8. Python終結(jié)兩層循環(huán)

? ? ? ?第73行的“else”語句是Python特有的語法,這個else語句是距離它最近的一個循環(huán)如果正常結(jié)束就會被執(zhí)行,如果被break中斷掉,就不會執(zhí)行。這樣邏輯就很清晰了,如果70~72行的循環(huán)體一直循環(huán)到結(jié)束沒有被中斷,則73~74行語句會被執(zhí)行,continue語句會跳過76行的break;如果70~72行的循環(huán)被72的break語句中斷,則73~75行的語句不會被執(zhí)行,76行的break會被執(zhí)行,這樣結(jié)果就是內(nèi)層循環(huán)被中斷,外層的同時也會被中斷。

??????我發(fā)現(xiàn)Python這個循環(huán)體自帶的“else”語句很有意思,第一次接觸時候不太習慣甚至有點排斥,后面遇到一些應(yīng)用場景后,感覺挺好用的,當然也有人批評這個特性讓代碼可讀性變差。

? 2. 郵件編碼解碼

? ? ??我們知道Email內(nèi)容在傳輸時是經(jīng)過編碼的,最知名的就是base64編碼,但其實MIME還定義一種QuotePrintable(簡稱QP)編碼。由于只知道base64編碼,以至于我遇到QP編碼的郵件解碼總是失敗,開始還以為程序問題,后來找了一些經(jīng)驗資料才知道是解碼方式不對。為此,郵件掃描程序?qū)崿F(xiàn)了一個郵件解碼方法,根據(jù)郵件提供的編碼信息判斷是base64還是QP編碼,然后調(diào)用相應(yīng)的解碼器解出郵件原文。郵件解碼方法如圖9所示。

圖9. 處理郵件編碼解碼問題

? 3. Excel保留格式問題

????? 使用xlwt或者xlutils填寫Excel表格,會有一個惱人的問題:如果你的當前工作表拷貝自一個原工作表,在寫入操作后,被寫入單元的格式信息會丟失。解決辦法是:在寫入前先保存格式信息,然后進行寫入單元格操作,再把保留的格式信息賦值給被寫入的單元格。具體操作見圖10。

圖10. 如何對Excel單元進行寫操作并保留原來格式

??4. Excel文件保存問題

????? 使用xlutils時候還遇到一個莫名其妙問題是,如果對Excel文件做了些許改動,比如打開文件手工修改一下格式等,修改完畢關(guān)閉文件,再用xlutils操作Excel寫入后,保存文件會報錯。報錯原因也很無厘頭,提示內(nèi)容往往是:TypeError: save descriptor 'decode' requires a 'bytes' object but received a 'NoneType'。經(jīng)過一番查詢,貌似這是一個庫文件的bug,應(yīng)該是Unicode編碼處理問題,需要Hack一下庫文件,修改后即正常。可以參考網(wǎng)上內(nèi)容https://github.com/python-excel/xlutils/issues/11 ??

? ?具體修正方式是:進入到Python安裝目錄下,找到Lib/site-packages/xlwt/UnicodeUtils.py文件,把里面的upack2()方法修改成圖11的形式。

圖11. 修正xlwt/UnicodeUtils.py中的Bug

五、如何獲得代碼

??????前文洋洋灑灑幾千字介紹了很多內(nèi)容,碼農(nóng)屆有句話叫:“Talk is cheap, show me the code”。光有文字沒有代碼怎么能說明問題,這里告訴你如何獲得參考代碼實現(xiàn)——在github網(wǎng)站下載,地址:https://github.com/swankong/NavReporter 。代碼中已經(jīng)去掉了我工作相關(guān)的敏感信息,包括產(chǎn)品名,公司名,郵箱地址等。

????? 由于這個程序較多依賴于我的工作環(huán)境,我又急于趁熱打鐵寫成這篇文章,導(dǎo)致修改過后的代碼大概不能直接成功運行,后面我會抽空花些時間維護一下,力爭能做成一個例子,可以讓github上下載的程序直接成功運行,這樣就更有參考意義。還要強調(diào)一下,目前版本中的一些功能方法稍加修改就可以拿出來單獨使用,有類似需求的讀者可自由參考借鑒。

六、總結(jié)與展望

?????本文介紹了如何使用Python實現(xiàn)自動郵件掃描和Excel讀寫,以達到辦公自動化提高工作效率的目的目前整個系統(tǒng)還只是完成了初步的功能實現(xiàn),尚且存在一些缺陷。下一步的工作包括但不限于:

??????? 1). 完善程序中英文注釋信息,提高可讀性。

??????? 2). 完成一個去掉敏感信息的應(yīng)用實例,實現(xiàn)github上傳的程序可以直接運行。

??????? 3). 考慮修改程序功能,增加把數(shù)據(jù)寫入關(guān)系數(shù)據(jù)庫的功能,從而實現(xiàn)估值表掃描下載、讀取解析、數(shù)據(jù)入庫一整個流程自動化。

???????最后感謝互聯(lián)網(wǎng)上眾多技術(shù)愛好者發(fā)布的經(jīng)驗分享文章,讓我在程序踩坑時候及時找到了解決方案。

總結(jié)

以上是生活随笔為你收集整理的字典写入excel_使用Python扫描邮件/填写Excel表格实现办公自动化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。