Python爬蟲監(jiān)控(郵件和釘釘)

一、監(jiān)控的意義

爬蟲腳本是基于網(wǎng)站的結(jié)構(gòu)去寫的,但是隨著互聯(lián)網(wǎng)的發(fā)展,很多公司的頁面結(jié)構(gòu)會(huì)發(fā)生變化,發(fā)生的變化就會(huì)導(dǎo)致我們寫的爬蟲失效,最主要的失效方式是xpath的失效。隨著我們寫的爬蟲越來越多,越就越來越難以發(fā)現(xiàn)這些失效的腳本,導(dǎo)致數(shù)據(jù)更新失敗,不及時(shí),或者不滿足抓取的質(zhì)量和數(shù)量要求。這就需要對(duì)爬蟲的腳本進(jìn)行監(jiān)控。

監(jiān)控的目的是讓數(shù)據(jù)及時(shí)的更新,腳本及時(shí)的發(fā)現(xiàn)bug以及解決bug。提高我們的工作效率。更好的保證線上數(shù)據(jù)產(chǎn)品的優(yōu)質(zhì)性。

我們需要介紹兩種常見的監(jiān)控方式:1、郵件 2、釘釘

二、Python郵件監(jiān)控(SMTP)

1. SMTP簡介

SMTP(Simple Mail Transfer Protocol)即簡單郵件傳輸協(xié)議,它是一組用于由源地址到目的地址傳送郵件的規(guī)則,由它來控制信件的中轉(zhuǎn)方式。
python的smtplib提供了一種很方便的途徑發(fā)送電子郵件。它對(duì)smtp協(xié)議進(jìn)行了簡單的封裝。

Python創(chuàng)建 SMTP 對(duì)象語法如下

import smtplib
smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )

參數(shù)說明:

  • host: SMTP 服務(wù)器主機(jī)。 你可以指定主機(jī)的ip地址或者域名如: runoob.com,這個(gè)是可選參數(shù)。
  • port: 如果你提供了 host 參數(shù), 你需要指定 SMTP 服務(wù)使用的端口號(hào),一般情況下 SMTP 端口號(hào)為25。
  • local_hostname: 如果 SMTP 在你的本機(jī)上,你只需要指定服務(wù)器地址為 localhost 即可。

Python SMTP 對(duì)象使用 sendmail 方法發(fā)送郵件,語法如下:

SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])

參數(shù)說明:

  • from_addr: 郵件發(fā)送者地址。
  • to_addrs: 字符串列表,郵件發(fā)送地址。
  • msg: 發(fā)送消息

這里要注意一下第三個(gè)參數(shù),msg 是字符串,表示郵件。我們知道郵件一般由標(biāo)題,發(fā)信人,收件人,郵件內(nèi)容,附件等構(gòu)成,發(fā)送郵件的時(shí)候,要注意 msg 的格式。這個(gè)格式就是 smtp 協(xié)議中定義的格式。

2. 郵件監(jiān)控五個(gè)步驟

 #導(dǎo)入郵件包
 import smtplib
 
 # 1.創(chuàng)建郵件對(duì)象
    smtp_obj = smtplib.SMTP()
    
 # 2.連接服務(wù)器
    smtp_obj.connect()
    
  #3.登錄操作
    smtp_obj.login()
    
  #4.發(fā)郵件
     smtp_obj.sendmail()
     
  #5.退出操作
   smtp_obj.quit()

3. 郵件監(jiān)控發(fā)送(代碼)

# 導(dǎo)入發(fā)送郵件包
import smtplib
from email.mime.text import MIMEText  # 用來創(chuàng)建文本格式的郵件體內(nèi)容
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage

class Send_Email:

    def __init__(self, num):
        self.num = num
        self.smtp = self.get_conn()
        # print(self.smtp)
        self.send_email()

    def get_conn(self):
        # 創(chuàng)建郵件對(duì)象
        smtp_obj = smtplib.SMTP()
        # 連接服務(wù)器
        smtp_obj.connect("smtp.163.com")
        # 登錄郵箱
        smtp_obj.login("13349949963@163.com", "zb376100870")
        return smtp_obj

    def send_email(self):
        # 定義發(fā)送郵件的三要素
        sender = "13349949963@163.com"
        receiver = "376100870@qq.com"
        # 獲取發(fā)送郵件的 郵件體
        msg = self.get_msg(sender, receiver)
        # 發(fā)送郵件
        self.smtp.sendmail(from_addr=sender, to_addrs=receiver, msg=msg.as_string())
        print("send success")

    def get_msg(self, sender, receiver):
        # 定義郵件主題
        subject = "恭喜你 你已經(jīng)被阿里巴巴公司錄用 "
        # 獲取郵件體中的 文本內(nèi)容(消息體)
        msg = self.get_content()
        # 生成郵件體的 三要素
        msg["From"] = sender
        msg["To"] = receiver
        msg["Subject"] = subject
        return msg

    def get_content(self):

        if self.num == 1:
            content = "請(qǐng)xx準(zhǔn)時(shí)報(bào)到"
            # 將內(nèi)容寫到面板中  文本格式
            msg = MIMEText(content, "plain", "utf-8")
            return msg
        elif self.num==2:
            # 讀取文件
            # with open("02.html", "r", encoding="utf-8") as f:
            #     content = f.read()
            # print(type(content))
            content = """
            <html>
                <h1>請(qǐng)xx準(zhǔn)時(shí)報(bào)到<h1>
                <a >baidu</a>
            </html>"""
            print(content)
            msg = MIMEText(content, "html", "utf-8")
            return msg
        elif self.num==3:
            #獲取含有內(nèi)嵌圖片資源的HTML格式的郵件體
            msg=self.get_pic()
            return msg
    #獲取圖片信息
    def get_pic(self):
        #通過cid圖片文件關(guān)聯(lián)起來
        content="<b>Some<i>HTML</i>text</b> and an image <br><img src='cid:image1'><br>goood"
        #如果content 中內(nèi)嵌資源,必須定義related字段
        #使用related定義內(nèi)嵌套資源的郵件體
        msgRoot=MIMEMultipart("related")
        #創(chuàng)建HTML格式的郵件體
        msgText=MIMEMultipart(content,"html","utf-8")
        #將msgText中的內(nèi)容附加到MIMEMultipart對(duì)象中
        msgRoot.attach(msgText)
        #讀取圖片文件內(nèi)容
        with open("2.jpg","rb")as f:
            result=f.read()
        #使用圖片信息創(chuàng)建一個(gè)圖片對(duì)象
        msgImage=MIMEImage(result)
        #指定文件的Content-ID 為image1
        msgImage.add_header("Content-ID","image1")
        #將msgImage中的圖片內(nèi)容附加到MIMEMultipart對(duì)象的指定image1當(dāng)中
        msgRoot.attach(msgImage)
        #返回?cái)y帶有內(nèi)嵌套圖片資源的HTML格式郵件的MIMEMultipart對(duì)象
        return msgRoot

    def __del__(self):
        # 關(guān)閉
        self.smtp.quit()


if __name__ == '__main__':
    #  1  # 發(fā)送的郵件體是字符串
   2  # 發(fā)送一個(gè)html的郵件體
   3 # 發(fā)送一個(gè)圖片的郵件體
   num=int(input("請(qǐng)發(fā)送郵件所對(duì)應(yīng)的數(shù)字"))
   Send_Email(num)

應(yīng)用場景:

  1. 鏈家租房 每天都要爬取一遍插入數(shù)據(jù)庫的時(shí)候 需要增加一個(gè)字段 更新插入時(shí)間refresh_time如果爬蟲 正常 這樣就可以保證 每天的refresh_time都是最新的

  2. 如何監(jiān)控那些 不正常更新的渠道(例如:鏈家租房),你可以寫sql語句查詢每個(gè)渠道的更新時(shí)間;。如果是最新的更新時(shí)間則說明是正常;如果不是判斷多久沒有更新,說爬蟲數(shù)據(jù)異常。這時(shí)需要 給指定的負(fù)責(zé)人發(fā)郵件 讓他修改代碼 使得爬蟲正常運(yùn)行。

郵件監(jiān)控和下面的釘釘監(jiān)控一樣,可以根據(jù)釘釘監(jiān)控來改寫

二、釘釘監(jiān)控

鏈家租房監(jiān)控腳本

import pymysql
import time
import requests
'''
kpi小姐姐的api接口:
https://oapi.dingtalk.com/robot/send?access_token=8daebe660297f090e6839b6a4454ff05382b59f3d515b3d7c14bc07f5fb642dd
'''

class Moniter:

    def __init__(self):
        self.conn_mysql()
        self.get_data()

    def conn_mysql(self):
        # 創(chuàng)建數(shù)據(jù)庫的連接對(duì)象
        # 字符集是utf8 不是utf-8
        self.conn = pymysql.connect(host="127.0.0.1", user="root",password='123',
                                    database="0218", charset="utf8")
        # 創(chuàng)建操作數(shù)據(jù)庫的對(duì)象
        self.cur = self.conn.cursor()

    def get_data(self):
        # 定義一天前的時(shí)間戳
        day_ago = time.time() - 86400

        # 定義查詢出總數(shù)和更新數(shù)量的sql語句
        sql = """
                select count(*) from lianjia
                union 
                select count(*) from lianjia where refresh_time > {}
                union 
                select phone from source_name where source = "lianjia"
                """.format(day_ago)
        # 執(zhí)行sql語句 并獲取sql語句查詢出來的 數(shù)據(jù)
        self.cur.execute(sql)
        self.conn.commit()
        data = self.cur.fetchall()
        # print(data, type(data))

        # 提出數(shù)據(jù) 獲取總數(shù) 和更新數(shù)
        total_count = int(data[0][0])
        refresh_count = int(data[1][0])
        phone = data[2][0]
        # print(total_count, refresh_count, phone)

        # 生成刷新數(shù)量的 百分比
        per_no_refresh = refresh_count / total_count
        # print(per_no_refresh)
        #如果最新數(shù)據(jù)的占比小于80%,則說明需要提醒
        if per_no_refresh < 0.8:
            per_no_refresh = "%.2f%%" % (per_no_refresh * 100)
            # print(per_no_refresh)

            # 發(fā)送釘釘消息
            self.dingding(phone, per_no_refresh)

    def dingding(self, phone, per_no_refresh):

        dd_api = "https://oapi.dingtalk.com/robot/send?access_token=" \
                 "8daebe660297f090e6839b6a4454ff05382b59f3d515b3d7c14bc07f5fb642dd"
        # print(phone, per_no_refresh)

        dd_json = {
            "msgtype": "text",
            "text": {
                "content": "你的渠道有問題 請(qǐng)及時(shí)解決 更新比例為:{}".format(per_no_refresh)
            },
            "at": {
                "atMobiles": [
                    phone,
                    "18679030315"
                ],
                "isAtAll": False
            }
        }

        requests.post(dd_api, json=dd_json)
        print("send success")


    def __del__(self):
        self.cur.close()
        self.conn.close()


if __name__ == '__main__':
    Moniter()

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 加入貓叔小灶群三個(gè)多月,簡書寫了78篇文,約五萬字,文字越寫越順,內(nèi)心越寫越充實(shí),而且,在這期間,我學(xué)習(xí)效率大大提...
    孫國飛揚(yáng)閱讀 463評(píng)論 11 18
  • 有人等在旅游階段 風(fēng)景感受比鄰無界限 有人等在咖啡館 同樣的位置 同樣的咖啡 音樂播放不階段 這樣的習(xí)慣 在咖啡館...
    汐的島閱讀 180評(píng)論 2 1
  • fetch:從遠(yuǎn)程獲取最新版本到本地,不會(huì)自動(dòng)merge 用WebStormGit操作:ctrl+shift+A ...
    Uching閱讀 421評(píng)論 0 0
  • 黑夜的貓 特立獨(dú)行 卻不喜歡這樣的雨夜 太過感傷 太過寂寞 太過懷念 入秋的一場雨 涼透了 涼透了 遠(yuǎn)方的暗黃的...
    Z黑夜的貓?zhí)亓ⅹ?dú)行閱讀 236評(píng)論 0 1

友情鏈接更多精彩內(nèi)容