那麼今天咱們就來說一個能夠「保證生產環節」的操做,預警系統。php
爲啥要有預警系統?是由於你的爬蟲的功能是爬取別人網頁上面的信息。一旦別人的網頁結果作了修改,或者域名發生變化。在爬蟲天天自動執行的時代,就會對你的數據形成確實。由於別人的修改致使了你的爬蟲失效。這個時候就要預警系統進來參與。html
預警系統有兩個做用:java
這篇文章裏面的項目和代碼,均出自皮爺以前寫的文章裏面。好比以前的Scrapy爬蟲,還有Spring Boot爲基礎寫的的 PeekpaHub 項目。spring
下文會詳細講解兩種狀況。數據庫
當爬蟲爬到你須要的數據的時候,要及時通知你。bash
這部分代碼主要寫在了爬蟲裏面。如下經過一個例子來給你們講解一下。服務器
背景知識:
皮爺曾經寫爬蟲爬取過日本氣象局的地震網站:http://www.jma.go.jp/jp/quake/quake_local_index.html
app![]()
網頁裏面是一張表格,裏面列出了地震的狀況。通常來講,一旦有地震發生,這個網站的更新速度是很快的。因此我寫的爬蟲經過每兩分鐘爬取這個網站,在必定延遲的基礎上,獲取最新的地震信息。
當每次爬蟲爬取信息的時候,若是發現爬取的新數據裏面,マグニチュード 或者 最大震度 超過必定數字的時候,這些數據就應該發送到個人郵箱裏面。socket
作法很簡單,這個操做步驟只須要在Scrapy的 pipelines.py
文件中的 process_item(self, item, spider)
函數中完成就能夠。ide
由於 process_item
裏面的調用時刻就是在爬蟲爬取完信息以後,存入數據庫以前的這個時刻。因此當數據傳到這個方法的時候,咱們能夠在裏面作判斷處理,若是條件符合,就發送郵件。
代碼部分截取以下:
def process_item(self, item, spider): try: if self.jpearth2.find_one({"jp_id": item['jp_id']}) is None: if self.needToSendHigh(item): self.sendEmail(item, True) if self.needToSendLow(item): self.sendEmail(item, False) self.jpearth2.insert(dict(item)) else: logging.info("items: " + item['jp_id'] + " has in jpearth2.") except Exception as e: logging.error("PIPLINE EXCEPTION: " + str(e))複製代碼
其中,sendEmial()
方法就是Python 發送email。
# pipeline.py def sendEmail(self, item, heighOrLow): subject = "INFO! INFO! 地震報告: " + item['jp_location'] + " -- 震級:" + item['jp_level'].strip()[1:] + " -- " + item[ 'jp_title'].strip() bodyhtml = '<html><body>' + \ '<h1>日本實時地震報告: ' + \ '地點:<a href="' + item['jp_url'] + '">' + item['jp_location'] + '</a>' + \ '震級:<a href="' + item['jp_url'] + '">' + item['jp_level'] + '</a>' + \ '</h1>' + \ '<h3>位置:<img src="' + item['jp_location_image_url'] + '"/></h3>' + \ '<h3>時間:<a href="' + item['jp_url'] + '">' + item['jp_title'] + '</a></h3>' + \ '<h3>強度:<a href="' + item['jp_url'] + '">' + item['jp_max_level'] + '</a></h3>' + \ '<p> 點擊上面的任意連接便可跳轉到『日本氣象廳』網站查看詳情 </p>' + \ '</body></html>' self.emailClient.sendEmail(self.toHighSendEmailLst, subject, bodyhtml) # emailClient.py def sendEmail(self, toLst, subject, body): ''' 發送郵件 :param toLst: 收件人的郵箱列表 :param subject: 郵件標題 :param body: 郵件內容 :return: ''' logging.info("sendEmail") message = MIMEText(body, 'html', 'utf-8') # 郵件內容,格式,編碼 message['From'] = self.sender # 發件人 message['To'] = ",".join(toLst) # 收件人列表 message['Subject'] = subject # 郵件標題 try: smtpSSLClient = smtplib.SMTP_SSL(self.smtp_host, self.smtp_port) # 實例化一個SMTP_SSL對象 loginRes = smtpSSLClient.login(self.smtp_user, self.smtp_pwd) # 登陸smtp服務器 # logging.info(f"登陸結果:loginRes = {loginRes}") # loginRes = (235, b'Authentication successful') if loginRes and loginRes[0] == 235: logging.info(f"登陸成功,code = {loginRes[0]}") smtpSSLClient.sendmail(self.sender, toLst, message.as_string()) logging.info(f"mail has been send successfully. message:{message.as_string()}") else: logging.info(f"登錄失敗,code = {loginRes[0]}") except Exception as e: logging.info(f"發送失敗,Exception: e={e}")複製代碼
最後實際效果就是,若是一旦發生地震比較嚴重,個人郵箱裏面就會收到一封服務器自動發送的郵件:
這部分的東西很簡單,皮爺以前寫過一個很詳細的文章:
『【Python實戰】Scrapy的高階騷操做,帶郵件功能的「種子吞噬器2.0」版本,更高更快更強!』 (https://www.jianshu.com/p/c360d12d8ddf)
接下來咱們主要講一下Spring Boot裏面如何自動發郵件。
由於PeekpaHub是做爲一個信息集合類網站展示的.
https://www.peekpa.tech/複製代碼
因此,判斷爬蟲是否出錯(好比目標網站域名變化致使爬取失敗),能夠寫一個定時循環任務,來天天定時從數據庫裏面看是否有數據。若是發生異常,則向管理員發送警告郵件。
@Scheduled(cron = "0 0 9,12,15,18 * * ? ") public void dailyDataCheck() { boolean hasData = databaseDao.checkHasData(TimeUtils.getInstance().getCurDayTime(), "fid7"); emailComponent.sendAlertMail("hasData: " + hasData); }複製代碼
上面的 Schedule 裏面的週期是用的 cron 寫的,意思是天天的9點,12點,15點和18點會自動調用函數。關於 Cron 的寫法,你們能夠去下面這個網站,裏面能夠根據你們本身的需求,自動生成相對應的局域,很是的方便。
在線Cron表達式生成器http://cron.qqe2.com/複製代碼
在 Spring Boot 裏面實現發送郵件,其實也很簡單,只須要用 JavaMailSender
就能夠。
@Componentpublic class EmailComponent { @Value("${mail.fromMail.sender}") private String sender; @Value("${mail.fromMail.receiver}") private String receiver; @Autowired private JavaMailSender javaMailSender; public void sendAlertMail(String textMessage) { SimpleMailMessage message = new SimpleMailMessage(); String curDayAndTime = TimeUtils.getInstance().getCurDayAndTime(); message.setFrom(sender); message.setTo(receiver); message.setSubject("DATA CHECK:: " + curDayAndTime + " PeekpaHub 數據測試結果"); message.setText(textMessage + "\nTime: " + curDayAndTime + "\nhttp://peekpa.tech/\n數據測試"); try { javaMailSender.send(message); } catch (Exception e) { print(e); } }}複製代碼
這裏面須要在 application.properties
裏面配置一些信息。
mail.fromMail.sender=發送郵件地址@126.commail.fromMail.receiver=接受郵件地址@126.comspring.mail.host=smtp.126.com //能夠用qq,163,這裏用的是126的spring.mail.username=發送郵件地址@126.comspring.mail.password=密碼spring.mail.default-encoding=UTF-8spring.mail.properties.mail.smtp.auth=truespring.mail.properties.mail.smtp.starttls.enable=truespring.mail.properties.mail.smtp.starttls.required=true// 在阿里雲上使用SMTP_SSL端口則是465spring.mail.properties.mail.smtp.socketFactory.port=465 spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory複製代碼
就這樣,咱們把代碼部署到阿里雲服務器上,而後天天都會準點調用函數,來檢測數據庫是否正常:
今天就先說到這裏吧,其實有了這兩個功能,我感受程序的可用性會提升不少。你能夠在手機上再安裝一個接受警告郵件的客戶端,打開App的推送,這樣若是一旦服務器有什麼問題,你就能夠在第一時間在手機上接到通知。這個功能其實還能夠擴展到其餘應用上面,實際上是個挺不錯的idea。
由於文章都是涉及到服務器的,因此福利就要寫在最前面:
皮爺這裏就有上千元的阿里雲和騰訊雲的優惠券給你使用(每一款優惠只要點擊優惠連接,進入便可領取):阿里雲部分:
【阿里雲新人1888元雲產品通用代金券】:
promotion.aliyun.com/ntms/yunpar…【阿里雲爆款雲主機,2折優惠券】:
promotion.aliyun.com/ntms/act/qw…【阿里雲企業級服務器2折優惠券】:
promotion.aliyun.com/ntms/act/en…騰訊雲:
【新客戶無門檻領取總價值高達2775元代金券,每種代金券限量500張,先到先得】:
cloud.tencent.com/redirect.ph…
若是你對文章中所寫的東西有什麼疑問或者不明白的地方,能夠關注公衆號『皮爺擼碼』,加入到『皮克啪交流羣』裏來和這裏面的大神一塊兒討論。