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

node.js爬取数据并定时发送HTML邮件的更多相关文章

  1. Node.js爬取豆瓣数据

    一直自以为自己vue还可以,一直自以为webpack还可以,今天在慕课逛node的时候,才发现,自己还差的很远.众所周知,vue-cli基于webpack,而webpack基于node,对node不了 ...

  2. node.js爬取ajax接口数据

    爬取页面数据与爬取接口数据,我还是觉得爬取接口数据更加简单一点,主要爬取一些分页的数据. 爬取步骤: 1.明确目标接口地址,举个例子 : https://www.vcg.com/api/common/ ...

  3. node.js抓取数据(fake小爬虫)

    在node.js中,有了 cheerio 模块.request 模块,抓取特定URL页面的数据已经非常方便. 一个简单的就如下 var request = require('request'); va ...

  4. 关于js渲染网页时爬取数据的思路和全过程(附源码)

    于js渲染网页时爬取数据的思路 首先可以先去用requests库访问url来测试一下能不能拿到数据,如果能拿到那么就是一个普通的网页,如果出现403类的错误代码可以在requests.get()方法里 ...

  5. Node.js 抓取电影天堂新上电影节目单及ftp链接

    代码地址如下:http://www.demodashi.com/demo/12368.html 1 概述 本实例主要使用Node.js去抓取电影的节目单,方便大家使用下载. 2 node packag ...

  6. 借助Chrome和插件爬取数据

    工具 Chrome浏览器 TamperMonkey ReRes Chrome浏览器 chrome浏览器是目前最受欢迎的浏览器,没有之一,它兼容大部分的w3c标准和ecma标准,对于前端工程师在开发过程 ...

  7. 【个人】爬虫实践,利用xpath方式爬取数据之爬取虾米音乐排行榜

    实验网站:虾米音乐排行榜 网站地址:http://www.xiami.com/chart  难度系数:★☆☆☆☆ 依赖库:request.lxml的etree (安装lxml:pip install ...

  8. Node.js 本地Xhr取得Node.js服务端数据的例子

    本以为用XHR取Nodejs http出的一段文字很简单,因为xhr取值和nodejs http出文字都是好弄的,谁知一试不是这回事,中间有个关键步骤需要实现. nodejs http出文字显示在浏览 ...

  9. Node.js 返回 JSON 数据

    Node.js 返回 JSON 数据 request.end([data[, encoding]][, callback]) var http = require('http'); const log ...

随机推荐

  1. centos忘记密码

    1.启动时按上下箭头,然后按e进入进入编辑模式 2.上下箭头切换在选择 linux ...这行在末尾输入 LANG=en_US.UTF-8 init=/bin/sh 然后按 ctrl+x 进行引导 3 ...

  2. ubuntu sublime text 3 安装

    #安装GPG wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | sudo apt-key add - #确保apt被设置为 ...

  3. 小学生都看得懂的C语言入门(1): 基础/判别/循环

    c基础入门, 小学生也可以都看得懂!!!! 安装一个编译器, 这方面我不太懂, 安装了DEV-C++  ,体积不大,30M左右吧, 感觉挺好用,初学者够了. 介绍下DEV 的快键键: 恢复 Ctrl+ ...

  4. 2018.8.1 状压 CF482C 题解

    noip2016考了一道状压dp,一道期望dp 然而这题是状压期望dp... 所以难度是什么,省选noi吗... 怎么办... 题目大意: 给定n个字符串,甲从中任选出一个串(即选出每个串的概率相同为 ...

  5. AI学习吧-公钥私钥、沙箱环境

    公钥私钥 公钥.私钥 可以互相解密 应用:数字签名和加密数据 数字签名:使用私钥加密,公钥解密 加密数据:使用公钥加密,私钥解密泄密时:当有人拿走了你的公钥,你可以到CI证书中心,使用你的私钥和公钥办 ...

  6. epoll(二)

    epoll概念 epoll对文件描述符的操作方式有两种工作模式:LT模式(Level Trigger,水平触发) 和ET模式(Edge Trigger,边缘触发). LT模式:当epoll_wait检 ...

  7. Memcached 快速入门

    Memcached简介 Memcached是一个专门用来做缓存的服务器,而且缓存的数据都在内存中.Memcached就相当于一个Dictionary键值对集合,保存的是键值对,然后根据key取valu ...

  8. python之requests urllib3 连接池

    0.目录 1.参考 2. pool_connections 默认值为10,一个站点主机host对应一个pool (4)分析 host A>>host B>>host A pag ...

  9. 【译】你应该了解的JavaScript数组方法

    让我们来做一个大胆的声明:for循环通常是无用的,而且还导致代码难以理解.当涉及迭代数组.查找元素.或对其排序或者你想到的任何东西,都可能有一个你可以使用的数组方法. 然而,尽管这些方法很有用,但是其 ...

  10. C# 之设计原则

    代码也需要有秩序,就像世界需要秩序,基于SOLID architecture principles. 一.SOLID原则 S.O.L.I.D.是一组面对面向对象设计的最佳实践的设计原则.术语来自Rob ...