您的位置:首页 > 移动开发

Nodejs监控Apple召回计划&邮件提醒

2019-07-24 00:24 2431 查看

最近,我的13寸 MacBook Pro 2015款电池膨胀了

把笔记本平放在桌面,四个脚中的前两个无法落地,笔记本盖合上之后,屏幕上会印上键盘的纹路,也就是说,笔记本C面D面变形了,已经购买超过3年,售后不给换,同年生产的15寸的MacBook Pro因为同样的问题出了电池召回计划,我想着再坚持一下,看看13寸的会不会也出召回计划

Apple的召回计划全都更新在这里https://support.apple.com/zh-cn/exchange_repair,每天手动去查看一次,不太对得起这台笔记本,干脆写了一个爬虫监控这个页面,有最新消息就邮件通知我,对笔记本来说,也算是“自己的事情自己做”

首先利用axios加载页面,cheerio负责解析,然后找到最新一篇召回计划的标题和链接

import axios from 'axios';
import async from 'async';
import cheerio from 'cheerio';

const URL = 'https://support.apple.com/zh-cn/exchange_repair';
const homePage = await axios.get(URL);
const $ = cheerio.load(homePage.data);
const firstRepair = $('.as-columns .table-responsive .icon-chevronright');
const firstTitle = firstRepair.eq(0).text();
const firstHref = firstRepair.closest('a').attr('href');

比对标题的开头,是不是以“13 英寸 MacBook Pro”开头的,如果是,用nodemailer以我qq邮箱的身份发邮件给我(发到我的gmail邮箱)

import nodemailer from 'nodemailer';
import path from 'path';

const reg = /^13 英寸 MacBook Pro/g;
// 创建传输器对象
let transporter = nodemailer.createTransport({
service: 'qq',
port: 465,
secureConnection: true,
auth: {
// 发件人地址
user: 'xxxx@qq.com',
// SMTP授权码
pass: 'xxxx'
}
});

// 有针对MacBook Pro 13寸的新召回计划,邮件我
if (reg.test(firstTitle)) {
let mailOptions = {
// 发件人
from: '"【我的定时任务】"xxxx@qq.com',
// 收件人
to: 'wangmeijian2016@gmail.com',
// 邮件主题
subject: '有针对MacBook Pro 13寸的新召回计划了',
// 发送text或者html格式
// text: 'Hello world?',
html: `<div>
<h3><a style="color: black" href="https://support.apple.com${firstHref}" target="_blank">${firstTitle}</a></h3>
<img src="cid:01" />
</div>`,
// 附件
attachments: [
{
filename: 'Apple.png',
path: path.resolve(__dirname, 'Apple.png'),
cid: '01',
}
]
};

transporter.sendMail(mailOptions, (err, info) => {
if (err) {
return console.log(err);
}
});
}

其中transporter里的pass不是邮箱密码,而是SMTP授权码,就是授权nodejs用我的qq邮箱发邮件,在qq邮箱【设置】-【账户】里面开启SMTP服务并获取SMTP授权码

你可能注意到我在邮件HTML模板里加入了一张图片Apple.png,并且这张图片的来源就是附件,给附件加个cid就可以在模板里引用了,图片是邮件HTML模板唯一可以引用的外部资源,其他包括字体文件、视频、js文件等都不可引用

另外需要注意的是,我将召回计划的标题颜色设置为黑色,用的是行间样式,是考虑到两个问题

一是兼容性问题,部分邮箱客户端会过滤掉style标签

二是行间样式权重高,web版gmail会给a链接增加一个样式类,设置链接的字体颜色为蓝色,我利用样式权重高的特性,将浏览器给的样式覆盖,从而达到我要的效果

做了个测试,字体颜色前后对比

更多类似兼容性去这里查询 

mailOptions还有更多配置,如CC抄送等,更多配置请到这里查看

回到正题,我的需求是每天自动查看一次,此处需要一个定时任务,交给node-schedule

import schedule from 'node-schedule';

// 每天上午9点执行
schedule.scheduleJob('0 9 * * *', () => {
// 每天到点干某事
});

综上,完整代码如下

/**
* 定时查看Apple召回计划&邮件提醒
*/
import schedule from 'node-schedule';
import axios from 'axios';
import async from 'async';
import cheerio from 'cheerio';
import nodemailer from 'nodemailer';
import dayjs from 'dayjs';
import path from 'path';

const formatString = 'YYYY-MM-DD HH:mm';
const timestamp = () => {
return dayjs().format(formatString);
}
const reptile = async () => {
const URL = 'https://support.apple.com/zh-cn/exchange_repair';
const homePage = await axios.get(URL);
const $ = cheerio.load(homePage.data);
const firstRepair = $('.as-columns .table-responsive .icon-chevronright');
const firstTitle = firstRepair.eq(0).text();
const firstHref = firstRepair.closest('a').attr('href');
const reg = /^13 英寸 MacBook Pro/g;

// 创建传输器对象
let transporter = nodemailer.createTransport({
service: 'qq',
port: 465,
secureConnection: true,
auth: {
user: 'xxx@qq.com',
pass: 'xxx'
}
});

// 有针对MacBook Pro 13寸的新召回计划,邮件我
if (reg.test(firstTitle)) {
let mailOptions = {
// 发件人
from: '"【我的定时任务】"xxx@qq.com',
// 收件人
to: 'wangmeijian2016@gmail.com',
// 邮件主题
subject: '有针对MacBook Pro 13寸的新召回计划了',
// 发送text或者html格式
// text: 'Hello world?',
html: `<div>
<h3><a style="color: black" href="https://support.apple.com${firstHref}" target="_blank">${firstTitle}</a></h3>
<img src="cid:01" />
</div>`,
// 附件
attachments: [
{
filename: 'Apple.png',
path: path.resolve(__dirname, 'Apple.png'),
cid: '01',
}
]
};

transporter.sendMail(mailOptions, (err, info) => {
if (err) {
return console.log(err);
} else {
console.log(`${timestamp()}:邮件已发送~`);
}
});
}else{
console.log(`${timestamp()}:Apple暂无新召回计划~`);
}
};
reptile();
console.log(`${timestamp()}:定时任务执行中……`);

// 每天上午9点执行
schedule.scheduleJob('0 9 * * *', () => {
try {
reptile();
} catch (err) {
console.log(err);
}
});

由于nodejs不能直接执行ES6,需要配置一下环境

一、安装babel-node

npm i -g @babel/core @babel/node

二、安装 presets 并配置 .babelrc 文件

npm i @babel/preset-env --save-dev

配置.babelrc 

{
"presets": [ "@babel/preset-env" ]
}

OK,可以执行了

babel-node xxx.js

……

 

本文地址:https://www.cnblogs.com/wangmeijian/p/11225845.html 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: