一、需求
郵件發(fā)送功能,作為一個(gè)【通知】或者說(shuō)【知曉】的方式,在實(shí)際應(yīng)用中會(huì)經(jīng)常使用的,試想一個(gè)場(chǎng)景:
你掌握著公司半數(shù)以上的爬蟲(chóng),并且你每天都要監(jiān)控它們(他們?cè)诜?wù)器上),你作為一個(gè)爬蟲(chóng)技術(shù)從業(yè)者,你肯定會(huì)想(偷懶),因?yàn)椴煌祽械墓こ處煵粫?huì)進(jìn)步。你希望當(dāng)它們觸發(fā)某個(gè)狀況的時(shí)候,你的郵箱會(huì)收到對(duì)應(yīng)的提醒,這樣你可以及時(shí)的處理這些狀況,當(dāng)然你也可以集成微信來(lái)開(kāi)發(fā),讓通知發(fā)送到你的微信,但是互聯(lián)網(wǎng)行業(yè),郵箱還是經(jīng)常用的。
可以根據(jù)實(shí)際需求,在不同的時(shí)機(jī)發(fā)送不同的提醒郵件,以對(duì)爬蟲(chóng)狀態(tài)進(jìn)行監(jiān)控。
這里我以監(jiān)控爬蟲(chóng)的停止信息來(lái)作為示例。

二、scrapy文檔
scrapy官網(wǎng)文檔有提供郵件發(fā)送的資料:
發(fā)送email
雖然Python通過(guò) smtplib 庫(kù)使得發(fā)送email變得很簡(jiǎn)單,Scrapy仍然提供了自己的實(shí)現(xiàn)。 該功能十分易用,同時(shí)由于采用了 Twisted非阻塞式(non-blocking)IO ,其避免了對(duì)爬蟲(chóng)的非阻塞式IO的影響。 另外,其也提供了簡(jiǎn)單的API來(lái)發(fā)送附件。 通過(guò)一些 settings 設(shè)置,您可以很簡(jiǎn)單的進(jìn)行配置。
簡(jiǎn)單例子
有兩種方法可以創(chuàng)建郵件發(fā)送器(mail sender)。 您可以通過(guò)標(biāo)準(zhǔn)構(gòu)造器(constructor)創(chuàng)建:
fromscrapy.mailimportMailSendermailer = MailSender()
或者您可以傳遞一個(gè)Scrapy設(shè)置對(duì)象,其會(huì)參考 settings:
mailer= MailSender.from_settings(settings)
這是如何來(lái)發(fā)送郵件(不包括附件):
mailer.send(to=["someone@example.com"], subject="Some subject", body="Some body", cc=["another@example.com"])
MailSender類(lèi)參考手冊(cè)
在Scrapy中發(fā)送email推薦使用MailSender。其同框架中其他的部分一樣,使用了 Twisted非阻塞式(non-blocking)IO 。
classscrapy.mail.MailSender(smtphost=None, mailfrom=None, smtpuser=None, smtppass=None, smtpport=None)
參數(shù)由以下組成:
smtphost (str) – 發(fā)送email的SMTP主機(jī)(host)。如果忽略,則使用 MAIL_HOST 。
mailfrom (str) – 用于發(fā)送email的地址(address)(填入 From:) 。 如果忽略,則使用 MAIL_FROM 。
smtpuser – SMTP用戶(hù)。如果忽略,則使用 MAIL_USER 。 如果未給定,則將不會(huì)進(jìn)行SMTP認(rèn)證(authentication)。
smtppass (str) – SMTP認(rèn)證的密碼
smtpport (int) – SMTP連接的端口
smtptls – 強(qiáng)制使用STARTTLS
smtpssl(boolean)– 強(qiáng)制使用SSL連接
classmethodfrom_settings(settings)
使用Scrapy設(shè)置對(duì)象來(lái)初始化對(duì)象。其會(huì)參考 這些Scrapy設(shè)置.
參數(shù): settings (scrapy.settings.Settings object) – the e-mail recipients
send(to, subject, body, cc=None, attachs=(), mimetype='text/plain')
發(fā)送email到給定的接收者。 參數(shù):
to (list) – email接收者
subject (str) – email內(nèi)容
cc (list) – 抄送的人
body (str) – email的內(nèi)容
attachs (iterable) – 可迭代的元組 (attach_name, mimetype, file_object)。 attach_name 是一個(gè)在email
的附件中顯示的名字的字符串, mimetype 是附件的mime類(lèi)型, file_object 是包含附件內(nèi)容的可讀的文件對(duì)象。
mimetype (str) – email的mime類(lèi)型
三、實(shí)際寫(xiě)法
根據(jù)上面官網(wǎng)文檔的一些介紹和語(yǔ)法(更多語(yǔ)法請(qǐng)上官網(wǎng)翻閱)
這里編寫(xiě)一段示例代碼(結(jié)合信號(hào)量)
3.1 設(shè)置郵箱pop
登錄QQ郵箱 找到設(shè)置-賬戶(hù)
然后生成授權(quán)碼(以前是生成密碼,現(xiàn)在用授權(quán)碼)
3.2 編碼
在具體的爬蟲(chóng)文件中編寫(xiě):
from scrapy.mail import MailSender
from scrapy.xlib.pydispatch import dispatcher
from scrapy import signals
接著在class類(lèi)的上方編寫(xiě)emial的鏈接配置信息:
mailers= MailSender(smtphost="smtp.qq.com", # 發(fā)送郵件的服務(wù)器
mailfrom="abcdefg@qq.com", # 郵件發(fā)送者
smtpuser="abcdefg@qq.com", # 用戶(hù)名
smtppass="qtpzvxxyyxxyyxxyyxde", # 發(fā)送郵箱的密碼不是你注冊(cè)時(shí)的密碼,而是授權(quán)碼?。?!切記!
smtpport=25 # 端口號(hào)
) #初始化郵件模塊
然后再到class類(lèi)中編寫(xiě)信號(hào)量監(jiān)聽(tīng)和具體的郵件發(fā)送代碼:
def __init__(self):
""" 監(jiān)聽(tīng)信號(hào)量 """
super(YoutubeapiSpider, self).__init__()
# 當(dāng)收到spider_closed信號(hào)的時(shí)候,調(diào)用下面的close方法來(lái)發(fā)送通知郵件
dispatcher.connect(self.close, signals.spider_closed)
def close(spider, reason):
""" 執(zhí)行郵件發(fā)送操作 """
body ="爬蟲(chóng)[%s]已經(jīng)關(guān)閉,原因是: %s"% (spider.name, reason)
subject ="[%s]爬蟲(chóng)關(guān)閉提醒"% spider.name
mailers.send(to={"admin@qq.com","quinns@aliyun.com"},
subject=subject,
body=body)
這樣就會(huì)在收到爬蟲(chóng)關(guān)閉信號(hào)的時(shí)候,通過(guò)abgdefg@qq.com給指定的admin@qq.com和quinns@aliyun.com發(fā)送郵件(實(shí)際應(yīng)用的時(shí)候可以考慮給1個(gè)或多個(gè)郵箱發(fā)送),郵件內(nèi)容是body,郵件標(biāo)題是subject。
3.3 在郵件里添加爬蟲(chóng)停止信息
畢竟停止信息里面對(duì)爬蟲(chóng)狀態(tài)和記錄比較詳細(xì),所以郵件中應(yīng)當(dāng)發(fā)送停止信息。
當(dāng)然了,寫(xiě)法很多,除了def close 還可以:
def __init__(self):
""" 監(jiān)聽(tīng)信號(hào)量 """
super(YoutubeapiSpider, self).__init__()# 當(dāng)收到spider_closed信號(hào)的時(shí)候,調(diào)用下面的close方法來(lái)發(fā)送通知郵件
dispatcher.connect(self.spider_closed, signals.spider_closed)
def spider_closed(self, spider, reason):
# 上方的信號(hào)量觸發(fā)這個(gè)方法
stats_info = self.crawler.stats._stats # 爬蟲(chóng)結(jié)束時(shí)控制臺(tái)信息
body = "爬蟲(chóng)[%s]已經(jīng)關(guān)閉,原因是: %s.\n以下為運(yùn)行信息:\n %s" % (spider.name, reason, stats_info)
subject = "[%s]爬蟲(chóng)關(guān)閉提醒" % spider.name
mailers.send(to={"513720453@qq.com"},
subject=subject,
body=body)
只要滿足觸發(fā)條件,就可以發(fā)送指定內(nèi)容的郵件。
然后收到的郵件是這樣的:

3.4 郵件配置的坑
在使用過(guò)程中,如果發(fā)送郵件后,scrapy報(bào)出如下錯(cuò)誤信息:

通過(guò)多方排查,依舊沒(méi)有資料信息。
后來(lái)無(wú)意中改動(dòng)了郵件發(fā)送配置中的端口,就解決了這個(gè)問(wèn)題

只要將原來(lái)的25端口改成465即可。(猜測(cè)跟郵件服務(wù)器pop3的ssl有關(guān),未親自確認(rèn))
這里雖然只是以爬蟲(chóng)關(guān)閉來(lái)舉例,實(shí)際上可以監(jiān)控更多的行為操作,比如百度翻譯的接口超量、捕獲一些特殊的異常等。