Node 爬虫邮件(定时)发送 —nodelove导语一、开发工具1.node下载2.vs code下载二、主要功能1.主要说明2.项目依赖的包(插件)三、项目开始1.初始化项目2.安装所有项目依赖包3.邮件布局参考4.墨迹天气、中国天气网网址5.邮件设置(1)官方配置代码库(2).我的参考代码163邮箱设置QQ邮箱设置6.node发送邮件规则参数讲解 *代表通配符
每个参数还可以传入数值范围:对象文本语法定时器定时器 定时器对象的cancl()方法即可四、完整代码1.认识天数gedayDate函数返回的数据2.发起请求获取我的qq链接返回我的QQ链接3.发起请求获取one数据返回的json数据4.通过模板引擎替换html数据5.定时发送的时间五、留言(结束)
自从用邮箱注册了很多账号后,便会收到诸如以下类似的邮件,刚开始还以为是一张图片,后来仔细一看不是图片呀,好像还是HTML呀,于是好奇的我,查阅多篇资料后,使用前端知识和Node做一个这样的“邮件网页”。
https://code.visualstudio.com/
依赖包名称 | 功能描述 | npm地址 |
---|---|---|
path | 路径配置 | |
superagent | html请求 | |
cheerio | 解析html | |
art-template | 模板引擎 | |
nodemailer | 发送电子邮件 | https://nodemailer.com/about/ |
node-schedule | 定时发送 | https://www.npmjs.com/package/node-schedule |
1npm init -y
xxxxxxxxxx
11npm install superagent cheerio art-template nodemailer node-schedule
xxxxxxxxxx
11npm install --save-dev babel-polyfill
注意事项:邮件只允许行内样式。
x1
2<html>
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
6 <meta name="description" content="张成,无风不起浪网,无浪网,无风不起浪@你">
7 <meta name="keywords" content="QQmail、163mail">
8 <title>node_love邮箱</title>
9 <style type="text/css">
10
11
12</style>
13</head>
14<body style="margin:0;padding: 0;">
15 <div style="width: 100%;margin: 40px auto;font-size: 20px;color: #5f5e5e;text-align: center;">
16 <span>今天是我们在一起的第</span>
17 <span style="font-size:24px;color:rgb(221, 73, 73)" >520</span>
18 <span>天</span>
19 </div>
20 <div style="width: 100%;margin: 40px auto;font-size: 20px;color: #5f5e5e;text-align: center;">
21 <img style="background:#0097e0" src="https://h5tq.moji.com/tianqi/assets/images/weather/w30.png" alt="晴--天气图标">
22 <!-- <img style="background:#0097e0" src="http://image.wufazhuce.com/Fu3neP5fitv8cYLulwrjQ9zaXMB5" alt="天气图标"> -->
23 <b style="display:block;color:#333;font-size:24px;margin:15px 0;">天气:太阳</b>
24 <span style="display:block;color:#333;font-size:24px;margin:15px 0;">温度:19</span>
25 <span style="display:block;color:#333;font-size:24px;margin:15px 0;">温度:19</span>
26 <span style="display:block;color:#676767;font-size:20px">提示:近期天气有雨。</span>
27</div>
28<div style="text-align:center;margin:35px auto;">
29 <span style="display:block;margin-top:55px;color:#676767;font-size:15px">ONE · 一个</span>
30 <!-- <span style="display:block;margin-top:25px;font-size:22px; color:#9d9d9d; ">2020/3/10</span> -->
31
32 <div style="color: #333; margin: 0 auto;padding: 12.5px;text-align: center;">
33 <p style="font-size: 48px;height: 48px;line-height: 48px;">2020</p>
34 <p style=" margin: 0 0 5px;">Mar 10</p>
35 </div>
36 <img class="fp-one-imagen" src="http://image.wufazhuce.com/FklQVpjBMzz15-N2MjQkE5LqYtNh"alt="one配图">
37 <span style="color:#b0b0b0;font-size:13px;"></span>
38 <div style="margin:10px auto;width:85%;color:#5f5e5e;" >生活是苦难的,我又划着我的断桨出发了。</div>
39</div>
40<script type="text/javascript"></script>
41</body>
42</html>
xxxxxxxxxx
381"use strict";
2const nodemailer = require("nodemailer");
3
4// async..await is not allowed in global scope, must use a wrapper
5async function main() {
6 // Generate test SMTP service account from ethereal.email
7 // Only needed if you don't have a real mail account for testing
8 let testAccount = await nodemailer.createTestAccount();
9
10 // create reusable transporter object using the default SMTP transport
11 let transporter = nodemailer.createTransport({
12 host: "smtp.ethereal.email",
13 port: 587,
14 secure: false, // true for 465, false for other ports
15 auth: {
16 user: testAccount.user, // generated ethereal user
17 pass: testAccount.pass // generated ethereal password
18 }
19 });
20
21 // send mail with defined transport object
22 let info = await transporter.sendMail({
23 from: '"Fred Foo 👻" <foo@example.com>', // sender address
24 to: "bar@example.com, baz@example.com", // list of receivers
25 subject: "Hello ✔", // Subject line
26 text: "Hello world?", // plain text body
27 html: "<b>Hello world?</b>" // html body
28 });
29
30 console.log("Message sent: %s", info.messageId);
31 // Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>
32
33 // Preview only available when sending through an Ethereal account
34 console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
35 // Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
36}
37
38main().catch(console.error);
xxxxxxxxxx
371//邮箱的发送
2const nodemailer = require("nodemailer");
3
4async function sendNodeMail() {
5 //html 页面内容
6 const html = "<h1>爱的</h1>";
7 console.log(html);
8
9 //默认使用smtp传输,创建重用邮箱对象
10 let transporter = nodemailer.createTransport({
11 host: "smtp.163.com",
12 port: 465,
13 secure: true,//开启加密协议,需要使用465端口
14 auth: {
15 user: "13469940053@163.com",//用户名
16 pass: "*******"//授权密码
17 }
18 });
19 //设置电子邮件数据
20 let mailoptions = {
21 from: '"无风不起浪@你" <13469940053@163.com>',//发件人邮箱
22 to: "13469940053@163.com",//收件人列表(可以多个发送以,分开)
23 subject: "文档html",//邮件名称标题
24 text: "正文文本",
25 html: html
26 };
27
28 transporter.sendMail(mailoptions, (error, info = {}) => {
29 if (error) {
30 console.log(error);
31 sendNodeMail();//再次发送
32 }
33 console.log("邮件发送成功!", info.messageId);
34 console.log("静静等待下一次发送!");
35 });
36}
37sendNodeMail();
xxxxxxxxxx
51var schedule = require('node-schedule');
2
3var j = schedule.scheduleJob('42 * * * *', function(){
4 console.log('The answer to life, the universe, and everything!');
5});
*代表通配符
xxxxxxxxxx
91* * * * * *
2┬ ┬ ┬ ┬ ┬ ┬
3│ │ │ │ │ |
4│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
5│ │ │ │ └───── month (1 - 12)
6│ │ │ └────────── day of month (1 - 31)
7│ │ └─────────────── hour (0 - 23)
8│ └──────────────────── minute (0 - 59)
9└───────────────────────── second (0 - 59, OPTIONAL)
6个占位符从左到右分别代表:秒、分、时、日、月、周几
*
表示通配符,匹配任意,当秒是*
时,表示任意秒数都触发,其它类推
下面可以看看以下传入参数分别代表的意思
xxxxxxxxxx
111每分钟的第30秒触发: '30 * * * * *'
2
3每小时的1分30秒触发 :'30 1 * * * *'
4
5每天的凌晨1点1分30秒触发 :'30 1 1 * * *'
6
7每月的1日1点1分30秒触发 :'30 1 1 1 * *'
8
92020年的1月1日1点1分30秒触发 :'30 1 1 1 2020 *'
10
11每周1的1点1分30秒触发 :'30 1 1 * * 1'
xxxxxxxxxx
81const task1 = ()=>{
2 //每分钟的1-10秒都会触发,其它通配符依次类推
3 schedule.scheduleJob('1-10 * * * * *', ()=>{
4 console.log('scheduleCronstyle:'+ new Date());
5 })
6}
7
8task1()
xxxxxxxxxx
181const schedule = require('node-schedule');
2
3function scheduleObjectLiteralSyntax(){
4
5 //dayOfWeek
6 //month
7 //dayOfMonth
8 //hour
9 //minute
10 //second
11 //每周一的下午16:11分触发,其它组合可以根据我代码中的注释参数名自由组合
12 schedule.scheduleJob({hour: 16, minute: 11, dayOfWeek: 1}, function(){
13 console.log('scheduleObjectLiteralSyntax:' + new Date());
14 });
15
16}
17
18scheduleObjectLiteralSyntax();
xxxxxxxxxx
211const schedule = require('node-schedule');
2
3function scheduleCancel(){
4
5 var counter = 1;
6 const j = schedule.scheduleJob('* * * * * *', function(){
7
8 console.log('定时器触发次数:' + counter);
9 counter++;
10
11 });
12
13 setTimeout(function() {
14 console.log('定时器取消')
15 // 定时器取消
16 j.cancel();
17 }, 5000);
18
19}
20
21scheduleCancel();
xxxxxxxxxx
231
2function getdayDate() {
3
4 return new Promise((resolve, reject) => {
5 const today = new Date();
6
7 const meet = new Date("2020-3-9");
8
9 const count = Math.ceil((today - meet) / 1000 / 60 / 60 / 24);
10 //格式化当前日期
11 const newyear = today.getFullYear()+ '年';
12 const format = (today.getMonth() + 1) + '月' + today.getDate() + '日';
13 //json格式存储数据
14 const dayDate = {
15 count,
16 newyear,
17 format
18 }
19 console.log(dayDate);
20 console.log("认识的天数:" + dayDate.count, "认识的时间:" + dayDate.format);
21 })
22}
23getdayDate();
xxxxxxxxxx
51{
2 count: 4,
3 newyear: '2020年',
4 format: '3月12日'
5}
xxxxxxxxxx
171const QQme = "https://13469940053.github.io/";
2
3function getQQmeDate() {
4 //请求获取数据
5 request.get(QQme).end((err, res) => {
6 if (err) return console.log("数据获取失败,请检查路径是否正确!");
7 // 官网源代码获取
8 // console.log(res.text);
9 //把字符串解析成html
10 const $ = cheerio.load(res.text);
11 //温度
12 const QQme =$('.social-link a').eq(2).attr('href');
13
14 console.log(QQme);
15 });
16}
17getQQmeDate();
xxxxxxxxxx
11tencent://AddContact/?fromId=50&fromSubId=1&subcmd=all&uin=2508723631
xxxxxxxxxx
201const Oneurl = "http://wufazhuce.com/";
2
3function getoneDate() {
4 //请求获取数据
5 request.get(Oneurl).end((err, res) => {
6 if (err) return console.log("数据获取失败,请检查路径是否正确!");
7 //把字符串解析成html
8 const $ = cheerio.load(res.text);
9 // console.log(res.text);
10 const oneImg = $('.carousel-inner>.item>img, .carousel-inner>.item>a>img').attr('src');
11 const oneText = $('.fp-one .fp-one-cita-wrapper .fp-one-cita a').eq(0).text();
12
13 const onedate = {
14 oneImg,
15 oneText
16 }
17 console.log(onedate);
18 })
19}
20getoneDate();
xxxxxxxxxx
41{
2 oneImg: 'http://image.wufazhuce.com/Fr0v-josIaX2-nu7z42409DwMijf',
3 oneText: '人生需要准备的,不是昂贵的茶,而是喝茶的心情。 '
4}
xxxxxxxxxx
231async function readerTemplate() {
2 //日期 数据
3 const dayDate = await getdayDate();
4 //天气获取数据
5 const MojiDate = await getMojiDate();
6 //获取one数据
7 const oneDate = await getoneDate();
8 //获取我的QQ链接
9 const QQme = await getQQmeDate();
10
11 // console.log(dayDate+MojiDate+oneDate+QQme);
12
13 //引擎数据替换
14 const html = template(path.join(__dirname, "./demo.html"), {
15 dayDate,
16 MojiDate,
17 oneDate,
18 QQme
19 });
20 //检测数据模板中的数据是否替换完成
21 console.log(html);
22}
23 readerTemplate();
xxxxxxxxxx
61var schedule = require('node-schedule');
2 //6个占位符从左到右分别代表:秒、分、时、日、月、周几 *代表通配符
3var j = schedule.scheduleJob('42 * * * * *', function(){
4 sendNodeMail();
5 console.log('生命、宇宙和一切的答案!发送成功!');
6});
输入npm install
安装依赖,再输入node main.js
,运行脚本,当然你的电脑不可能不休眠,建议你部署到你的云服务器上运行。