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邮件

     

  • 相关阅读:
    Java对象的生命周期与作用域的讨论(转)
    [置顶] Oracle学习路线与方法
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 未名湖边的烦恼
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
    Java实现 蓝桥杯 算法训练 最大的算式
  • 原文地址:https://www.cnblogs.com/vadim-web/p/10598591.html
Copyright © 2011-2022 走看看