zoukankan      html  css  js  c++  java
  • 10分钟教你用python获取天气并发送邮件提醒

    前言

    今天没妹子约,刚好研究一下。如何用神奇的python打造一个把妹神器吧。看完这个,你们就能走向人生巅峰,迎娶白富美啦。

    我知道你们想看看效果

    image

    当然啦,这只是测试版的效果,真正的版本可比这个厉害多啦。不过作为一个直男,另一个男的给小编发这个测试感觉还是有点怪怪的哈。

    文:吉柏言

    暑假来了,各位又不得不和男女朋友暂时分开2个月了!!长达两个月的时间里不能相见,你可知我多想你啊,想知道你的城市下雨了吗,想知道你带伞了吗,想知道你长什么样,想知道你叫啥,咳咳,单身汪小编表示情绪稳定。

    没关系,虽然不能见面,但是云关怀还是要到的嘛,每天查一查你那里的天气如何,送上作为男朋友的关切问候,再配上一张爱你的图片,噫~~。但是作为绝地鸡王那必须每晚吃鸡呀,早上醒来忘了打卡怎么办?? 能让机器干的活我们何必自己动手呢?当然可以走一波python大法好啦!

    今天的代码我们要做得就是定点打卡,每天向亲爱的女票送去温暖的祝福~~,单身汪小编表示情绪稳定。

    环境准备

    首先,安装我们需要的库:

    import requests
    from bs4 import BeautifulSoup
    from email.mime.image import MIMEImage
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from email.header import Header
    import smtplib
    import os
    

    我们用requests + bs4 库进行爬取当日的天气状况以及我们需要的图片,用email库和smtplib库来发邮件,当中我们还需要os库对其他文件进行操作。

    开始搞事

    首先爬取天气状况和图片资源,我选择的是对中国气象台和豆瓣上一位名为名为“狼魄乾坤”的网友的豆瓣相册进行爬取,首先本着盗亦有道的原则,先查看robots协议。
    image

    image

    很好,中央气象站没有robots协议,豆瓣也没有对相册加以限制,那么我们可以放心大胆地爬取了。

    进入网站,查找一下她所在的城市,本汪没有女票就以自己所在的城市为例子了。

    http://www.nmc.cn/publish/forecast/AHB/wuhan.html 。分析一下这个地址,发现对于城市的分类命名规则是A+省份简写如湖北(HB)以及城市拼音,对于一些比较模糊的省份简写小编附在下图的代码中:

    def main():
    #    print("河北HE 内蒙古NM 陕西SN 黑龙江HL 河南HA")
    #    province = input("input the province,the big alpha for short:")
    #    city = input("input the city you wanna search plz:")
        province = "HB"
        city = "wuhan"
        url = "http://www.nmc.cn/publish/forecast/A" + province + "/" + city + ".html"
        html = getHTMLText(url)
        url = "https://www.douban.com/photos/album/157693223/"
        image = getHTMLText(url)
    

    请忽略小编的辣鸡英文。

    getHTMLText(url)是自定义方法,为的是获取网页的源代码,返回值为包含整个源代码的字符串:

    def getHTMLText(url):
        try:
            r = requests.get(url)
            print(r.raise_for_status)
            r.encoding = r.apparent_encoding
            return r.text
        except:
            return ""
    

    我们用requests.get(url)向网站提出爬取申请,用raise_for_status查看状态码,如果为200则说明爬取成功,然后我们用apparent_encoding替换掉encoding,这是让程序自己识别编码方式,保证返回的不是乱码。倘若爬取过程没有出错,就把爬下来的新鲜的天气信息素材返回给变量html。用同样的方法,我们获取新鲜的图片库的素材也用同样的方法,返回给变量image。

        imagLink = []
        whetherInfo = parserHTMLWeather(html)
        name = 1
        for image in imagLink:
            print(image)
        for image in imagLink:
            downloadPicture(image,name)
            name += 1
    

    回到main方法,我们要声明一个imagLink的列表,用来存放每个图库中每个图的地址,whetherInfo用来存储解析后的html的信息。打印image确定地址返回无误,因为在图库的源码中有豆瓣自己的大图地址和图片的地址,我们需要的是图片地址,确定无误后就可以逐个进行下载图片资源了。

    先来看解析天气信息的parserHTMLWeather方法:

    def parserHTMLWeather(html):
        try:
            dirt = {}
            soup = BeautifulSoup(html,"html.parser")
            place = soup.find(name = "head").find("title")
            dirt["place"] = str(place.string).split("-")[0]
            AnnoceTime = soup.find(name = 'div', attrs = {"class":"btitle"}).find("span")
            dirt["AnnoceTime"] = str(AnnoceTime.string)
            Everyday = AnnoceTime.find_parent().find_next_sibling().find_all(name = "div",class_ = "detail")
            for eachday in Everyday:
                info = eachday.find(name = "div",class_ = "day")
                thisDay = {}
                date = str(info.find(name = "div",class_ = "date").string)
                week = str(info.find(name = "div",class_ = "week").string)
                wdesc = str(info.find(name = "div",class_ = "wdesc").string)
                temp = str(info.find(name = "div",class_ = "temp").string)
                direct = str(info.find(name = "div",class_ = "direct").string)
                wind = str(info.find(name = "div",class_ = "wind").string)
    
                thisDay["date"] = date
                thisDay["week"] = week
                thisDay["wdesc"] = wdesc
                thisDay["temp"] = temp
                thisDay["direct"] = direct
                thisDay["wind"] = wind
                dirt[thisDay["date"]] = thisDay
    
            return dirt
        except:
            return {}
    

    首先先声明dirt为一个字典,然后把html用beautifulSoup库对其进行解析,解析后的soup对象可以调用它的find方法和find_all方法开始寻找我们需要的信息所对应的标签。至于哪个信息对应哪个标签,可以在浏览器中用ctrl + F的快捷键调出搜索框。获取到我们需要的信息后,我们可以把它进行加工保存在每天的thisDay字典里,然后再把7天的thisDay字典加入dirt字典里,最后返回dirt字典。具体的加工方法就是用split方法切片、提取。当然也可以选择正则表达式,需要额外再引用re库。

    然后是解析图片:

    def parserHTMLPicture(imag,imagLink):
        try:
            soup = BeautifulSoup(imag,"html.parser")
    #        next_url = soup.find(name = 'link',rel = 'next')['href']
    #        next_page = getHTMLText(next_url)
            imagAddress = soup.find(name='div',class_ = 'photolst clearfix').find_all(name = 'img')
            for image in imagAddress:
                imagLink.append(image['src'])
            
            return imagLink
        except:
            return []
    

    解析图片我们只需要把图片的地址获取到imagLink列表中即可。然后我们遍历这个列表,并且下载这些图片:

    def downloadPicture(url,name):
        root = 'C:\Users\10990\Pictures\'#这里填保存的路径
        path = root + str(name) + '.jpg'
        try:
            if not os.path.exists(root):
                os.mkdir(root)
            if not os.path.exists(path):
                r = requests.get(url)
                with open(path,'wb') as f:
                    f.write(r.content)
                    f.close()
                    print("文件保存成功")
            else:
                print("文件已存在")
        except:
            print("爬取失败")
    

    在下载前我们要注意判断路径是否存在,若不存在要建立一个,在开始爬之前要留意是否已经爬取过,若已经存在则跳过。命名我是以数字顺序命名的,在后续调用中也更方便。

    然后我们需要新建一个txt文件,用来保存本次发送的照片名字,注意该文件应该和代码的py文件保存在同一路径下。

    回到main()方法

    with open('pictureName.txt','r') as f:
            name = eval(f.read())
            f.close()
        with open('pictureName.txt','w') as f:
            newName = str(name + 1)
            f.write(newName)
            f.close()
        msgRoot = makeMessage(whetherInfo,name)
    sendMsg(msgRoot)
    

    然后我们读取当前的图片名,赋给name,再把name名加一后重新保存下来,这样每天发给女票的就是一张新的图片了。然后要把我们的天气信息和我们每天想说的话以及图片打包成一个email对象发送出去就行啦。

    def makeMessage(dirt,image):
        #编辑消息
        print(dirt)
        message = dirt["place"]+' 今天 '
        items = {'wdesc','temp','direct','wind'}
        for item in items:
            message += dirt["
            今天
           "][item].strip('
            ')+" "
        for temp in message.split(" "):
            if temp.find("℃") != -1:
                if eval(temp.split("℃")[0]) > 25:
                    message += "今天很热,尽量别出门啦"
                elif eval(temp.split("℃")[0]) < 12:
                    message += "今天很冷,注意保暖"
        if message.find("雨") != -1:
            message += " 出门的话记得带伞"
        print(message)
        
        #生成邮件对象
        msgRoot = MIMEMultipart('related')
        msgRoot['From'] = Header("我是发信人","utf-8")
        msgRoot['To'] = Header('我是收信人','utf-8')
        subject = '赴戍登程口占示家人'
        msgRoot['Subject'] = Header(subject,'utf-8')
    
        msgAlternative = MIMEMultipart('alternative')
        msgRoot.attach(msgAlternative)
        
        mail_msg = '''
        <p> 力微任重久神疲,再竭衰庸定不支。
            苟利国家生死以,岂因祸福避趋之?
            谪居正是君恩厚,养拙刚于戍卒宜。
            戏与山妻谈故事,试吟断送老头皮。
        </p>
        <p>'''+message+'''</p>
        <p><img src = "cid:image1"></p>
    '''
        msgAlternative.attach(MIMEText(mail_msg,'html','utf-8'))
        
        catalog = 'C:\Users\10990\Pictures\' + str(image) + ".jpg"
        #指定图片为当前目录
        with open(catalog,'rb') as fp:
            msgImage = MIMEImage(fp.read())
            fp.close()
    
        #定义图片在ID,在HTML文本中引用
        msgImage.add_header('Content-ID','<image1>')
        msgRoot.attach(msgImage)
        return msgRoot
    
    def sendMsg(message):
        mail_host = "smtp.qq.com"#要使用的smtp服务器
        mail_user = "*******"#用户名和密码
        mail_pass = "********"
        sender = '********'#发送者
        receivers = ['*******']#收信者,注意这里是一个列表,就是说可以群发,当然劝君莫浪~~
        try:
            smtpObj = smtplib.SMTP()
            smtpObj.connect(mail_host)
            smtpObj.ehlo()
            smtpObj.starttls()
            smtpObj.login(mail_user,mail_pass)
            smtpObj.sendmail(sender,receivers,message.as_string())
            print("邮件发送成功")
            smtpObj.quit()
        except smtplib.SMTPException:
            print("Error:无法发送邮件")
    
    

    往后都是可以从网上找到的代码,当然了各位也可以更进一步,从网上爬取各种骚话,用同样的方式解析并加入email对象中,为了不吃狗粮小编决定交给各位自己发掘(其实就是懒)需要注意,图片我们只爬取了一页的图片,各位还可以自行添加代码,完成自动换页之后的爬取,因为图片有限,当我们的txt文件数大于18,即自动发送18天后,需要另外爬取第二页的图片。

    另外,推荐把程序挂到服务器上面,做个定时发送。每天准点发送。这样妹子就可以天天收到你的云关怀啦。

    记得让女票把你加入白名单,否则你发过去的邮件都会被投进垃圾箱的。

    完整代码

    欲获取代码,请关注我们的微信公众号【程序猿声】,在后台回复:pylove。即可下载。

    微信公众号

    推荐文章:10分钟教你用Python做个打飞机小游戏超详细教程

  • 相关阅读:
    Bootstrap
    继承与多态
    面对对象与封装
    antd表格排序
    样式文本过长用...显示的时候,用弹框来显示文本(react为例)
    锚点
    树形结构的搜索,只显示搜索内容
    fetch不携带cookie
    antd 给select下拉框添加懒加载
    post方法下载文件
  • 原文地址:https://www.cnblogs.com/dengfaheng/p/12697315.html
Copyright © 2011-2022 走看看