• node的api使用——URL——get方法——网页爬虫——node事件——path路径——判断文件类型——fs四种异步封装——客户端文件验证发送


    URL

    新建URL对象

    const url=require("url");
    var myUrl=new URL("http://10.9.63.202:3005?name=牛牛");
    console.log(myUrl);
    
    • 1
    • 2
    • 3
    URL {
      href: 'http://10.9.63.202:3005/?name=%E7%89%9B%E7%89%9B',
      origin: 'http://10.9.63.202:3005',
      protocol: 'http:',
      username: '',
      password: '',
      host: '10.9.63.202:3005',
      hostname: '10.9.63.202',
      port: '3005',
      pathname: '/',
      search: '?name=%E7%89%9B%E7%89%9B',
      searchParams: URLSearchParams { 'name' => '牛牛' },
      hash: ''
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    URL对象.searchParams获取search内容

    var url =require("url"); 
    var str=new URL("https://www.163.com:4400/news/index.html?a=1&b=2#c");
    console.log(str.searchParams);
    console.log(str.searchParams.get("a"));
    
    ==============================================
    输出:
    URLSearchParams { 'a' => '1', 'b' => '2' }
    1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    合并路径

    var url,{resolve} =require("url"); 
    var c=resolve("http://localhost:4000","news");
    console.log(c)
    
    =================
    输出
    http://localhost:4000/news
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    解析url编码格式方法

    decodeURIComponent()
    encodeURIComponent()
    
    • 1
    • 2

    parse:解析路径信息

    const url = require('url')
    const urlString = 'https://www.baidu.com:443/ad/index.html?id=8&name=牛牛#tag=1101'
    const parsedStr = url.parse(urlString)
    console.log(parsedStr)
    
    • 1
    • 2
    • 3
    • 4
    Url {
      protocol: 'https:',
      slashes: true,
      auth: null,
      host: 'www.baidu.com:443',
      port: '443',
      hostname: 'www.baidu.com',
      hash: '#tag=1101',
      search: '?id=8&name=牛牛',
      query: 'id=8&name=牛牛',
      pathname: '/ad/index.html',
      path: '/ad/index.html?id=8&name=牛牛',
      href: 'https://www.baidu.com:443/ad/index.html?id=8&name=牛牛#tag=1101'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    爬虫实现基础

    初始化工程

    node中的 GET 请求获取 和前端的AJAX类似,但是不需要考虑通信中的跨域这样就可以成为一个爬虫的基础环境成立。
    GET 主要用于请求远程服务的文件

    http中的get方法和request方法

    var {get,request} = require("https");
    //解构:注意这两个方法在https下可以单独使用其方法
    console.log(get,request);
    ============================
    [Function: get] [Function: request]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    get方法:参数一:请求路径,回调函数

    var {get,request} = require("https")
    
    
    get("https://www.smzdm.com/homepage/headline",async function(result){
         /*result  InCommingMessage  请求对象*/
         /*从参数的使用也可推断出他是请求体对象*/
        var data = await getData(result);
        console.log(data);
    })
    
    function getData(req){
        return new Promise((resolve,reject)=>{
            var _data = "";
            req.on("data",_chunk=> _data+= _chunk);
            req.on("end",()=>{
                try{
                    _data = JSON.parse(_data);
                }catch(e){}
                resolve(_data)
            });
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    总结:
    get: 网页通常不含有请求的get方式,直接写入地址,请求就可以了
    request : request 通常包含请求的数据发送还有请求的写入。既可以解决get问题也可以解决post问题。

    • 如果要解决post问题时,需要发送数据,这时候需要给请求中设置headers属性,增加Content-Length
    • 属性值就是 Buffer.byteLength(data)
    • request会返回一个对象,只有使用end发送数据后才可以获取

    网页 爬虫代码

    var http = require("http");
    var {get}=require("https");
    http.createServer(async (req,res)=>{
        res.writeHead(200,{
            "Access-Control-Allow-Origin":"*",
            "Content-Type":"text/html;charset=utf-8"
        });
    
       console.log(req.url.substr(1));//https://www.smzdm.com/homepage/headline
       console.log(await getProxydata(req.url.substr(1)));
    
    }).listen(3000);
    
    function getData(req){
        return new Promise((resolve,reject)=>{
            var _data='';
            req.on("data",(_chunk)=> _data += _chunk);
            req.on("end",()=>{
                try{
                    _data = JSON.parse(_data);
                }catch(e){}
                resolve(_data)
            })
        })
    }
    /*通过一次代理请求*/
    function getProxydata(url){
        return new Promise((resolve,rejcet)=>{
            /* get获取其他网页数据 */
            get(url,async (req)=>{
                resolve(await getData(req))
            })
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <script>
            var xhr = new XMLHttpRequest();
            xhr.addEventListener("load",loadHandler);
            xhr.open("GET","http://localhost:3000/"+"https://www.smzdm.com/homepage/headline");
            xhr.send();
    
            function loadHandler(e){
    
            }
        </script>
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    事件

    在node中不能操作bom和dom
    但是node自己封装了一套事件的触发:
    给对象添加事件;
    通过-来添加事件;

    var Event = require("events");
    var evt = new Event();
    evt.on("abc",()=>{
        console.log("aoaoaoo");
    })
    evt.emit("abc")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    但与ecms不同的是,触发事件可以传入参数;执行的函数就可以利用参数,到那时参数是逐个的传入,不能解构!!!,
    事件也可以继承
    事件传参

    var Event = require("events");
    var evt = new Event();
    evt.on("abc",(o)=>{
        console.log("aoaoaoo",o);
    })
    evt.emit("abc",{a:1,B:2})
    /* aoaoaoo { a: 1, B: 2 } */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    删除事件,和事件函数:就不能写匿名函数了

    var Event = require("events");
    var evt = new Event();
    evt.on("abc",handler);
    function handler(o){
        console.log("aoaoaoo",o);
        evt.off("abc",handler);
    }
    evt.emit("abc",{a:1,B:2})
    evt.emit("abc",{a:1,B:2})//不再执行
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    事件只执行一次.once

    var Event = require("events");
    var evt = new Event();
    evt.once("abc",handler);
    function handler(o){
        console.log("aoaoaoo",o);
    }
    evt.emit("abc",{a:1,B:2})
    evt.emit("abc",{a:1,B:2})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    path

    路径主要是为了解决本地路径的拼接所需要的一个方法集
    引入path

    var path = require('path');
    
    • 1

    path.join
    方法使用平台特定的分隔符作为定界符将所有给定的 path 片段连接在一起,然后规范化生成的路径。

    var path = require('path');
    var str=path.join('/foo', 'bar', 'baz/asdf');
    console.log(str);/* \foo\bar\baz\asdf */
    
    • 1
    • 2
    • 3

    path.dirname
    返回路径中目录名

    var path = require('path');
    var str=path.join('/foo', 'bar', 'baz/asdf.txt');
    console.log(path.dirname(str));/* \foo\bar\baz */
    
    • 1
    • 2
    • 3

    path.extname
    返回路径中的扩展名

    var path = require('path');
    var str=path.join('/foo', 'bar', 'baz/asdf.txt');
    console.log(path.extname(str));/* .txt */
    
    • 1
    • 2
    • 3

    path.parse
    将字符串对象转换为对象

    var path = require('path');
    var str=path.join('/foo', 'bar', 'baz/asdf.txt');
    console.log(path.parse(str));
    
    ==============
    输出:
    {
      root: '\\',
      dir: '\\foo\\bar\\baz',
      base: 'asdf.txt',
      ext: '.txt',
      name: 'asdf'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    path.format
    将path对象转换为字符串

    var path = require('path');
    var str=path.join('/foo', 'bar', 'baz/asdf.txt');
    var obj=path.parse(str);
    console.log(path.format(obj))/* \foo\bar\baz\asdf.txt */
    
    • 1
    • 2
    • 3
    • 4

    __dirname和__filename
    本地全局的当前文件夹地址和全局的当前文件路径和文件名
    __dirname:当前这个js所在路径
    __filename:当前这个js文件的目录

    var path = require('path');
    console.log(__dirname);/* E:\--\-----第二阶段\练习\0822\nodeBase */
    var str = path.join(__dirname,"/c.text");
    console.log(str);/* E:\--\-----第二阶段\练习\0822\nodeBase\c.text */
    
    console.log(__filename);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    path.resolve()获取当前文件的文件夹路径

    var path = require("path")
    console.log(path.resolve());/* E:\-----\第二阶段\练习\0822\nodeBase */
    
    • 1
    • 2

    注意的是在使用nodeTS中ES6模块化时,__dirname不能使用,需要使用path.resolve()

    path.basename获取当前路径下的文件名称

    var str = path.basename("http://www.163.com/a.txt");
    console.log(str);/* a.txt */
    
    
    var str=path.basename("c:/a/b/c.txt");
    console.log(str);/* a.txt */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    判断文件类型的MIME 类型

    npm i mime
    或者在pack.json中添加:

     "dependencies": {
        "mime":"^3.0.0"
      },
    
    • 1
    • 2
    • 3

    引入:var mime = require("mime"); console.log(mime);
    MIME 类型例如: “txt/html"

    var mime = require("mime");//获取MiMie类型插件
    console.log(mime.getType("C:/a/b/c/d.txt"));/* text/plain */
    
    • 1
    • 2

    fs

    原生的javascript没有操作这个文件的权利。但是nodejs有,对文件的操作。
    但是这种fs提供的对文件的操作全是异步的操作。需要通过回调函数来去获取,输出之类的,但是为了更快的操作异步,node提供了一套更快的内容;

    var fs = require("fs")
    var fsp = require("fs/promises");//异步的fs
    
    • 1
    • 2

    fs.mkdir 异步方法
    创建文件夹

    var fs = require("fs")
    fs.mkdir('logs', (err) => {//参数只有一个
    	console.log('done.')
    })
    ./logs和上面的一样表示在当前目录下建立文件夹
    ../logs和表示在当前目录上一级建立文件夹
    fs.mkdir('./logs', (err,resolut) => {
        console.log(err,resolut)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    fs.mkdir 异步方法
    删除文件夹

    fs.rmdir('logs', () => {
        console.log('done.')
    })  
    
    • 1
    • 2
    • 3

    封装一个mkdir,rmdir的prmoise的函数

    var fs = require("fs")
    
    function mkdir(url) {
        return new Promise((reslove, reject) => {
            // fs.mkdir(url,err=>{
            //     console.log("done");
            // })
            fs.rmdir('logs', () => {
                console.log('done.')
            })
        })
    }
    
    async function init(url) {
        await mkdir(url);
    }
    init("logs");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    fs.existsSync 同步方法
    判断路径是否存在
    返回一Boolean值

    if (fs.existsSync('path')) {
    	console.log('该路径已存在');
    }
    
    • 1
    • 2
    • 3

    fs.readFile

    异步读取文件.注意地址中会有转义字符,所以\使用的时候要多敲一个

    • 异步读取方法1
    var fs=require("fs");
    fs.readFile("绝对路径/相对路径","utf8",function(err,data){
        console.log(err);
        console.log(data.toString());
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 异步读取方法2
    npm install mz
    
    • 1
    var fs = require('mz/fs');
    fs.readFile('./e.txt', 'utf-8').then(result => {
        console.log(result);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 异步读取方法3,封装;
    var fs=require("fs");
    function readFile(url,mime){
        return new Promise((resolve,reject)=>{
            fs.readFile(url,mime,(err,resoult)=>{
                if(err) resolve(err);
                resolve(resoult);
            })
        })
    }
    async function init(url,mime){
        var data = await readFile(url,mime);
        console.log(data);
    }
    init("./e.txt",'utf-8');
    
    
    (async () => {
        console.log(await readFile("./e.txt",'utf-8'))
    })()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 异步读取方法4;
    const fsP = require('fs').promises
    const fsp = fsP.readFile('./e.txt', 'utf-8').then((result) => {
        console.log(result)
    })
    
    console.log(fsp)/* Promise {  } */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    fs.readdir读取当前路径下的文件和文件夹,返回一个数组

    fs.readdir(__dirname,(err,result)=>{
        console.log(result);
    })
    
    • 1
    • 2
    • 3

    fs.stat读取文件和文件夹的详细信息
    异步result.isFile()判断这个文件是文件还是文件夹。

    fs.stat(path.join(__dirname,"e.txt"),(err,result)=>{
        console.log(result);
    })
    
    • 1
    • 2
    • 3

    简易封装httpfs.readfilemime文件类型验证同步发送文件数据到客户端。(未完)

    var mime = require("mime");
    var fs = require("fs");
    var http = require("http");
    const path = require("path");
    
    init();
    async function init(){
        http.createServer(async (req,res)=>{
            var url = req.url.split("?")[0].substr(1);
            res.writeHead(200,{
                "Content-Type":mime.getType(url)+";charset=utf-8",
                "Access-Control-Allow-Origin": "*" //CORS 允许谁跨域访问    
            })
            console.log(mime.getType(url));
            var data = await readFile(path.join(path.resolve(),url));   
            res.end(data)
        }).listen(3000)
    }
    function readFile(name){
        return new Promise((resolve,reject)=>{
            if(/text/.test(mime.getType(name))){
                fs.readFile(name,'utf8',(err,data)=>{
                   if(err)  resolve(null)
                   resolve(data)
                })
            }else{
                fs.readFile(name,(err,data)=>{
                    if(err)  resolve(null)
                    resolve(data)
                })
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    文件资源管理器:

    ar mime = require("mime");
    var fs = require("fs");
    const path = require("path");
    
    function readFile(name){
        return new Promise((resolve,reject)=>{
            fs.readFile(name,(err,resoult)=>{
                if(err) resolve(err);
                resolve(resoult);
            })
        })
    }
    
    /* 传入当前路径 */
    function readDir(name){
        return new Promise((resolve,reject)=>{
            fs.readdir(name,(err,result)=>{
                if(err) resolve(null)
                else resolve(result.map(item=>path.join(name,item)));
            })
        })
    }
    function statFile(name){
        return new Promise((resolve,rejsct)=>{
            fs.stat(name,(err,result)=>{
                if(err) resolve(null);
                else if(result.isFile()) resolve(true);
                else resolve(false);
            })
        })
    }
    
    async function readPath(path){
        var list = await readDir(path);
        list.forEach(async (item)=>{
            var t = await statFile(item);
            if(!t && t!==null){
                await readPath(item)
            }else{
                var data = await readFile(item);
                console.log(data+"");
            }
        })
    }
    
    function init1(path){
        readPath(path)
    }
    init1(__dirname);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
  • 相关阅读:
    【python笔记】第十节 闭包与装饰器
    电力电子转战数字IC20220820day65——uvm实战1B
    [PwnThyBytes 2019]Baby_SQL - 代码审计+布尔盲注+SESSION_UPLOAD_PROGRESS利用
    DDP、pytorch的分布式 torch.distributed.launch 训练说明
    可道云kodbox上传出错解决办法
    了解一下Ubuntu Linux
    csharp开发日常之Activator.CreateInstance构造函数生成实例
    Qt创建动态库给C#调用,通过回调完成交互
    6. 【图的存储结构】邻接矩阵、邻接表 、十字链表 、邻接多重表
    【每日一题】—— C. Yarik and Array(Codeforces Round 909 (Div. 3))(贪心)
  • 原文地址:https://blog.csdn.net/m0_46672781/article/details/126470479