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('🏀开始🏀')