likes
comments
collection
share

那一刻,我选择用程序来方便的生活

作者站长头像
站长
· 阅读数 8

在某天的下班路上,哼着小曲唱着歌的我欢快的走在回家的小路上,到了家门口掏出钥匙打开门后大喊一声:“小爱同学我回来了”,时间的流逝却没有带来我预想中的“我在”,我愣了,随后反应过来,md停电了,掏出手机后看着上头跳动的电量,一股悔恨从心头升起,nnd我应该换个手机了。。。于是乎,反手掏出身份证跑向当年挚爱的小网吧,去抚平我那蛋蛋的忧桑,随后就有了这篇文章。

那一刻,我选择用程序来方便的生活

此刻我的心情这个表情包一样,刺激中带着些沉稳,激动中带着些洒脱。反手就打开我最爱的“极速浏览器”,下载了我最爱用的vscode,舔起了我打过交道的node,此刻的我想着要给他们一个家。

没错,我准备写一个停电提醒给我自己用了,火热的心情愈发的难耐了,showtime~

那一刻,我选择用程序来方便的生活

一、准备

整个程序其实比较简单,就是一下流程。

  1. 找到当地的通知发布网站
  2. 分析网站结构,如果有直接用的接口直接用就好
  3. 获取数据
  4. 发送数据

我这里用的是node + cheerio + node-schedule ,node就不用多了,cheerio用来解析获取到的html文档,node-schedule用来执行定时任务。新建一个index.js文件,增加以下内容:

const http = require('http');//导入http模块
const cheerio = require('cheerio');//导入cheerio模块
const Mail = require('./mail');//导入自己写的Mail模块用来发送邮件
const schedule = require('node-schedule');//导入定时任务模块
let lastTime = "";//一个变量,用来保存上次获取的列表的第一条通知的发布消息的日期

二、一 获取网站数据

找到当地的网站后建立一个新的js文件,因为我这里找到的是返回的一个html机构,所以我写一个获取html的方法getHtml(),代码如下,使用这个方法首先需要导入http模块

function getHtml(src) {
    return new Promise((resolve, reject) => {
        http.get(src, response => {
            let { statusCode } = response
            if (statusCode == 200) {
                let str = ""
                response.on('data', d => {
                    str += d.toString()
                })
                response.on('end', () => {
                    resolve(str)
                })
                response.on('error', err => {
                    reject()
                })
            }
        })
    })
}

二 解析列表数据

接下来增加一个解析html的方法parseList(),如下,这个方法是获取我所在地区的停电通知列表,该方法的使用需要先引入cheerio,调用cheerio的load方法加载获取的html之后就可以使用类jquery的语法来进行操作了。cheerio的相关api可参看其文档:https://www.npmjs.com/package/cheerio

function parseList(html) {
    const $ = cheerio.load(html)//加载html
    let target = $('.news-blocks ul li').eq(0)//因为获取详情需要通过列表获取地址来进行跳转,因此需要获取列表中的第一个也是最新发布的那一个
    let url = target.find('a').attr('href')//获取跳转详情的地址
    let time = target.find('.tagtime span').text()//获取该通知的发布时间
    let title = target.find('.news-title').text()//获取该通知的标题
    let isShaHe = title.includes('所在地')//判断该通知中时候包含所在地
    // console.log(url, time, isShaHe)
    return Promise.resolve({ url, time, isShaHe, title })//返回获取到的上述信息
}

这个方法中通过cheerio的操作获取到了需要的信息。

注意,这个方法不是通用的,需要结合自己所在地的具体情况做相应的处理

三 获取详情方法

列表的相关信息在获取到后增加一个getContent()方法获取一下详情,如下

function parseContent(html) {
    const $ = cheerio.load(html)
    return Promise.resolve($('.content').html())
}

四 添加开始方法

增加一个start方法用来启动程序,如下

async function start() {
    let html = await getHtml('http://www.sttcq.com/td/jx/gz/lps/')//调用getHtml()方法获取列表
    let { url, time, isShaHe, title } = await parseList(html)//解析列表
    //不是目的地的不继续执行
    if (!isShaHe) {
        return
    }
    //本次获取时间与上次时间相同也不继续执行
    if (time == lastTime) {
        return
    }
    let contentHtml = await getHtml(`http://www.sttcq.com${url}`)//获取内容详情html
    //获取详情中的内容
    parseContent(contentHtml).then(html => {
        //邮件通知
        
    })
}

到这里调用start方法后不出意外的这个程序已经可以跑起来了,可以获取的相应的内容,但是不能发送邮件给我。

五 增加邮件发送模块

翻出一份好久前写的代码,代码如下:

const nodemailer = require('nodemailer');
function mail(subject,target, content) {
    
    let transporter = nodemailer.createTransport({
        service: 'qq', //服务器 , 可在node包文件下的nodemailer >>lib>>well-known-->services.json文件下查看支持的邮箱
        port: 465, //端口号
        secureConnection: true, // 使用 SSL
        auth: {
            user: '', //设置发送邮件的邮箱
            // smtp授权码
            pass: '',
        }
    });
    //发送设置
    let mailOptions = {
        from: '',//设置发送邮箱
        to: target, //发到哪里
        subject: subject, // 邮件主题
        // 发送text或者html格式
        // text: 'Hello world?', //text下的内容必须是字符串 , 否则会报错
        html: content // html body
    };
    //发送邮件
    return new Promise((resolve,reject)=>{
        transporter.sendMail(mailOptions, (err) => {
            if (err) {
                console.log('发送失败');
                console.log(err);
                reject('fail')
    
            } else {
                console.log('发送成功',new Date().toLocaleString());
                resolve('ok')
            }
        })
    })
}
module.exports = {
    mail
}

此方法是一个通用方法,对于qq邮箱来说改改就能用。 关于nodemailer的具体使用可以查看对应的文档www.npmjs.com/package/nod…

六 修改start方法

添加完邮件发送模块后,修改一下start方法,添加获取详情后发送邮件的步骤,如下

async function start() {
    //...
    parseContent(contentHtml).then(html => {
        //邮件通知
        Mail.mail(title, "发送到的邮箱", html)
    })
}

将start方法内的判断先注释掉,如果邮箱的确实配置正确的话且不出意外的话邮箱内就可以收到一封邮件了,如下图

那一刻,我选择用程序来方便的生活

七 添加定时任务

使用node-schedule添加定时任务,代码如下

schedule.scheduleJob('0 0 6,8,10,14,16,18,20,22,23 * * ?', () => {
    console.log('获取停电通知任务执行',new Date().toLocaleString())
    start()
})

每天的6点-23点之间在指定的时间段执行任务。node-schedule的使用可参考文档www.npmjs.com/package/nod…

最后把这个文件运行一下就能在要停电的时候及时知道了~

此刻的我,看了一眼键盘旁边的手机,心里无比的平静,我果然是严肃的,就是旁边的烟味有点大,他真该死啊!

那一刻,我选择用程序来方便的生活