先看效果
其中的内容包含了当前时间、与女友的纪念日、当天天气、每日一句话和生活小常识(爱从小事做起)
所用到的包
"cheerio": "^1.0.0-rc.3", //爬取网站内容
"node-schedule": "^1.3.2", //定时器
"nodemailer": "^6.3.1", //发送邮箱
"nodemailer-smtp-transport": "^2.7.4",
"superagent": "^5.1.0"
目录结构
整体思路
主要分为三步:
1.爬取数据和通过API获取数据
2.处理数据,整合成要发送的模板
3.设置发送时间,发送邮件
一、获取数据
本案例中的数据来源有两个,其中的“每日一句”是通过爬取ONE的web版往网站获取的(网址:http://wufazhuce.com/)
天气信息和健康小知识是通过天行API获取的(网址:https://www.tianapi.com/signup.html?source=474284281),使用前需要去申请apikey。
config/confi.js中为配置信息
module.exports = {
MEMORIAL_DAY: '2016-09-17', //与女朋友的纪念日
TXAPIKEY: '', //此处须填写个人申请的天行apikey,请替换成自己的
//邮箱配置(qq邮箱)
emailUser: "@qq.com", // 账号 你自定义的域名邮箱账号
emailPass: "", // 密码 你自己开启SMPT获取的密码
toEmailList: ['[email protected]'], // 收件列表,可同时发送给多个人
emailSubject: '来自馒头耙耙的每日关心', //邮件标题
}
这里需要说明一下,上面的emailPass不是指的你的邮箱登陆密码,而是你的邮箱开启SMTP服务的密码,这里以QQ邮箱为例。
登陆QQ邮箱,点击设置->账户
往下翻,找到SMTP服务,点击开启后会弹出你的服务密码
config/superagent.js爬取页面信息
const superagent = require('superagent')
//请求
function req(url,method, params, data, cookies) {
return new Promise(function (resolve,reject) {
superagent(method, url)
.query(params)
.send(data)
.set('Content-Type','application/x-www-form-urlencoded')
.end(function (err, response) {
if (err) {
reject(err)
}
resolve(response)
})
})
}
module.exports = {
req
}
utils/cheerio.js中为获取数据,内容如下:
const cheerio = require('cheerio');
const superagent = require('../config/superagent');
const ONE = 'http://wufazhuce.com/'; // ONE的web版网站
const TXHOST = 'http://api.tianapi.com/txapi/'; // 天行host
const config = require('../config/config')
async function getOne() {
// 获取每日一句
try {
let res = await superagent.req(ONE, 'GET');
let $ = cheerio.load(res.text);
let todayOneList = $('#carousel-one .carousel-inner .item');
let todayOne = $(todayOneList[0])
.find('.fp-one-cita')
.text()
.replace(/(^\s*)|(\s*$)/g, '');
return todayOne;
} catch (err) {
console.log('错误', err);
return err;
}
}
async function getTXweather() {
// 获取天行天气
let url = TXHOST + 'tianqi/';
try {
let res = await superagent.req(url, 'GET', {
key: config.TXAPIKEY,
city: '重庆'
});
let content = JSON.parse(res.text);
if (content.code === 200) {
let todayInfo = content.newslist[0];
return todayInfo;
} else {
console.log('获取接口失败', content.code);
}
} catch (err) {
console.log('获取接口失败', err);
}
}
async function getTXhealthtip() {
// 获取健康小提示
let url = TXHOST + 'healthtip/';
try {
let res = await superagent.req(url, 'GET', {
key: config.TXAPIKEY,
});
let content = JSON.parse(res.text);
if (content.code === 200) {
let healthtip = content.newslist[0].content;
return healthtip;
} else {
console.log('获取接口失败', content.code);
}
} catch (err) {
console.log('获取接口失败', err);
}
}
module.exports = {
getOne,
getTXweather,
getTXhealthtip
}
二、处理数据
处理时间:utils/dateTime.js(获取当天时间、计算当天与女友纪念日的差值、格式化时间)
function getDay(date) {
var date2 = new Date();
var date1 = new Date(date);
var iDays = parseInt(
Math.abs(date2.getTime() - date1.getTime()) / 1000 / 60 / 60 / 24
);
return iDays;
}
function getToday(){
let today = new Date()
var year = today.getFullYear();
var month = today.getMonth() + 1;
var day = today.getDate();
return `今天是${year}年${month}月${day}日`
}
function formatDate(date) {
var tempDate = new Date(date);
var year = tempDate.getFullYear();
var month = tempDate.getMonth() + 1;
var day = tempDate.getDate();
var hour = tempDate.getHours();
var min = tempDate.getMinutes();
var second = tempDate.getSeconds();
var week = tempDate.getDay();
var str = '';
if (week === 0) {
str = '星期日';
} else if (week === 1) {
str = '星期一';
} else if (week === 2) {
str = '星期二';
} else if (week === 3) {
str = '星期三';
} else if (week === 4) {
str = '星期四';
} else if (week === 5) {
str = '星期五';
} else if (week === 6) {
str = '星期六';
}
if (hour < 10) {
hour = '0' + hour;
}
if (min < 10) {
min = '0' + min;
}
if (second < 10) {
second = '0' + second;
}
return year + '-' + month + '-' + day + '日 ' + hour + ':' + min + ' ' + str;
}
module.exports = {
getDay,
formatDate,
getToday
};
处理发送邮件信息:utils/email.js
// 引入email 模块
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
const config = require('../config/config')
// 开启一个 SMTP 连接池
var transport = nodemailer.createTransport(smtpTransport({
host: "smtp.qq.com", // qq邮箱主机
secure: true, // 使用 SSL
secureConnection: true, // 使用 SSL
port: 465, // SMTP 端口
auth: {
user: config.emailUser, // 账号 你自定义的域名邮箱账号
pass: config.emailPass // 密码 你自己开启SMPT获取的密码
}
}));
function sendEmail(htmlcon) {
// 设置邮件内容 可以拼接html 美化发送内容
var mailOptions = {
from: config.emailUser, // 发件地址
to: config.toEmailList, // 收件列表
subject: config.emailSubject, // 标题
text: "text",
html: htmlcon // html 内容
}
transport.sendMail(mailOptions, function (error, response) {
if (error) {
console.log("fail: " + error);
console.log("发送失败");
} else {
console.log("发送成功");
}
transport.close(); // 如果没用,关闭连接池
});
}
module.exports = {sendEmail}
三、设置发送时间及发送邮件
设置发送时间:utils/schedule.js
const schedule = require('node-schedule')
// date 参数
//其他规则见 https://www.npmjs.com/package/node-schedule
// 规则参数讲解 *代表通配符
//
// * * * * * *
// ┬ ┬ ┬ ┬ ┬ ┬
// │ │ │ │ │ |
// │ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
// │ │ │ │ └───── month (1 - 12)
// │ │ │ └────────── day of month (1 - 31)
// │ │ └─────────────── hour (0 - 23)
// │ └──────────────────── minute (0 - 59)
// └───────────────────────── second (0 - 59, OPTIONAL)
// 每分钟的第30秒触发: '30 * * * * *'
//
// 每小时的1分30秒触发 :'30 1 * * * *'
//
// 每天的凌晨1点1分30秒触发 :'30 1 1 * * *'
//
// 每月的1日1点1分30秒触发 :'30 1 1 1 * *'
//
// 每周1的1点1分30秒触发 :'30 1 1 * * 1'
function setSchedule(date,callback) {
schedule.scheduleJob(date, callback)
}
module.exports = {
setSchedule
}
index.js入口文件
const Email = require('./utils/email')
const Schedule = require('./utils/schedule')
const DateTime = require('./utils/dateTime')
const Cheerio = require('./utils/cheerio')
const config = require('./config/config')
async function run(){
let oneText = await Cheerio.getOne()
let weather = await Cheerio.getTXweather()
let healthtip = await Cheerio.getTXhealthtip()
let today = DateTime.getToday()
Email.sendEmail(`
${today} ${weather.week}
和馒头耙耙相恋的第 ${DateTime.getDay(config.MEMORIAL_DAY)} 天
${weather.lowest}~${weather.highest}
${weather.weather} ${weather.wind}${weather.windspeed}
${weather.tips}
${oneText}
生活小常识:
${healthtip}