我設法撰寫了一段代碼(由網路上的多個來源組成,并適應我的需要),它應該執行以下操作:
- 讀取一個excel檔案
- 從 A 列搜索來自特定檔案夾的郵件主題中每個單元格的值
- 如果匹配(單元格值等于主題的前 9 個字符),則將帶有單元格值的附件(每封郵件只有一個附件,不多也不少)保存在“輸出”檔案夾中。
- 如果不匹配,則轉到下一封郵件,分別轉到下一個單元格值。
- 最后,顯示運行時間(不是很重要,僅供我了解)
該代碼實際上有效(使用只有 9 封電子郵件的電子郵件檔案夾進行測驗)。我的問題是運行時間。
該腳本的實際范圍是在包含 32700 封電子郵件的檔案夾中查找 2539 個值并保存附件。
我已經完成了 2 次運行,如下所示:
- 32700 封電子郵件中的 2539 個值(約 1 小時后停止)
- 32700 封電子郵件中的 10 個值(約 40 分鐘后停止;此時腳本處理了 4 個值)
我想知道/學習,是否有辦法使腳本更快,或者它是否因為寫得不好等而變慢。
下面是我的代碼:
from pathlib import Path
import win32com.client
import os
from datetime import datetime
import time
import openpyxl
#name of the folder created for output
output_dir = Path.cwd() / "Orders"
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
folder = outlook.Folders.Item("Shared Mailbox Name")
inbox = folder.Folders.Item("Inbox")
messages = inbox.Items
wb = openpyxl.load_workbook(r"C:\Users\TEST\Path-to-excel\FolderName\ExcelName.xlsx")
sheet = wb['Sheet1']
names=sheet['A']
for cellObj in names:
ordno = str(cellObj.value)
print(ordno)
for message in messages:
subject = message.Subject
body = message.body
attachments = message.Attachments
if str(subject)[:9] == ordno:
output_dir.mkdir(parents=True, exist_ok=True)
for attachment in attachments:
attachment.SaveAsFile(output_dir / str(attachment))
else:
pass
start = time()
print(f'Time taken to run: {time() - start} seconds')
我需要提一下,我是 Python 的新手,因此歡迎社區提供任何幫助,尤其是在澄清我做錯了什么以及為什么做錯之后。
我也讀過一些類似的問題,但沒有任何幫助,或者至少我不知道如何采用這些方法。
謝謝!
uj5u.com熱心網友回復:
在我看來,您的程式的主要問題是當您只需要遍歷郵件并檢查它們的主題是否在值串列中時,您有兩個嵌套回圈(一個在值上,一個在郵件上)。
首先,您需要使用以下內容構建價值串列:
ordno_values = [str(cellObj.value) for cellObj in names]
然后,在您的郵件回圈中,您只需要將條件調整為:
if str(subject)[:9] in ordno_values:
uj5u.com熱心網友回復:
您的用例過于具體,任何人都無法重新創建,并且僅提供通用性能提示,但您的主要問題是“O x N”和同步處理的組合:目前您正在處理一個值,一次處理一條訊息,其中包括用于獲取電子郵件的磁盤 IO。
您當然可以通過從作業簿創建單個值串列來改進事情。然后,您可以將此串列與處理池一起使用(請參閱 Python 檔案)來一次閱讀多封電子郵件。
但是如果您可以使用主題來查詢郵件服務器,情況可能會更好。
如果您有后續問題,請將它們分解為任務的特定部分。
uj5u.com熱心網友回復:
首先,而不是遍歷檔案夾中的所有專案:
for message in messages:
subject = message.Subject
然后檢查一個主題是從指定的字串開始還是包含這樣的字串:
if str(subject)[:9] == ordno:
相反,您需要使用Find
/FindNext
或 Restrict methods of the
Items` 類,您可以在其中獲取與您的搜索條件相對應的專案集合。在以下文章中閱讀有關這些方法的更多資訊:
- 如何:使用 Find 和 FindNext 方法從檔案夾中檢索 Outlook 郵件專案(C#、VB.NET)
- 如何:使用限制方法從檔案夾中檢索 Outlook 郵件專案
例如,您可以對集合使用以下限制(取自 VBA 示例):
criteria = "@SQL=" & Chr(34) & "urn:schemas:httpmail:subject" & Chr(34) & " ci_phrasematch 'question'"
有關詳細資訊,請參閱使用字串比較過濾專案。
此外,您可能會發現該類的AdvancedSearch
方法Application
很有幫助。AdvancedSearch
在 Outlook 中使用該方法的主要好處是:
- 搜索在另一個執行緒中執行。您不需要手動運行另一個執行緒,因為該
AdvancedSearch
方法會在后臺自動運行它。 - 可以在任何位置(即超出某個檔案夾的范圍)搜索任何專案型別:郵件、約會、日歷、便箋等。和
Restrict
/方法可以應用于特定的集合(參見 Outlook 中類的Find
屬性)。FindNext
Items
Items
Folder
- 完全支持 DASL 查詢(自定義屬性也可用于搜索)。為了提高搜索性能,如果為商店啟用了即時搜索,則可以使用即時搜索關鍵字(請參閱類的
IsInstantSearchEnabled
屬性Store
)。 Stop
您可以使用類的方法隨時停止搜索程序Search
。
有關詳細資訊,請參閱Outlook 中的高級搜索以編程方式:C#、VB.NET。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/491145.html