使用vscode通过node.js爬取墨迹天气网站的数据,然后通过邮件每天定时给特定的一个或者多个邮箱发送具有特定html样式的163邮件。
实现爬取功能准备工作:
-
官网下载node.js
-
打开vs code建好项目,在终端输入npm init -y初始化项目;在vs code终端输入npm install superagent cheerio art-template node-schedule nodemailer安装需要的各种依赖包。
-
还需要一个163邮箱以及邮箱客户端授权密码。然后就OK可以开始撸代码啦~
main.js代码(爬虫以及计算时间部分代码)
//引入superagent包,用于服务器发送http请求;
const request = require('superagent');
//导入cheerio包,把字符串解析成html。
const cheerio = require('cheerio');
//导入模板引擎,
const template = require('art-template');
//导入path模块处理路径
const path = require('path');
//导入Nodemailer包
const nodemailer = require("nodemailer");
//导入定时模块包
var schedule = require('node-schedule');
//计算放暑假的天数
function getDayData() {
return new Promise((resolve, reject) => {
//现在的时间
const today = new Date();
//暑假开始的时间
const meet = new Date('2019-7-20');
//计算暑假到今天的天数
const count = Math.ceil((today - meet) / 1000 / 60 / 60 / 24);
//今天日期格式化
const format = today.getFullYear() + " / " + (today.getMonth() + 1) + " / " + today.getDate();
const dayData = {
count,
format
}
// console.log(dayData);
resolve(dayData);
})
}
// getDayData();
//请求墨迹天气的数据
function getMojiData() {
return new Promise((resolve, reject) => {
request.get('https://tianqi.moji.com/weather/china/henan/xinyang').end((err, res) => {
if (err) return console.log("数据请求失败~");
// console.log(res.text);
const $ = cheerio.load(res.text);
//图标
const icon = $('.wea_weather span img').attr('src');
//天气
const weather = $('.wea_weather b ').text();
//温度
const temperature = $('.wea_weather em').text();
console.log(temperature);
//提示
const tips = $('.wea_tips em').text();
const MojiData = {
icon,
weather,
temperature,
tips
}
// console.log(mojiData);
resolve(MojiData);
})
})
}
// getMojiData();
//请求one页面抓取数据
function getOneData() {
return new Promise((resolve, reject) => {
request.get('http://wufazhuce.com/').end((err, res) => {
if (err) return console.log("数据请求失败~");
const $ = cheerio.load(res.text);
// 爬取图片
const img = $('.carousel-inner>.item>a>img').eq(2).attr('src');
//爬取文字
const text = $('.fp-one .fp-one-cita-wrapper .fp-one-cita a').eq(2).text();
const OneData = {
img,
text
}
// console.log(OneData);
resolve(OneData);
})
})
}
// getOneData();
// 通过模板引擎替换html的数据
async function renderTemplate() {
//获取 日期
const dayData = await getDayData();
//获取 墨迹天气数据
const MojiData = await getMojiData();
//获取one网页数据
const OneData = await getOneData();
// console.log(dayData);
// console.log(MojiData);
// console.log(OneData);
//当所有数据都获取成功的时候,进行模板引擎数据的替换
return new Promise((resolve, reject) => {
const html = template(path.join(__dirname, "./email.html"), {
dayData,
MojiData,
OneData
});
resolve(html);
})
}
// renderTemplate();
async function sendNodeMail() {
const html = await renderTemplate();
// const html = "<h1>哈哈哈啊</h1>";
console.log(html);
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "smtp.163.com",
port: 465,
secure: true, // true for 465, false for other ports
auth: {
user: "XXXXX@163.com(你的邮箱)", // generated ethereal user用户名
pass: "XXXXX(你的邮箱客户端授权密码)" // generated ethereal password
}
});
// send mail with defined transport object
let mailOptions = {
from: '"缓月" <XXXXX@163.com", // list of receivers收件人列表
subject: "测试邮件~", // Subject line
html: html // html body
};
transporter.sendMail(mailOptions, (error, info = {}) => {
if (error) {
console.log(error);
sendNodeMail(); //再次发送
}
console.log("邮件发送成功", info.messageId);
console.log("静等下一次发送~");
})
}
var j = schedule.scheduleJob("00 26 15 * *", function() {
sendNodeMail();
console.log("发送邮件成功~");
})
邮件模板样式代码
这个是你写的邮件的样式,可以理解为一个模板,即你每天发送邮件的固定样式(可以根据自己的喜好进行更改~).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>邮件</title>
</head>
<body style="margin: 0;padding:0;">
<div style="width:100%;margin:0 auto;padding: 20px;text-align: center;">
<span style="font-size: 26px;font-weight:600;">今天是放暑假的第</span>
<span style="color: chocolate;font-size:36px;font-weight:bold;">{{ dayData.count }}</span>
<span style="font-size: 26px;font-weight:600;">天</span>
</div>
<p style="text-align:center;">小可耐,今天也要加油喔~</p>
<div style="width: 100%;margin:0 auto;color:lightsteelblue;text-align:center;">
<img src="{{ MojiData.icon }}" alt="天气icon" style="" />
<b style="display:block;color:#333;font-size:24px;margin:15px 0;">天气:{{ MojiData.weather }}</b>
<span style="display:block;color:#333;font-size:22px;margin:15px 0;">温度:{{ MojiData.temperature }}</span>
<span>Tips:{{MojiData.tips}}</span>
</div>
<div style="text-align:center;margin: 35px 0;">
<span style="display:block;margin-top:55px;color:#676767;font-size:15px;">
ONE·一个
</span>
<span style="display:block;margin-top:25px;color:#9d9d9d;font-size:22px;">{{ dayData.format }}</span>
<img src="{{ OneData.img }}" style="width:100%;margin-top:10px;" alt="今日图片" />
<div style="margin: 10px auto;margin-top:10px;">
{{ OneData.text }}
</div>
</div>
</body>
</html>