下雨天~让程序猿打伞是不可能的!!!

42 阅读2分钟

PS:在厦门每到秋冬换季都有一段时间会断断续续下雨,每回下雨都忘了带伞可烦了。 然而当我带伞的时候雨又不下了,你说气人不气人。这个时候心里想如果下雨的前一天 有人可以提醒我一下那该多好呀,以示灵感就来了。

设计思路:写个爬虫,每天定时下午三点去爬厦门天气预报,如果发现第二天会下雨,那 就发邮件通知我第二天记得带伞,并且告诉我今天天气和明天的天气基本情况。

技术实现思路:
1. 请求网站 http 库
2. 使用 cheerio 库将网站转成 dom
3. 分析网页的数据,然后获取相关信息
4. 判断如果第二天会下雨 调用发送邮箱 nodemailer 库

踩坑1:本来是想找下有没有免费的天气接口,找了一圈基本都是要注册账号,还大部分都是收费的,果断自己写个爬虫。
踩坑2:城市id找不到,多亏了技术达人们总结出来了。👉城市id查询
踩坑3:邮箱授权码,这边用到的是QQ邮箱的授权码,具体操作请看👉连接
踩坑4:使用pm2 启动 这个 node 项目,mac电脑重启后自动启动.sh程序,👇 发现.sh没有执行,需要给.sh文件设置默认终端打开,并且在个性化设置中>用户与群主>登录项 将.sh文件加入开机任务中

附上代码详情

// 获取厦门近7天的天气 http://www.weather.com.cn/weather/101230201.shtml
// 每天下午3点获取第二天天气预报
// 如果第二天会下雨,向邮箱 caijiajia1@126.com 发提醒
const http = require('http');
const cheerio = require('cheerio');
const nodemailer = require('nodemailer');

// 配置开始
const timeDing = 15; // 定时每天下午3点判断发送通知
const mails = [
    'caijiajia1@126.com'
];
// 配置结束

let sendDate = '';
const url = 'http://www.weather.com.cn/weather/101230201.shtml';
const func = () => http.get(url,function(res){
    // 分段返回的 自己拼接
    let html = '';
    // 有数据产生的时候 拼接
    res.on('data',function(chunk){
        html += chunk;
    })
    // 拼接完成
    res.on('end', async function(){
        const $ = cheerio.load(html);
        const today = $('#hidden_title').val();
        const next = $('.t.clearfix li').eq(1).find('p').eq(0).html();
        const nextS = $('.t.clearfix li').eq(1).find('p.tem span').eq(0).html();
        const nextI = $('.t.clearfix li').eq(1).find('p.tem i').eq(0).html();

        const text = `明天会下雨,记得带伞哦!!!
今天天气: ${today}
第二天天气: ${next} ${nextI}/${nextS}
`;
        // 如果第二天有雨,向指定邮箱们发消息
        if(~next.indexOf('雨')) {
            for(mail of mails) await sendMail({text, mail});
        }
    })
});

// 发送邮箱
async function sendMail({text, mail}){
    const user = '395336343@qq.com'; // 自己的邮箱
    const pass = '****************'; // qq邮箱的授权码
    let transporter = nodemailer.createTransport({
        host:'smtp.qq.com',
        port:587,
        secure: false,
        auth:{
            user:user,
            pass:pass
        }
    });
    await transporter.sendMail({
        from: `发送人<${user}>`,
        to: `接收人<${mail}>`,
        subject: '主人,天气预报提醒一下。',
        text
    });
    console.log(`邮箱:${mail} 🏆发送成功🏆`)
}

// 平均每50分钟判断一次当前是否是下午3点,如果是获取天气预报
setInterval(function(){
    const date = new Date();
    const curHour = date.getSeconds();
    const dateStr = date.toLocaleString().slice(0, 10);
    if(curHour === timeDing && sendDate !== dateStr) {
        sendDate = dateStr;
        func();
    }
}, 50 * 1000 * 60)

console.log('🏀开始🏀')