node学习系列--二(爬虫,express,中间件)

上边我们学习了node一些基础知识,相信对node有了一定的认知。下面继续学习node知识

九、使用nodejs做一个简易的爬虫

  • 思路:1、获取目标网站

    ​ 2、分析网站内容

    ​ 3、获取有效信息,下载,存储操作

    1、使用http模块获取网站信息,由于内存空间有限,因此数据的存储通过分批次的从内容中存入硬盘,所以有了数据流的概念。

    let http=require('http');
    let fs=require('fs');
    const url='http://www.baidu.com';
    http.get(url,(res)=>{
      let rawData='';
        // 数据分段,只有接收到数据就会触发data,chunk为每次的数据片段
      res.on('data',(chunk)=>{
        rawData+=chunk.toString('utf8');
        console.log('--------', '数据流');
      })
        // 数据流传输完毕
      res.on('end',()=>{
          // 数据传输完后,将其保存在当前目录下的baidu.html文件里。
        fs.writeFileSync('./baidu.html', rawData);
        console.log('数据流结束');
      })
    }).on('error', (err)=>{
      console.log(err);
      console.log('请求错误')
    })
    
    • 上述内容没有安全验证
    let http=require('http');
    let fs=require('fs');
    const url='http://www.baidu.com';
    http.get(url,(res)=>{
      // 安全判断
      const {statusCode}=res; // 状态码
      const contentType=res.headers['content-type']; // 文件类型
      let err=null;
      if(statusCode!==200){
        err=new Error("请求状态失败");
      }else if(!/^text\/html/.test(contentType)){
        err=new Error("文件类型不是网页")
      }
      if(err){
        res.resume(); //重置缓存
        return;
      }
      // 数据分段,只有接收到数据就会触发data,chunk为每次的数据片段
      let rawData='';
      res.on('data',(chunk)=>{
        rawData+=chunk.toString('utf8');
        console.log('--------', '数据流');
      })
      // 数据流传输完毕
      res.on('end',()=>{
        fs.writeFileSync('./baidu.html', rawData);
      })
    }).on('error', (err)=>{
      console.log(err);
      console.log('请求错误')
    })
    

    2、爬虫完善,需要对爬下来的内容进行正则匹配,匹配我们需要的东西,此时,自己写一个正则表达式比较的麻烦,因此,使用cheerio插件来完成。

    npm install cheerio --save
    

    用法举例:

    let cheerio=require('cheerio');
    const $=cheerio.load('<div><img src="http://wwww.baidu.com/img/1.jpg"/></div>');
    console.log($('img').attr('src'));
    // 输出结果为:http://wwww.baidu.com/img/1.jpg
    

    有多个img标签,以及获取标签中汉字举例:

    let cheerio = require("cheerio");
    const $ = cheerio.load(
        '<div><img src="http://wwww.baidu.com/img/1.jpg"/><p>我是p元素</p><img src="http://wwww.baidu.com/img/2.jpg"/></div>'
    );
    $("img").each((index,el)=>{
      console.log($(el).attr("src"));
    })
    console.log($("p").text());
    // 输出结果为:
    http://wwww.baidu.com/img/1.jpg
    http://wwww.baidu.com/img/2.jpg
    我是p元素
    

    最后附上爬取图片保存到本地代码:

    let http=require('http');
    let fs=require('fs');
    let path=require('path')
    let request = require('request');
    let cheerio = require("cheerio");
    const url='http://www.hello.com/';
    fs.readdir('./',(err,data)=>{
      let isNo=false;
      for(let i=0;i<data.length;i++){
        if(data[i]==='images'){
          isNo=true;
        }
      }
      if(!isNo){
        fs.mkdirSync('./images', (err)=>{
          if(err){
            console.log('创建文件夹失败');
          }else{
            console.log('创建文件夹成功');
          }
        });
      }
    });
    http.get(url,(res)=>{
      // 安全判断
      const {statusCode}=res; // 状态码
      const contentType=res.headers['content-type']; // 文件类型
      let err=null;
      if(statusCode!==200){
        err=new Error("请求状态失败");
      }else if(!/^text\/html/.test(contentType)){
        err=new Error("文件类型不是网页")
      }
      if(err){
        res.resume(); //重置缓存
        console.log(err);
        return;
      }
      // 数据分段,只有接收到数据就会触发data,chunk为每次的数据片段
      let rawData='';
      res.on('data',(chunk)=>{
        rawData+=chunk.toString('utf8');
        console.log('--------', '数据流');
      })
      // 数据流传输完毕
      res.on('end',()=>{
      const $=cheerio.load(rawData);
        $('img').each((index,el)=>{
          request($(el).attr("src")).pipe(fs.createWriteStream(path.join(__dirname,'images','images'+index+'.jpg')));
        })
      })
    }).on('error', (err)=>{
      console.log(err);
      console.log('请求错误')
    })
    

十、使用express快速搭建node服务器

1、 模块的引用(三方外置模块)从当前目录开始找,找不到往上级目录开始找,最后依然找不到,报错找不到。

2、 使用步骤:

  • 引入express模块
  • 实例化express
  • 监听

3、windwos获取ip地址用ipconfig命令,linux用ifconfig

4、服务器相关:

  • 服务器是一台电脑
  • 服务器软件(apach, iis, tomcat, node, ngnix)注:apach用于php的,ngnix用于linux系统的
  • 服务器ip和端口号

外网:ip地址对应对应的主机,port对应某个程序

5、api接口的组成要素:

  • ip 地址
  • port 端口号
  • pathname 路径
  • 请求方式
  • 接收用户的数据,数据格式由后端制定
  • 返回值

6、使用get方式获取提交的数据,使用req.query来获取该提交的数据,post方式获取的数据,使用req.body来获取post提交的数据。

7、express不能解析消息体,因此使用post方式提交数据时候,需要使用第三方插件来进行解析body消息体。插件名字叫做bodyparser插件

8、使用postman来测试post接口

const express = require('express');
const bodyParser = require('body-parser')
const app = express() // express实例化
// parse application/x-www-form-urlencoded   处理表单格式post提交数据
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json    处理以json格式提交的数据,处理后req.body能取到值
app.use(bodyParser.json())
// post请求方式
app.post('/user/work', (req, res)=>{
  const {name} = req.body;
  if(name==="领哥"){
    res.send({success: true, worker: '领哥'});
  }
})
// get请求方式
app.get('/user/login', (req, res)=>{
  if(req.query.name==='hello'&&req.query.ps==='123'){
    res.send({success: "登录成功"});
  }else{
    res.send({err: "登录失败"});
  }
})
app.listen(3000, ()=>{
  console.log('服务在3000端口运行')
})

9、 express路由,将数据分层处理,不用将所有内容都写在一个文件里,这样将不同功能内容分开处理。

例如:项目中有两个模块,分别是食物模块和用户模块,使用router将他们在两个文件中书写,便于区分。

// 主入口
const express = require('express');
const app = express() // express实例化
const userRouter=require('./router/user.js')
const foodRouter=require('./router/food.js')
app.use('/user', userRouter);
app.use('/food', foodRouter);
app.listen(3000, ()=>{
  console.log('服务在3000端口运行')
})
// 和主入口文件同级的router文件夹下的user.js文件
const express=require('express');
const router=express.Router();

router.get('/name', (req, res)=>{
  res.send({name: 'ling'});
})
router.get('/age', (req, res)=>{
  res.send({age: 22});
})
router.get('/login', (req, res)=>{
  res.send({success: true});
})

module.exports=router;
// 和主入口文件同级的router文件夹下的food.js文件
const express= require('express');
const router = express.Router();

router.get('/del', (res, req)=>{
  req.send('删除食物')
})

router.get('/add', (res, req)=>{
  req.send('添加食物')
})
module.exports=router

在浏览器中访问 localhost:3000/user/name得到{name: ‘ling’}

10、middlewear中间件,也称作是拦截器。

  • 内置中间件 static-静态资源目录

  • 自定义中间件 (全局中间件,局部中间件)

    • 全局中间件声明格式
    app.use(pathname, (req,res,next)=>{})
    
    • 局部中间件格式
    app.get(pathname,function1,function2)
    // 其中function1要有三个参数,function2有两个参数
    app.get(pathname,(req,res,next)=>{},(req,res)=>{})
    
  • 第三方中间件 例如:body-parse

  • 如果中间件作用于根目录可以简写为:

app.use((req,res,next)=>{})
// 其中body-parse在解析json格式时候使用方式是app.use(bodyParser.json()),因此是中间件

使用场景用于重复性的内容操作,比如token验证,每一个模块都验证一下挺麻烦,使用middlewear验证一次,所有的都使用,大大简化操作。可以自定义一个中间件,用法如下(全局的):

const express = require('express');
const app = express(); // express实例化
app.use('/', (req, res, next)=>{
  console.log('中间件');
  const {token}=req.query;
  if(token){
    next()
  }else{
    res.send('缺少token');
  }
});
app.get('/user', (req, res)=>{
  res.send('请求user');
});
app.listen(3000, ()=>{
  console.log('服务在3000端口运行')
})
// 访问localhost:3000/user?token=1235得到   “请求user”

有两个参数,第一个是路径,什么路径下需要拦截,比如所有的都要拦截,使用 ‘/’ 因为所有的接口都要走 ‘/’ 路径。第二个为回调函数,此回调函数有三个参数,最后一个为next,用法和vue路由守卫类似。

使用局部中间件实现:

const express = require('express');
const app = express(); // express实例化
app.get('/user', (req, res, next)=>{
  console.log('function1')
  next()
},
(req, res)=>{
  console.log('function2')
  res.send('放行');
});
app.listen(3000, ()=>{
  console.log('服务在3000端口运行')
})
// 在浏览器输入localhost:3000/user   返回  "放行" 并在控制台有输出function1, function2
  • 静态资源目录static,用于声明服务器默认访问的路径,类似apache中的www

    const express = require('express');
    const path = require('path');
    const app = express(); // express实例化
    app.use(express.static(path.join(__dirname, './hello')));
    console.log(path.join(__dirname, './hello'))
    app.listen(3000, ()=>{
      console.log('服务在3000端口运行')
    })
    

    此时访问域名:3000将直接访问指定的静态资源目录下的index.html文件,同样的,可以使用中间件指定路径

    const express = require('express');
    const path = require('path');
    const app = express(); // express实例化
    app.use('public', express.static(path.join(__dirname, './hello')));
    console.log(path.join(__dirname, './hello'))
    app.listen(3000, ()=>{
      console.log('服务在3000端口运行')
    })
    // 此时访问域名:3000/public将会访问指定静态路径下的index.html文件。
    

10、mongodb非关系型数据库相关

  • 首先,安装mongodb数据库,启动cmd之后输入mongod使用命令行启动数据库命令。然后不要关闭此cmd,新开一个cmd,输入mongo回车,如果报c/data/db找不到,需要去对应哪个文件下新建文件夹,然后,就可以操作数据了,show dbs查看数据库。
  • mongoose是node操作mongodb的插件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值