美文网首页大数据 爬虫Python AI Sql
爬虫程序又莫名崩溃了?教你这一招轻松解决!

爬虫程序又莫名崩溃了?教你这一招轻松解决!

作者: 奇峰他爹 | 来源:发表于2020-04-27 21:37 被阅读0次

    每当我们写爬虫的时候,短暂的代码运行与抓取如果期间出现异常情况,我们可以及时的发现。可实际的爬虫开发项目往往运行需要耗时,对于增量式爬虫有时也是需要放到服务器上面跑的。这样我们就不能及时的观察到异常情况,那有没有比较容易实现的技术来解决这样的问题呢?(经验总结在最后)

    答案是肯定的,有!那就是使用邮件通知,那具体如何操作呢?

    接下来我来模拟写一下需求:

    当爬虫出现故障时,第一时间通知程序员小哥哥来维护,采用邮件通知的方式。

    那我们首先来介绍一下 Python 当中支持 Smtp 协议模块叫什么名字,有以下两个模块以及他们对应的作用:

    • email负责构造邮件
    • smtplib负责发送邮件
      我们这里使用大家常用的 QQ 邮箱作为演示,小伙伴也可以使用其他邮箱可自行选择。在使用 QQ 邮箱时需要做以下配置。

    1. QQ 邮箱配置

    这里我们使用 SMTP 发信功能所以,您需要先开启 SMTP 发信功能才能通过 SMTP 接口发送邮件。

    SMTP 协议是一个简单的邮件传输协议,利用它您可以将邮件发送给别人。此协议使用命令和应答在客户端与服务器之间传输报文。即客户端发出一个命令,服务器返回一个应答。发送方与接收方进行一问一答的交互,由发送方控制这个对话。

    我先登陆到我们的 QQ 邮箱,界面如下:


    在这里插入图片描述

    选择设置,进入到如下界面:


    在这里插入图片描述
    找到:POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 在这里插入图片描述

    QQ 邮箱 SMTP 服务器地址:smtp.qq.com, ssl端口:465。

    需要其他的服务器地址以及端口的小伙伴可以点击此链接:常用邮箱 SMTP 服务器地址大全


    在这里插入图片描述

    2. Python 发送邮件

    以下实例你需要修改:发件人邮箱(你的QQ邮箱),密码,收件人邮箱(可发给自己)

    
    import smtplib
    from email.mime.text import MIMEText
    from email.utils import formataddr
    
    my_sender = '1432803776@qq.com'  # 发件人邮箱账号
    my_pass = 'xxxxxxxxx'           # 发件人邮箱授权码 不是qq密码   
    my_user = '1432803776@qq.com'    # 收件人邮箱账号,我这边发送给自己
    
    
    """
    作为一个开发者。有一个学习的氛围跟一个交流圈子特别重要,
    这是一个我的python全栈交流群: 587855308  ,
    不管你是小白还是大牛欢迎入驻,分享技术,讨论技术,大家一起交流学习成长!
    希望帮助开发者少走弯路
    """
    
    
    def mail():
        ret = True
        try:
            msg = MIMEText('填写邮件内容', 'plain', 'utf-8')
            msg['From'] = formataddr(["AI悦创", my_sender])  # 括号里的对应发件人邮箱昵称、发件人邮箱账号
            msg['To'] = formataddr(["aiyuechuang", my_user])  # 括号里的对应收件人邮箱昵称、收件人邮箱账号
            msg['Subject'] = "发送邮件测试"  # 邮件的主题,也可以说是标题
    
            server = smtplib.SMTP_SSL("smtp.qq.com", 465)  # 发件人邮箱中的SMTP服务器,端口是25
            server.login(my_sender, my_pass)  # 括号中对应的是发件人邮箱账号、邮箱授权码
            server.sendmail(my_sender, [my_user, ], msg.as_string())  # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
            server.quit()  # 关闭连接
        except Exception:  # 如果 try 中的语句没有执行,则会执行下面的 ret=False
            ret = False
        return ret
    
    
    ret = mail()
    if ret:
        print("邮件发送成功")
    else:
        print("邮件发送失败")
    

    运行代码效果如下:


    在这里插入图片描述

    3. 实战

    爬虫脚本是基于网站的结构去写的,但是随着互联网的发展,很多公司的页面结构会发生变化,发生的变化就会导致我们写的爬虫失效,最主要的失效方式是 xpath 的失效。随着我们写的爬虫越来越多,越就越来越难以发现这些失效的脚本,导致数据更新失败,不及时,或者不满足抓取的质量和数量要求。这就需要对爬虫的脚本进行监控。

    监控的目的是让数据及时的更新,脚本及时的发现 bug 以及解决 bug。提高我们的工作效率。更好的保证线上数据产品的优质性。

    目标网站:糗事百科>>> https://www.qiushibaike.com/text/

    • 爬虫代码如下:
    在这里插入代码片
    import requests
    from bs4 import BeautifulSoup
    from requests.exceptions import RequestException
    headers = {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
    }
    
    class QiuShiBaiKe(object):
      def __init__(self, url):
        self.url = url
        self.headers = headers
    
      def requests_func(self):
        try:
          response = requests.get(self.url, headers = headers)
          if response.status_code == 200:
            return response.text
          return None
        except RequestException:
          return None
    
      def parse_page(self, html):
        soup = BeautifulSoup(html, 'lxml')
        result = soup.select('#content .content-block .col1 .article')
        for res in result:
          # imgs = res.select('.author a img')
          # print(imgs)
          img = res.select('.author a img')[0].get('src')
          # img = img[:len(user_name)-23]
          img = img[:img.find('.jpg') + len('.jpg')]
          user_name = list(res.select('.author a h2')[0].stripped_strings)[0]
          joke = list(res.select('.content span')[0].stripped_strings)[0]
          yield {
            'img':img,
            'user_name':user_name,
            'joke':joke,
          }
      def save_file(self, content):
        with open("joke.txt", 'a+' ,encoding = "utf-8")as f:
          f.write(content+"\n")
    
      def main(self):
        html = self.requests_func()
        for res in self.parse_page(html):
          self.save_file(str(res))
          print(res)
    
    if __name__ == '__main__':
      urls = ['https://www.qiushibaike.com/text/page/{}/'.format(page) for page in range(1, 14)]
      for url in urls:
        result = QiuShiBaiKe(url)
        result.main()
    

    3.1 添加邮件通知

    把邮件通知单独创建一个 .py 文件,代码如下:

    
    import smtplib
    from email.mime.text import MIMEText
    from email.utils import formataddr
    
    my_sender = '1432803776@qq.com'  # 发件人邮箱账号
    my_pass = 'xxxxxx'           # 发件人邮箱授权码 不是qq密码   
    my_user = '1432803776@qq.com'    # 收件人邮箱账号,我这边发送给自己
    
    
    def email_func(Email_content = None, Email_subject = None):
      try:
        msg = MIMEText(Email_content, 'plain', 'utf-8')
        msg['From'] = formataddr(["AI悦创", my_sender])  # 括号里的对应发件人邮箱昵称、发件人邮箱账号
        msg['To'] = formataddr(["aiyuechuang", my_user])  # 括号里的对应收件人邮箱昵称、收件人邮箱账号
        msg['Subject'] = Email_subject  # 邮件的主题,也可以说是标题
    
        server = smtplib.SMTP_SSL("smtp.qq.com", 465)  # 发件人邮箱中的SMTP服务器,端口是25
        server.login(my_sender, my_pass)  # 括号中对应的是发件人邮箱账号、邮箱授权码
        server.sendmail(my_sender, [my_user, ], msg.as_string())  # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件
        server.quit()  # 关闭连接
        print("邮件发送成功")
      except Exception:
        print("邮件发送失败")
    
    if __name__ == '__main__':
      email_func("AIyuechuang", "hjb")
    

    上面的代码修改完毕之后,我们需要在爬虫的函数里面调用该函数,所以我们先导入函数:

    from email_f import email_func
    

    这里我们简单的进行调用函数:fromemail_fimportemail_func 更复杂的小伙伴可以自行添加哦。

    这里我们为了照顾绝大多数同学,就人工指定爬虫异常时放回特定信息。当然小伙伴还可以直接返回报错信息。

    我们编写在请求函数中:

    def requests_func(self):
        try:
          response = requests.get(self.url, headers = headers)
          if response.status_code == 200:
            email_func("请求成功, 返回数据", "QiuShiBaiKe_Spider")
            return response.text
          else:
            email_func("请求成功, 没有返回数据!", "QiuShiBaiKe_Spider")
            return None
        except RequestException:
          email_func("请求失败!", "QiuShiBaiKe_Spider")
          return None
    

    我们先正常运行代码查看效果:


    在这里插入图片描述

    至此,我们的邮件通知功能已经成功应用,这里有一点要跟小伙伴说的就是:为什么要把邮件单独写成一个 .py 文件,因为我们实际工作当中开发需要做到,模块化开发,上面所用到的是最基本的模块化。

    3.2 应用场景:

    3.2.1 正常更新的
    例如糗事百科,每天都要爬取一遍插入数据库的时候,需要增加一个字段更新插入时间 refresh_time 如果爬虫 正常,这样就可以保证,每天的 refresh_time 都是最新的。
    3.2.2 不正常更新的
    如何监控那些不正常更新的渠道(例如:链家租房),你可以写 sql 语句查询每个渠道的更新时间。如果是最新的更新时间则说明是正常;如果不是判断多久没有更新,说爬虫数据异常。这时需要给指定的负责人发邮件,让他修改代码,使得爬虫正常运行。
    3.2.3 爬虫中邮件通知一般加在哪呢?
    看到这里,表示你已经成功使用并监控你的爬虫,不过对于新手可能会有疑问:我们一般把异常通知加载呢?这里列出几点来:

    1. 这里小伙伴们在编写代码中要用好 try...except ,这里要注意:except后面如果指定了报错类型我们可以在你使用 except的后面添加邮件通知。

    2. 发起 get、post、head 等请求时,需要添加异常处理,因为有时候你会遇到一些:Url 异常、headers 所带参数被该网站的反爬技术改变等,这样我们添加之后就能快速定位到哪里报错。

    3. 解析网站时,有时会因为网站的 HTML 结构或者 JSON、Ajax 改变,这时我们也需要用到邮件通知。

    4. 总结

    这里我们讲到了 Python 发送邮件,并在爬虫中调用。在什么地方添加邮件通知会帮助我们快速出现问题的代码位置:

    • try...except :要添加
    • 发起请求时要添加:get、post、head,因为有事还有一些应为你 SSL 造成问题。
    • 解析网站时,有事数据未抓取到,无法提取而造成的报错,也需要在解析网站的位置添加邮件通知。

    以上便是我总结的一些爬虫报警实战经验。希望对你的工作有所帮助。代码可以进球球裙,回复“爬虫报警”即可获取哦!

    < 学习过程中有遇到不懂得问题可以随时找我咨询 >

    相关文章

      网友评论

        本文标题:爬虫程序又莫名崩溃了?教你这一招轻松解决!

        本文链接:https://www.haomeiwen.com/subject/ftlpwhtx.html