zoukankan      html  css  js  c++  java
  • node.js爬取数据并定时发送HTML邮件

      node.js是前端程序员不可不学的一个框架,我们可以通过它来爬取数据、发送邮件、存取数据等等。下面我们通过koa2框架简单的只有一个小爬虫并使用定时任务来发送小邮件!

      首先我们先来看一下效果图

      差不多就是这样,其实之前已经有人做了类似的东西,我也只是想自己操作一遍,练习一下koa2框架,async+await,以及爬虫、定时器和发送邮件。下面我将带着各位刚刚学习node的小童鞋进入这个世界。

    1.我们先来看一看这个项目用到的框架和依赖

    1. koa2框架--基于Node.js平台的下一代web开发框架,也就是我们的开发载体
    2. ejs--嵌入式JavaScript模板引擎
    3. superagent--客户端请求代理模块
    4. cheerio--抓取网页数据模块
    5. node-schedule--任务调度器模块(定时器)
    6. nodemailer--邮件发送模块

      差不多就是这些模块,首先来初始化koa2项目,并进入目录

    npm install -g koa-generator
    koa2 test_koa
    cd test_koa

      然后安装各种依赖

    npm install ejs superagent cheerio node-schedule nodemailer --save

    2.编辑ejs模板

      因为我们要展示最近三天的编号、天气、温度、污染程度、以及one网站的图片、图片来源和鸡汤。所以按照我们想要表现的数据编写ejs模板。这里我们留下待使用的数据接口,想要详细学习请点击ejs官方网站

    3.接下来我们编写util工具方法集

      首先引入方法需要的依赖

    const cheerio = require('cheerio');
    const superagent = require('superagent');
    const nodemailer = require('nodemailer');

      具体是做什么的上面已经提及

    1.首先编写爬虫爬取one网站的页面,然后获取第一张图片也就是今天的图片。

    module.exports.getOneData = async (url) => {
      return new Promise( resolve => {
        superagent.get(url).end((err,res)=>{
          if(err){
            return 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)
        })
      })
    }

      因为superagent.get(url).end方法是一个异步的方法,所以我们使用async方法返回一个Promise对象,superagent.get(url)中的url为客户端请求代理模块路径。end方法中有两个参数,第一返回错误,第二个是获取的网页结果对象,res.text就是网页源码。接下来使用cheerio模块转化整个网页源代码成jquery模式。

    let $ = cheerio.load(res.text);

      之后分别获取图片路径、图片来源和鸡汤文

    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,""),

      并封装成对象,.replace(/(^s*)|(s*$)/g,"")是清除文本的前后导空格。

    2.然后爬取天气预报网站的页面。

      这个原理和上面的一样就不多做解释,直接贴代码

    module.exports.getWeatherData = async (url) => {
      return new Promise( resolve => {
        superagent.get(url).end((err,res)=>{
          if(err){
            return err
          }
          let $ = cheerio.load(res.text);
          let arr = [];
          $('.table_day7').each((index,item)=>{
            if (index < 3) {
              arr.push({
                day: $(item).find('dd:nth-of-type(1)').text(),
                air: $(item).find('dd:nth-of-type(2) b').text(),
                icon: "http:"+$(item).find('dd:nth-of-type(3) img').attr("src"),
                weather: $(item).find('dd:nth-of-type(4)').text(),
                temp: $(item).find('dd:nth-of-type(5)').text().replace(/℃/g,"°"),
              })
            }
          })
          resolve(arr)
        })
      })
    }

    3.接下来我们编写方法,发送email的天数

    module.exports.getDateIndex = () => Math.ceil((new Date().getTime() - 1553085879604) / ( 24 * 60 * 60 *1000 ));

      先生成一个当天的时间戳,我这里是1553085879604,然后通过这个时间戳计算是第几天发送信息,这个很简单。

    4.当天的日期

      这个也不用说,直接贴代码

    module.exports.getToday = () => new Date().getFullYear() + " / " + new Date().getMonth() + " / " + new Date().getDate();

    5.我们使用nodemailer模块发送

    module.exports.sendEmail = (html) => {
      nodemailer.createTestAccount(() => {
        let transporter = nodemailer.createTransport({
          service: 'qq',
          port: 568,
          secure: false,
          auth: {
            user: '1149967915@qq.com',
            pass: '这里填写你自己的SMTP授权码'
          }
        });
        let mailOptions = {
          from: '"郭志强" <1149967915@qq.com>',
          to: '15045160109@163.com',
          subject: '一碗鸡汤趁热喝!',
          html: html
        };
        transporter.sendMail(mailOptions, (error, info) => {
          if (error) {
            return console.log(error);
          }
          console.log('发送成功----', info.accepted[0], new Date());
        });
      });
    }

      这里需要注意的是auth的pass不是密码,而是SMTP授权码,想知道怎么得到SMTP授权码的点这里。上面这五个方法基本就够了。

    4.在项目根目录下创建schedule.js并调用定时器方法

      这里我们写一个定时器并且调用上面写的方法,首先引入依赖

    const schedule = require('node-schedule');
    const fs = require('fs');
    const path = require('path');
    const ejs = require('ejs');

      接下来引入util工具库中的方法

    const { getOneData, getWeatherData, getDateIndex, getToday, sendEmail } = require('./util/index');

      在调用getOneData方法和getWeatherData方法时。

    const oneUrl = "http://wufazhuce.com";
    const weatherUrl = "http://www.tianqi.com/beijing/7/";
    const oneData = await getOneData(oneUrl);
    const weatherData= await getWeatherData(weatherUrl);

      像上面这样写显然是不合理的,我们并不需要等待getOneData方法执行完才去执行getWeatherData。node社区从不会辜负我们,我们可以采取await Promise.all方法同时执行这两个异步方法。之后是获取ejs模板,并通过接口渲染数据。

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

      最后调用sendEmail方法发送邮件。

    sendEmail(html)

      schedule定时任务模块就不多讲,详情请看点击这里,下面贴上schedule.js所有代码

    const schedule = require('node-schedule');
    const fs = require('fs');
    const path = require('path');
    const ejs = require('ejs');
    
    const { getOneData, getWeatherData, getDateIndex, getToday, sendEmail } = require('./util/index');
    
    module.exports = function () {
      //定时任务
      schedule.scheduleJob('0 0 7 * * *', async () => {
        const oneUrl = "http://wufazhuce.com";
        const weatherUrl = "http://www.tianqi.com/beijing/7/";
        const [oneData, weatherData] = await Promise.all([getOneData(oneUrl), getWeatherData(weatherUrl)]);
        const dateIndex = getDateIndex();
        const today = getToday();
        const template = ejs.compile(fs.readFileSync(path.resolve(__dirname, 'views/index.ejs'), 'utf8'));
        let ejsModelObject = {
          oneData: oneData,
          weatherData: weatherData,
          dateIndex: dateIndex,
          today: today,
        }
        const html = template(ejsModelObject);
        sendEmail(html)
      });
    }

      到这里就可以收工了,你也可以给心爱人送上暖心的邮件,这就自由发挥了。感谢大家支持,喜欢就收藏吧。博客园同步更新。

    原创博客:转载请注明node.js爬取数据并定时发送HTML邮件

     

  • 相关阅读:
    10.22(day11) Object类 异常
    10.19(day10)
    10.18(day9)内部类 抽象类 接口
    10.17(day8) Static关键字 包的使用 访问修饰符的权限 设计模式
    paho-mqtt error1: incorrect protocol version解决方法
    Python进阶-pickle/eval/exec
    关联分析算法Apriori和FP-Growth
    LOF聚类分析
    Python进阶-迭代器和生成器
    Linux常见坑
  • 原文地址:https://www.cnblogs.com/vadim-web/p/10598591.html
Copyright © 2011-2022 走看看