如何给你的爬虫添加预警系统

作者:admin 时间:20180808 阅读:45



image

之前皮爷的文章里面,讲述了怎样编写爬虫,怎样把爬虫通过Scrapyd部署到远端的服务器上,也讲了怎样通过SpringBoot来实现每天自动执行爬虫。

那么今天我们就来讲一个可以“保证生产环节”的操作,预警系统。

为啥要有预警

为啥要有预警系统?是因为你的爬虫的功能是爬取别人网页上面的信息。一旦别人的网页结果做了修改,或者域名发生变化。在爬虫每天自动执行的时代,就会对你的数据造成确实。因为别人的修改导致了你的爬虫失效。这个时候就要预警系统进来参与。

预警系统有两个作用:

  1. 当爬虫爬取信息,如果某些信息需要及时通知工作人员,这可时候可以使用预警来通知相关人员。
  2. 当爬虫爬取数据产生异常的时候,需要及时通知相关人员。

本文背景

这篇文章里面的项目和代码,均出自皮爷之前写的文章里面。比如之前的Scrapy爬虫,还有Spring Boot为基础写的的 PeekpaHub 项目。

下文会详细讲解两种情况。

第一种情况

当爬虫爬到你需要的数据的时候,要及时通知你。

这部分代码主要写在了爬虫里面。以下通过一个例子来给大家讲解一下。

背景知识:
皮爷曾经写爬虫爬取过日本气象局的地震网站:http://www.jma.go.jp/jp/quake/quake_local_index.html


image

网页里面是一张表格,里面列出了地震的情况。一般来说,一旦有地震发生,这个网站的更新速度是很快的。所以我写的爬虫通过每两分钟爬取这个网站,在一定延迟的基础上,获取最新的地震信息。

当每次爬虫爬取信息的时候,如果发现爬取的新数据里面,マグニチュード 或者 最大震度 超过一定数字的时候,这些数据就应该发送到我的邮箱里面。

做法很简单,这个操作步骤只需要在Scrapy的 pipelines.py 文件中的 process_item(self, item, spider) 函数中完成就可以。

因为 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="'%20+%20item['jp_url']%20+%20'">' + item['jp_location'] + '</a>' + \
                   '震级:<a href="'%20+%20item['jp_url']%20+%20'">' + item['jp_level'] + '</a>' + \
                   '</h1>' + \
                   '<h3>位置:<img src="'%20+%20item['jp_location_image_url']%20+%20'"/></h3>' + \
                   '<h3>时间:<a href="'%20+%20item['jp_url']%20+%20'">' + item['jp_title'] + '</a></h3>' + \
                   '<h3>强度:<a href="'%20+%20item['jp_url']%20+%20'">' + 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}")

最后实际效果就是,如果一旦发生地震比较严重,我的邮箱里面就会收到一封服务器自动发送的邮件:


image

这部分的东西很简单,皮爷之前写过一个很详细的文章:

『【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 就可以。

@Component
public 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.com
mail.fromMail.receiver=接受邮件地址@126.com
spring.mail.host=smtp.126.com //可以用qq,163,这里用的是126的
spring.mail.username=发送邮件地址@126.com
spring.mail.password=密码
spring.mail.default-encoding=UTF-8
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
// 在阿里云上使用SMTP_SSL端口则是465
spring.mail.properties.mail.smtp.socketFactory.port=465 
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory

就这样,我们把代码部署到阿里云服务器上,然后每天都会准点调用函数,来检测数据库是否正常:


image


image

CLOSE

今天就先说到这里吧,其实有了这两个功能,我感觉程序的可用性会提高很多。你可以在手机上再安装一个接受警告邮件的客户端,打开App的推送,这样如果一旦服务器有什么问题,你就可以在第一时间在手机上接到通知。这个功能其实还可以扩展到其他应用上面,其实是个挺不错的idea。

因为文章都是涉及到服务器的,所以福利就要写在最前面
皮爷这里就有上千元的阿里云和腾讯云的优惠券给你使用(每一款优惠只要点击优惠链接,进入即可领取):

阿里云部分
【阿里云新人1888元云产品通用代金券】:
https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=nrkmbo9q

【阿里云爆款云主机,2折优惠券】:
https://promotion.aliyun.com/ntms/act/qwbk.html?userCode=nrkmbo9q

【阿里云企业级服务器2折优惠券】:
https://promotion.aliyun.com/ntms/act/enterprise-discount.html?userCode=nrkmbo9q

腾讯云

【新客户无门槛领取总价值高达2775元代金券,每种代金券限量500张,先到先得】:
https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=b351b2fc50b15866ff9d19b58a5df0f5&from=console

【腾讯云服务器、云数据库特惠,3折优惠券】:
https://cloud.tencent.com/redirect.php?redirect=1014&cps_key=b351b2fc50b15866ff9d19b58a5df0f5&from=console

如果你对文章中所写的东西有什么疑问或者不明白的地方,可以关注公众号『皮爷撸码』,加入到『皮克啪交流群』里来和这里面的大神一起讨论。


底部二维码.png



公众号:程序员资源社区

扫码回复:源码,获取网站教程源码

编程网盘资料/视频分享群(免费)

微信扫码进群领取资料