领先的免费Web技术教程,涵盖HTML到ASP.NET

网站首页 > 知识剖析 正文

給她每日一封暖心小邮件~(每天的一封信)

nixiaole 2025-07-24 20:56:25 知识剖析 5 ℃

编写代码 网页爬虫

这里我们使用到superagent和cheerio组合来实现爬虫:

  • 分析网页DOM结构,如下图所示:



  • 用superagent来获取指定网页的所有DOM:

superagent.get(URL).end(function(err,res){//

}

  • 用cheerio来筛选superagent获取到的DOM,取出需要的DOM

imgUrl:$(todayOne).find('.fp-one-imagen').attr('src'),

type:$(todayOne).find('.fp-one-imagen-footer').text().replace(/(^\s*)|(\s*$)/g, ""),

text:$(todayOne).find('.fp-one-cita').text().replace(/(^\s*)|(\s*$)/g, "")

以下就是爬取ONE的代码,天气预报网页也是一个道理:

const superagent = require('superagent'); //发送网络请求获取DOM

const cheerio = require('cheerio'); //能够像Jquery一样方便获取DOM节点

const OneUrl = "http://wufazhuce.com/"; //ONE的web版网站

superagent.get(OneUrl).end(function(err,res){if(err){console.log(err);}let $ = cheerio.load(res.text);let selectItem=$('#carousel-one .carousel-inner .item');let todayOne=selectItem[0]; //获取轮播图第一个页面,也就是当天更新的内容let todayOneData={ //保存到一个json中imgUrl:$(todayOne).find('.fp-one-imagen').attr('src'),type:$(todayOne).find('.fp-one-imagen-footer').text().replace(/(^\s*)|(\s*$)/g, ""),text:$(todayOne).find('.fp-one-cita').text().replace(/(^\s*)|(\s*$)/g, "")};console.log(todayOneData);

})

EJS模版引擎生成HTML

通过爬虫获取到了数据,那么我们就能够通过将date输入到EJS渲染出HTML,我们在目录下创建js脚本和ejs模版文件:

  • app.js

const ejs = require('ejs'); //ejs模版引擎

const fs = require('fs'); //文件读写

const path = require('path'); //路径配置

//传给EJS的数据

let data={title:'nice to meet you~'

}

//将目录下的mail.ejs获取到,得到一个模版

const template = ejs.compile(fs.readFileSync(path.resolve(__dirname, 'mail.ejs'), 'utf8'));

//将数据传入模版中,生成HTML

const html = template(data);

console.log(html)

  • mail.ejs

<!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>Document</title>

</head>

<body><h1><%= title %></h1>

</body>

</html>

用Node发送邮件

这里我们可以发送纯text也可以发送html,注意的是邮箱密码不是你登录邮箱的密码,而是smtp授权码,什么是smtp授权码呢?就是你的邮箱账号可以使用这个smtp授权码在别的地方发邮件,一般smtp授权码在邮箱官网的设置中可以看的到,设置如下注释。

const nodemailer = require('nodemailer'); //发送邮件的node插件

let transporter =
nodemailer.createTransport({service: '126', // 发送者的邮箱厂商,支持列表:
https://nodemailer.com/smtp/well-known/port: 465, // SMTP 端口secureConnection: true, // SSL安全链接auth: { //发送者的账户密码user: '账户@126.com', //账户pass: 'smtp授权码', //smtp授权码,到邮箱设置下获取}});

let mailOptions = {from: '"发送者昵称" <地址@126.com>', // 发送者昵称和地址to: 'like@vince.studio', // 接收者的邮箱地址subject: '一封暖暖的小邮件', // 邮件主题text: 'test mail', //邮件的text// html: html //也可以用html发送 };


//发送邮件

transporter.sendMail(mailOptions, (error, info) => {

if (error) {return console.log(error);}console.log('邮件发送成功 ID:', info.messageId);

});

Node定时执行任务

这里我们用到了node-schedule来定时执行任务,示例如下:

var schedule = require("node-schedule");

//1. 确定的时间执行

var date = new Date(2017,12,10,15,50,0);

schedule.scheduleJob(date, function(){

console.log("执行任务");

});

//2. 秒为单位执行

//比如:每5秒执行一次

var rule1 = new schedule.RecurrenceRule();

var times1 = [1,6,11,16,21,26,31,36,41,46,51,56];

rule1.second = times1;

schedule.scheduleJob(rule1, function(){console.log("执行任务");

});

//3.以分为单位执行

//比如:每5分种执行一次

var rule2 = new schedule.RecurrenceRule();

var times2 = [1,6,11,16,21,26,31,36,41,46,51,56];

rule2.minute = times2;

schedule.scheduleJob(rule2, function(){

console.log("执行任务");

});

//4.以天单位执行

//比如:每天6点30分执行

var rule = new schedule.RecurrenceRule();

rule.dayOfWeek = [0, new schedule.Range(1, 6)];

rule.hour = 6;

rule.minute =30;

var j = schedule.scheduleJob(rule, function(){    console.log("执行任务");getData();

});

思路与步骤

当所有的问题都解决后,便是开始结合代码成一段完整的程序,思路很简单,我们来逐步分析:

  1. 由于获取数据是异步的,并且不能判断出哪个先获取到数据,这个是可以将获取数据的函数封装成一个Promise对象,最后在一起用Promise.all来判断所有数据获取完毕,再发送邮件

// 其中一个数据获取函数,其他的也是类似

function getOneData(){let p = new Promise(function(resolve,reject){superagent.get(OneUrl).end(function(err, res) {if (err) {reject(err);}let $ = cheerio.load(res.text);let selectItem = $("#carousel-one .carousel-inner .item");let todayOne = selectItem[0];let todayOneData = {imgUrl: $(todayOne).find(".fp-one-imagen").attr("src"),type: $(todayOne).find(".fp-one-imagen-footer").text().replace(/(^\s*)|(\s*$)/g, ""),text: $(todayOne).find(".fp-one-cita").text().replace(/(^\s*)|(\s*$)/g, "")};resolve(todayOneData)});})return p

}

  1. 将爬取数据统一处理,作为EJS的参数,发送邮件模板。

function getAllDataAndSendMail(){let HtmlData = {};// how long withlet today = new Date();let initDay = new Date(startDay);let lastDay = Math.floor((today - initDay) / 1000 / 60 / 60 / 24);let todaystr =today.getFullYear() +" / " +(today.getMonth() + 1) +" / " +today.getDate();HtmlData["lastDay"] = lastDay;HtmlData["todaystr"] = todaystr;

Promise.all([getOneData(),getWeatherTips(),getWeatherData()]).then(function(data){HtmlData["todayOneData"] = data[0];HtmlData["weatherTip"] = data[1];HtmlData["threeDaysData"] = data[2];sendMail(HtmlData)}).catch(function(err){getAllDataAndSendMail() //再次获取console.log('获取数据失败: ',err);})

}

  1. 发送邮件具体代码

function sendMail(HtmlData) {const template = ejs.compile(fs.readFileSync(path.resolve(__dirname, "email.ejs"), "utf8"));const html = template(HtmlData);


let transporter = nodemailer.createTransport({service: EmianService,port: 465,secureConnection: true,auth: EamilAuth});


let mailOptions = {from: EmailFrom,to: EmailTo,subject: EmailSubject,html: html};transporter.sendMail(mailOptions, (error, info={}) => {if (error) {console.log(error);sendMail(HtmlData); //再次发送}console.log("Message sent: %s", info.messageId);});}

安装与使用

如果你觉得这封邮件的内容适合你发送的对象,可以按照以下步骤,改少量参数即可运行程序;

  1. git clone https://github.com/Vincedream/NodeMail
  2. 打开main.js,修改配置项

//纪念日

let startDay = "2016/6/24";

//当地拼音,需要在下面的墨迹天气url确认

const local = "zhejiang/hangzhou";

//发送者邮箱厂家

let EmianService = "163";

//发送者邮箱账户SMTP授权码

let EamilAuth = {user: "xxxxxx@163.com",pass: "xxxxxx"

};

//发送者昵称与邮箱地址

let EmailFrom = '"name" <xxxxxx@163.com>';

//接收者邮箱地

let EmailTo = "like@vince.studio";

//邮件主题

let EmailSubject = "一封暖暖的小邮件";

//每日发送时间

let EmailHour = 6;

let EmialMinminute= 30;

  1. 终端输入npm install安装依赖,再输入node main.js,运行脚本,当然你的电脑不可能不休眠,建议你部署到你的云服务器上运行。

Tags:

最近发表
标签列表