nodejs基本操作

node.js

导出模块

一个js文件就是一个模块,模块内部的所有变量,对象,方法对外界都不可见。如果想暴露出去让别人用,就需要导出模块。语法如下:

	module.exports = {
	    a :a,
	    foo
	}

Demo

  • 暴露的模块,mathuilts.js

    	function getSum(x, y) {
    	    return x + y;
    	}
    
    
    ​	
    ​	const APP_NAME = "nodejs"function getGap(x, y) {
    	    return x - y;
    	}
    	
    	// getSum   getSum()
    	// 如果要暴露的是方法,一定不能添加(),直接声明方法名即可
    	module.exports = {
    	    getSum,
    	    name: APP_NAME,
    	    getGap
    	}
    
    
  • 使用模块

   // 在引入自定义模块的时候,相对路径要使用标准的写法,也就是要添加./var mathutils = require("./mathutils");
   ​	
   ​	// var sum = getSum(1, 2);
   ​	console.log(mathutils.name)
   ​	console.log(mathutils.getSum(1,2))
   ​	console.log(mathutils.getGap(1,2))

crypto模块

NodeJs的crypto模块提供了哈希,加密相关的功能支持。

哈希算法:MD5,SHA1,SHA256,Hmac

哈希算法用来对数据进行签名,确定数据的唯一性,以及是否被篡改。由于其过程不可逆,也常常用来对用户密码进行加密。

	let crypto = require("crypto");
	
	let data = "你好,这是一个加密的原文数据";
	
	// 指定算法
	// let hash = crypto.createHash("md5");
	// let hash = crypto.createHash("sha1");
	// let hash = crypto.createHash("sha256");
	// let hash = crypto.createHash("sha512");
	// 传入原文
	// hash.update(data)
	// 计算hash
	// let digest = hash.digest("hex");
	// console.log(digest)

Hmac是基于key和hash的认证算法。它在上面哈希算法的基础上,再传入一个key。只要key变化,即使输入同样的数据也会得到不同的结果。可以将Hmac理解为随机数增强的哈希算法。

	// let salt = "salt";
	//
	// let hmac = crypto.createHmac("md5", salt);
	// hmac.update(data)
	// let digest = hmac.digest("hex");
	// console.log(digest)
	let key = "helloworld";

对称加密算法:AES

AES是一种常用的对称加密算法,加解密都用同一个密钥。

AES加密:

	let data = '123456'
	let password = 'baby'
	const cipher  = crypto.createCipher('aes192', password)
	let encrypted = cipher.update(data, 'utf-8', 'hex')
	encrypted += cipher.final('hex')
	console.log(encrypted);

AES解密:

	const decipher = crypto.createDecipher('aes192', password)
	let encrytedData = 'd1b992fe45e85e43f3b73e0716874bc8'
	let decrypted = decipher.update(encrytedData, 'hex', 'utf-8')
	decrypted += decipher.final('utf-8')
	console.log(decrypted);

event模块

大多数 Node.js 核心 API 都采用惯用的异步事件驱动架构,其中某些类型的对象(触发器)会周期性地触发命名事件来调用函数对象(监听器)。例如,fs.ReadStream会在文件被打开时触发事件;stream 会在数据可读时触发事件。

用法如下:

	const EventEmitter = require('events')
	class MyEmitter extends EventEmitter{}
	
	const myEmitter = new MyEmitter()
	// 注册xxx事件
	myEmitter.on('aaa', (a)=>{
	    console.log('aaa事件被触发,参数:'+a);
	})
	// 1秒钟之后触发aaa事件,并传递参数
	setTimeout(()=>{
	    myEmitter.emit('aaa', 'aaaaaa')
	},1000)

当你想设计一个模块,它具有在某个条件下执行某个操作的功能,那么event模块就派上用场了。例如:你想设计一个用户注册模块,当用户注册成功之后给用户发送一个email。

【案例】美女图片爬虫项目

功能需求

  • 爬取http://www.27270.com/ent/meinvtupian/网站页面,处理GBK乱码的问题;
  • 从中提取出图片数据,并下载图片

第三方模块简介

iconv-lite : 用于处理gbk编码问题,iconv-lite

cheerio : 用于数据提取 cheerio

	let cheerio = require("cheerio");
	
	let html = `
	<ul id="fruits">
	  <li class="apple">Apple</li>
	  <li class="orange">Orange</li>
	  <li class="pear">Pear</li>
	</ul>
	`;
	
	// 加载代码片段
	let $ = cheerio.load(html);
	// let text = $("li.apple").text();
	// console.log(text)
	
	// 使用类似jQuery的语法获取多个对象,并转为数组
	let lis = $("ul li").toArray();
	// 遍历数组
	for (let i = 0; i < lis.length; i++) {
	    // 将DOM对象转为jQuery对象
	    let jEle = $(lis[i]);
	    // 获取数据
	    console.log(`class:${jEle.attr("class")},text:${jEle.text()}`)
	}

### 代码

	let http = require("http");
	let iconv = require("iconv-lite");
	let cheerio = require("cheerio");
	let fs = require("fs");
	let path = require("path");
	
	// 1.请求目标页面,处理了中文乱码
	http.get("http://www.27270.com/ent/meinvtupian/", res => {
	
	    let data = [];
	    res.on("data", chunk => {
	        data.push(chunk)
	    })
	
	    res.on("end", () => {
	        let html = iconv.decode(Buffer.concat(data), 'gb2312');
	        // 2.解析页面,查找图片的地址和图片的标题
	        let imgData = parseHTML(html);
	        // 3.下载图片
	        downloadImgs(imgData)
	    })
	})
	
	// 2.解析页面,查找图片的地址和图片的标题
	function parseHTML(html) {
	
	    let $ = cheerio.load(html);
	
	    let arr = $("div.MeinvTuPianBox>ul>li>a>i>img").toArray();
	
	    let imgData = [];
	    for (let i = 0; i < arr.length; i++) {
	        let jEle = $(arr[i]);
	
	        imgData.push({
	            src: jEle.attr("src"),
	            title: jEle.attr("alt")
	        })
	    }
	
	    return imgData;
	}
	
	// 3.下载图片
	function downloadImgs(imgData) {
	    imgData.forEach(imgObj => {
	
	        http.get(imgObj.src, res => {
	
	            let filePath = path.join("imgs", imgObj.title+path.extname(imgObj.src))
	            let writeStream = fs.createWriteStream(filePath);
	            res.pipe(writeStream)
	
	        })
	    })
	}

重构

实现爬虫功能,需要实现抓取页面,提取数据,下载图片这些子功能。而这些功能的调用都是当某个步骤完成了,才能执行下一个步骤,因此我们可以使用event模块来重构整个项目.

	let EventEmmiter = require("events");
	let http = require("http");
	let iconv = require("iconv-lite");
	let cheerio = require("cheerio");
	let fs = require("fs");
	let path = require("path");


​	
​	class GirlSpider extends EventEmmiter {// 1.请求目标页面,处理了中文乱码downloadHTML() {
​	        http.get("http://www.27270.com/ent/meinvtupian/", res => {
​	
​	            let data = [];
​	            res.on("data", chunk => {
​	                data.push(chunk)})
​	
​	            res.on("end", () => {let html = iconv.decode(Buffer.concat(data), 'gb2312');// 页面下载成功以后,触发事件this.emit("downloadHTMLSuccess", html)})})}
​	
​	    // 2.解析页面,查找图片的地址和图片的标题parseHTML(html) {let $ = cheerio.load(html);
	
	        let arr = $("div.MeinvTuPianBox>ul>li>a>i>img").toArray();
	
	        let imgData = [];
	        for (let i = 0; i < arr.length; i++) {
	            let jEle = $(arr[i]);
	
	            imgData.push({
	                src: jEle.attr("src"),
	                title: jEle.attr("alt")
	            })
	        }
	        // 页面解析成功以后,触发事件
	        this.emit("parseHTMLSuccess", imgData)
	    }
	
	    // 3.下载图片
	    downloadImgs(imgData) {
	        imgData.forEach(imgObj => {
	
	            http.get(imgObj.src, res => {
	
	                let filePath = path.join("imgs", imgObj.title + path.extname(imgObj.src))
	                let writeStream = fs.createWriteStream(filePath);
	                res.pipe(writeStream)
	
	            })
	        })
	    }
	
	    // 初始化方法
	    init() {
	        // 添加监听
	        this.on("downloadHTMLSuccess", (html) => {
	            this.parseHTML(html)
	        })
	
	        this.on("parseHTMLSuccess", (imgData) => {
	            this.downloadImgs(imgData)
	        })
	        // 开始下载页面
	        this.downloadHTML()
	    }
	}
	
	let girlSpider = new GirlSpider();
	girlSpider.init()

MongoDB

介绍

MongoDB是一个由C++编写的高性能的文档型数据库,为web应用提供可扩展数据库解决方案。它和MySQL的区别如下:

数据库MongoDBMySQL
存储单元按collection存储,一个collection中包含很多document按table存储,一个table中包含很多的记录
数据格式要求非常灵活,document可以存储任意json格式的数据row中的每一列的数据类型都是限定死的,不够灵活
数据字段扩展对数据字段的扩展零消耗数据扩展字段有很大的消耗.比如:上万条数据再增加一列就要消耗几十秒
事务支持在4.0之后版本支持,目前已经支持 支持
读写性能一般情况下,读写性能都要略高于MySQL性能平稳

具体区别如下:

下载与安装

下载地址


ORM - mongoose

无论是mysql还是mongodb,传统的与数据库交互的方式都是按照他们提供的API来写代码。它们提供的API往往不是很容易理解,而且难以记忆,如果传错了参数,写错一个符号都要查文档。就像上面我们学习的数据库API一样。

ORM框架允许我们面向对象操作,不需要记忆任何的数据库API,只需要操作对象即可,由框架底层去调用数据库API,这样就大大提高了程序员的开发效率。不过既然多了一层封装,肯定要损失一点点的性能,可以忽略不计。

在NodeJS中,mongodb最好的orm框架就是mongoose

安装mongoose
npm install mongoose --save

如果你本机没有安装nodejs驱动,会自动安装nodejs驱动,因为mongoose依赖nodejs驱动了。

文档参考:mongoose官方文档

连接数据库
	const mongoose = require('mongoose')
	//连接数据库
	mongoose.connect("mongodb://127.0.0.1:27017/test");
	const db = mongoose.connection;
	
	db.on('error', console.error.bind(console, 'connection error:'));
	db.once('open', function() {
	    console.log('连接mongodb成功!');
	});

模型定义

mongoose使用schema来描述数据的格式,字段,规则,有了schema之后可以生成model来操作数据。

	const mongoose = require('mongoose')
	const schema = mongoose.Schema({
	    name: {
	      type: String,
	      required: true
	    },
	    age: Number,
	    fav: [String],
	});
	
	module.exports = mongoose.model('user', schema)
增删改查

直接查看文档中Model相关API。


	await User.create()
	await User.findOne()
	await User.updateOne()
	await User.deleteOne()
	//增加条件操作符: 所有支持的操作符:https://docs.mongodb.com/manual/reference/operator/query/
	await User.findOne({
	    age: {$gt:11},
	    tags:{$in:[1,2,3]}
	 })

高级查询
	//分页查询
	await Book.find().skip(10).limit(10)
	
	//排序和字段映射
	await User.find().skip(0).limit(2).sort({age:-1}).select("-hobby")

Schema和数据类型

https://mongoosejs.com/docs/guide.html

所有的方法

https://mongoosejs.com/docs/api.html#Model

操作符

https://docs.mongodb.com/manual/reference/operator/query/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值