什么是端口

一台电脑可以部署多个服务器,根据端口不同找到不同的服务器。

默认的http端口为80端口。

web服务器读取网页并返回

  1. 使用http模块开启一个服务器
  2. 在服务器内部读取文件,将读取到的字符串内容作为服务器的响应返回
const http = require("http");
const fs = require("fs");
const path = require("path");
const server = http.createServer((req, res) => {
  // 拼接路径
  const filePath = path.join(__dirname, "index.html");
  fs.readFile(filePath, "utf-8", (err, data) => {
    if (err == null) {
      // 返回页面
      res.end(data);
    } else {
      res.end(err);
    }
  });
});
server.listen(8080, () => {
  console.log("成功开启");
});

image-20200702165449844

静态服务器的实现

静态服务器的流程

  1. 浏览器向服务器发起请求

  2. 服务器查询受否存在这个文件

    • 存在

      返回

    • 不存在

      返回默认404页面

静态服务器的实现

静态服务器实现与读取网页返回几乎一致,通过request.url可以获取用户访问的路径。

const http = require("http");
const fs = require("fs");
const path = require("path");
const server = http.createServer((req, res) => {
  // 得到用户请求的是哪一个页面
  console.log(req.url); // /pica.jpg
  var filePath = path.join(__dirname, "static", req.url);
  // 服务器存在嗅探功能,根据请求资源名字,能够得知请求类型。因此编码参数可以省略
  fs.readFile(filePath, (err, data) => {
    if (err == null) {
      res.end(data);
    } else {
      res.end(path.join(__dirname, "static", "404.html"));
    }
  });
});

server.listen(8080, () => {
  console.log("成功开启:http://127.0.0.1:8080");
});

image-20200702174739374

接收前端传来的get参数

get参数是与url拼接在一起的,因此可以使用url.parse方法解析字符串。

const http = require("http");
// 处理url
const url = require("url");

const server = http.createServer((req, res) => {
  //   res.end(req.url);
  /**
   * url.parse 解析通过get传来的参数
   * @param {string} req.url 待解析的url
   * @param {boolean} true 如果为true则返回一个对象
   * @returns {Object}
   */
  let urlObj = url.parse(req.url, true);
  console.log(urlObj.query);
  res.end(JSON.stringify(urlObj.query));
});
server.listen(8080, () => {
  console.log("成功开启");
});

image-20200702210042663

接收前端传来的post参数

接收post数据需要为请求体注册data事件与end事件。前者表示接收数据,回调函数内参数传入数据,函数体处理数据;后者表示接收完数据后调用的回调函数。

处理接收的数据使用querystring.parse可以将接收的数据转换为对象形式。

const http = require("http");
const querystring = require("querystring");
const server = http.createServer((req, res) => {
  let postData = "";
  // 时间处理程序,参数是传递过来的数据
  req.on("data", (chunk) => {
    postData += chunk;
  });
  req.on("end", () => {
    console.log(postData); //name=123&passwd=haha
    // 解析传来的参数数据
    let postObj = querystring.parse(postData); //{ name: '123', passwd: 'haha' }
    console.log(postObj);
  });
  res.end("sb");
});
server.listen(8080, () => {
  console.log("成功开启");
});

GET与POST的区别

GETPOST
传值通过url传值通过请求体(querystring)
数据大小相对较少将对较大
安全性相对较低相对较高
一般用途请求数据、获取数据提交数据

爬虫示例

使用第三方模块的步骤:

  1. 新建一个文件夹(非中文且不能与模块名相同)

  2. npm init -y 进行初始化

  3. 下载模块

    可以到npm官网搜索

  4. 使用模块

    参照模块说明文档

  1. 爬取丁香园的body数据

    const fs = require("fs");
    var Crawler = require("crawler");
    
    var c = new Crawler({
      maxConnections: 10,
      callback: function (err, res, done) {
        if (err) {
          console.log(err);
        } else {
          var $ = res.$;
          fs.writeFile("./temp/1.txt", $("body").text(), (err) => {
            if (err == null) {
              console.log("成功");
            }
          });
        }
        done();
      },
    });
    
    c.queue("https://ncov.dxy.cn/ncovh5/view/pneumonia");
    
  2. 爬取一张图片

    var Crawler = require("crawler");
    var fs = require("fs");
    
    var c = new Crawler({
      encoding: null,
      jQuery: false, // set false to suppress warning message.
      callback: function (err, res, done) {
        if (err) {
          console.error(err.stack);
        } else {
          fs.createWriteStream(res.options.filename).write(res.body);
        }
    
        done();
      },
    });
    
    c.queue({
      uri: "https://ae01.alicdn.com/kf/H21b5f6b8496141a1979a33666e1074d9x.jpg",
      filename: "./temp/test.jpg",
    });
    

npm命令的使用

  1. 安装当前目录下的项目所需要的所有依赖包npm install

  2. 如果下载过程中卡住,可以使用npm cache clean -f清除缓存

  3. 使用淘宝镜像

    参考地址:https://developer.aliyun.com/mirror/NPM?from=tnpm

pakeage与pakeage-lock的区别

  1. 使用npm5之前的版本,是不会生成package-lock.json这个文件的。

  2. npm5以后,包括npm5这个版本,才会生成package-lock.json文件

  3. 当使用npm安装包的时候,npm都会生成或書更新package-lock.json文件

    • npm5以后的版本,在安装包的时候,不需要加--save(s)参数,也会自动在package.json中保存依项

    • 当安装包的时候,会自动创建或更新package-jock.json文件

    • package-lock.json文件内保存了node_modules:中所有包的信息,包含这些包的名称、版本号、下地址。带来好处是,如果重新npm install的时候,就无逐个分析包的依赖项,因比会大大加快安装速度

    • package-lock.json文件名来看,Iock代表的是"锁定"的意思。它用来物定当前开发使用的版本号,防止npm install的时侯自动更新到了更新版本。因为新版本有可能会更新老的API,导数之前的代码出错

    • 原来的package.json文件只能定大版本,也就是版本号的第一位,并不能定后面的小版本,你每次npm install都是拉取的该大版本下的最新的版本,为了稳定性考虑我们几手是不敢随意升级依包的,这将导数多出来很多工作量,测试/适配等,所以package-lock.json文件出来了,当你每次安装一个依赖的候就定在你安装的这个版本。

使用express模块

GET与POST传参:

  • GET传参–接收参数

    只需要在请求体内直接通过request.query即可取到传参对象

  • POST参数–接收参数

    需要导入body-parser模块,首先对url进行转码,然后在请求体内可以通过request.body获取传参对象

创建一个简单的服务器

const express = require("express");
// 创建服务器
const app = express();

// 创建路由
app.get("/", (req, res) => {
  // 注意 使用express模块创建服务器,使用send作为相应
  res.send("Hello World!你好啊");
});
// 监听接口
app.listen(3000, () => {
  console.log(`Server running at  http://127.0.0.1:3000`);
});

创建一个静态资源服务器

创建静态资源可以设置静态目录app.use(express.static("PATH"));

const express = require("express");
// 创建服务器
const app = express();
// 设置静态目录
app.use(express.static("static"));
// 创建路由
app.get("/", (req, res) => {
  // 注意 使用express模块创建服务器,使用send作为相应
  res.send("Hello World!你好啊");
});
// 监听接口
app.listen(3000, () => {
  console.log(`Server running at  http://127.0.0.1:3000`);
});

实现一个简单的get接口

const express = require("express");

const app = express();

/**
 * 得到随机笑话
 * @date 2020-07-03
 * @param {string} "/joke" 请求地址
 * @param {function} (req,res) 请求与相应
 */
app.get("/joke", (req, res) => {
  let arr = ["第一个笑话", "第二个笑话", "第三个笑话"];
  let index = Math.floor(Math.random() * 3);
  res.send(arr[index]);
});

app.listen(3000);

返回JSON

返回json直接返回一个对象即可。

const express = require("express");

const app = express();

app.get("/food", (req, res) => {
  let arr = ["第一个笑话", "第二个笑话", "第三个笑话"];
  let index = Math.floor(Math.random() * 3);
  res.send({
    foodName: arr[index],
    price: 100,
    desc: "这是一个描述",
  });
});

app.listen(3000);

实现一个带有参数的GET接口

通过req.query可以获取传输的参数对象,然后取到具体的内容。

const express = require("express");

const app = express();

app.get("/getNickName", (req, res) => {
  // 接收参数
  let heroName = req.query.heroName;
  console.log(heroName);
  let heroNickName = "";
  let hero = {
    提莫: "迅捷斥候",
    李青: "盲僧",
    盖伦: "德玛西亚之力",
    亚索: "疾风剑豪",
  };
  if (hero[heroName] != undefined) {
    heroNickName = hero[heroName];
  } else {
    heroNickName = "暂无这个英雄的资料";
  }
  res.send(heroNickName);
});

app.listen(3000);

实现简单的POST接口

const express = require("express");

const app = express();
// 只需要将方式改为post即可
app.post("/sb", (req, res) => {
  res.send("sb");
});

app.listen(3000);

带参数的POST接口

在post请求中,无法使用req.query拿到请求的数据。所以拿到数据需要使用第三方模块body-parser模块。

  1. 将请求体解析

    app.use(bodyParser.urlencoded({ exrtended: false }));

  2. 通过req.body拿到请求的数据

    image-20200703115616895

const express = require("express");
const bodyParser = require("body-parser");

const app = express();
// 将请求体的数据解析
app.use(bodyParser.urlencoded({ exrtended: false }));
app.post("/login", (req, res) => {
  console.log(req.body);
  if (req.body.name == "123" && req.body.passwd == "123") {
    res.send("登录成功");
  } else {
    res.send("登录失败");
  }
});

app.listen(3000);

返回是json格式字符串的接口

使用express模块返回字符串默认为text/html格式,设置响应头后即可返回json格式的字符串。

const express = require("express");

const app = express();

app.get("/getFood", (req, res) => {
  res.setHeader("Content-Type", "text/json");
  res.send(
    `foodName:"红烧肉",
        price:100`
  );
});
app.listen(3000, () => {
  console.log("服务器已开启");
});

image-20200703142458941

POST传文件参数

post接收文件参数需要使用multer模块,然后将传过来的文件放在此模块创建的文件夹下。

请求第二个可选参数为接收文件的键值。通过req.file获取文件信息,通过req.body获取一同传输的文本信息。

const express = require("express");
const multer = require("multer");

const app = express();
// 创建一个uploads文件夹
var upload = multer({ dest: "uploads/" });
app.post("/register", upload.single("usericon"), (req, res) => {
  // 传过来的文件,参数名用usericon
  // 一起传过来的文本信息保存在req.body中
  console.log(req.file);
  console.log(req.body);
  res.send("sb");
});

app.listen(3000);

image-20200703145224424

image-20200703145231408