Nodejs監控Apple召回計劃&郵件提醒

wangmeijian發表於2019-07-24

最近,我的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 

相關文章