如何給你的爬蟲添加預警系統


以前皮爺的文章裏面,講述了怎樣編寫爬蟲,怎樣把爬蟲經過Scrapyd部署到遠端的服務器上,也講了怎樣經過SpringBoot來實現天天自動執行爬蟲。

那麼今天咱們就來說一個能夠「保證生產環節」的操做,預警系統。php

爲啥要有預警

爲啥要有預警系統?是由於你的爬蟲的功能是爬取別人網頁上面的信息。一旦別人的網頁結果作了修改,或者域名發生變化。在爬蟲天天自動執行的時代,就會對你的數據形成確實。由於別人的修改致使了你的爬蟲失效。這個時候就要預警系統進來參與。html

預警系統有兩個做用:java

  1. 當爬蟲爬取信息,若是某些信息須要及時通知工做人員,這可時候可使用預警來通知相關人員。
  2. 當爬蟲爬取數據產生異常的時候,須要及時通知相關人員。

本文背景

這篇文章裏面的項目和代碼,均出自皮爺以前寫的文章裏面。好比以前的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複製代碼

就這樣,咱們把代碼部署到阿里雲服務器上,而後天天都會準點調用函數,來檢測數據庫是否正常:


CLOSE

今天就先說到這裏吧,其實有了這兩個功能,我感受程序的可用性會提升不少。你能夠在手機上再安裝一個接受警告郵件的客戶端,打開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…

【騰訊雲服務器、雲數據庫特惠,3折優惠券】:
cloud.tencent.com/redirect.ph…

若是你對文章中所寫的東西有什麼疑問或者不明白的地方,能夠關注公衆號『皮爺擼碼』,加入到『皮克啪交流羣』裏來和這裏面的大神一塊兒討論。

相關文章
相關標籤/搜索