使用 http 模块来实现简单的爬虫及资源压缩

所谓爬虫,就是用来爬取网页的内容。

在 nodejs 中,可以使用 http 和 https 模块来实现简单爬虫。会使用到一个模块,cheerio 模块。该模块可以将返回的字符串转为 jQuery 中的 $ 对象,从而可以使用 jQuery 中的各种方法。

const https = require('https');
const cheerio = require('cheerio');

// 爬虫的思路很简单,其实就是发送 http 请求,去请求那个页面
// 接下来拿到响应的内容,然后筛选有用的信息

https.get('https://tuijian.hao123.com/hotrank',(req)=>{
    let data = ''; // 装回来的数据
    req.on('data',(chunk)=>{
        data += chunk
    });
    req.on('end',()=>{
        filter(data);
    })
})

function filter(data){
    let result = []; // 存放筛选后的数据
    const $ = cheerio.load(data); // 将字符串传递给 cheerio 模块,会生成一个 jQuery 对象,我们就可以在服务器端使用 jQuery 方法
    const temp_arr = $('[monkey="ss"]').find('.point-bd').find('.point-title')
    temp_arr.each((index,item)=>{
        result.push($(item).text());
    })
    console.log(result);
}

数据IO操作相关模块

这里会涉及到 Buffer、Stream 文件流。

Buffer

在最早的时候,js在浏览器里面运行,也就是说意味着 js 是在客户端运行,所以,那个时候,js只能操作字符串。随着node的出现,js 可以做服务器端的开发,所以也就有操作二进制数据的需求,Buffer 可以让我们操作二进制数据。

我们简单介绍一下Buffer 相关的方法。

Buffer相当于是在内存里面开辟了一段空间。我们程序员可以手动的去指定这段内存空间的大小。

let buf1 = new Buffer.alloc(5);
console.log(buf1); // <Buffer 00 00 00 00 00>

往buffer里面写入数据,如下:

let buf1 = new Buffer.alloc(5);
buf1.write('a');
console.log(buf1);

再来看一个buffer的示例:

let buf = new Buffer.alloc(26);
for(let i=0;i<26;i++){
    buf[i] = i + 97;//小a的按下去的码
}
console.log(buf.toString());
Stream 文件流

流的概念

所谓流,就像水流一样。例如,我们在网上在线看电影,或者下载电影,不是说电影这个资源一瞬间就达到我们客户端,而是以流的形式,一点一点过来的。这里其实就涉及到了流的概念。

理想的方式,读一部分,写一部分,不管文件有多大,只要时间允许,总会处理完。

在 nodejs 中,就允许我们来操作这个流。

模块名为 stream,提供了几个常用的事件:

  • data:当有数据可读时触发
  • end:没有更多的数据可读时会触发
  • error:发生错误的时候,会触发
  • finish:所有数据写入底层的时候会触发

在stream中,常见的流有2块:

  • readable:可读流
  • writable:可写流

前面我们学习了fs模块,在fs中,读取文件的api是readFile,但是这个api其实是nodejs已经给你封装过一次,其实读取文件的底层,仍然是采用流的操作来读取。接下来,我们来通过流的形式来读取文件:

const fs = require('fs');
// 创建一个可读流
const rs = fs.createReadStream('./test.txt');
rs.setEncoding('utf8');
rs.on('data',(chunk)=>{
    console.log(chunk);
    console.log('-----------------------------');
})
可写流

通过可写流来复制文件。

const fs = require('fs');
// 创建一个可读流
const rs = fs.createReadStream('./test.txt');
// 创建一个可写流
const ws = fs.createWriteStream('./test2.txt');
rs.setEncoding('utf8');//使用这个不会乱码
rs.on('data',(chunk)=>{
    ws.write(chunk);
})
rs.on('end',()=>{
    console.log('复制完成!');
})
使用pipe方法来处理流

使用 pipe 方法,当我们处理大型文件,效率就要高一些,它相当于在两个流文件之间建立了一个管道。

接下来我们来使用 pipe 方法简化上面的文件操作的步骤:

const fs = require('fs');
// 创建一个可读流
const rs = fs.createReadStream('./test.txt');
// 创建一个可写流
const ws = fs.createWriteStream('./test3.txt');
rs.setEncoding('utf8');
rs.pipe(ws);

资源压缩

在做web 开发的时候,服务器端向客户端返回数据,往往这个数据需要将其压缩,

(1)要明确浏览器端是否接受压缩文件

在浏览器发送http请求的时候,请求头里面会有一个键值对,Accept-Encoding,表示我这个浏览器可以接收的编码格式,如果里面包含 gzip,说明该浏览器可以接收压缩文件

(2)nodejs里面如何对文件进行压缩

会使用nodejs里面的一个内置模块zlib。

const fs = require('fs');
const zlib = require('zlib');

// 创建一个压缩文件的对象,这个对象负责压缩文件
const gzip = zlib.createGzip();
const rs = fs.createReadStream('./test.txt'); // 创建了一个可读流
const ws = fs.createWriteStream('./test.txt.gz'); // 创建了一个可写流

rs.pipe(gzip).pipe(ws);

解压缩其实就是压缩的一个反向操作。

const zlib = require('zlib');

// 创建一个压缩文件的对象,这个对象负责压缩文件
const gunzip = zlib.createGunzip();
const rs = fs.createReadStream('./test.txt.gz');
const ws = fs.createWriteStream('./test10.txt');

rs.pipe(gunzip).pipe(ws);

(3)实际应用

在实际开发中,我们需要首先判断用户的浏览器是否支持压缩文件,示例代码如下:

const fs = require('fs');
const zlib = require('zlib');
const http = require('http');

const filePath = './index2.html'; // 假设这是我要向客户端返回的文件

http.createServer((req,res)=>{//创建服务器
    // 获取 accept-encoding 的值
    const acceptEncoding = req.headers['accept-encoding'];//请求头的键值对
    if(acceptEncoding.indexOf('gzip')!=-1){//判断浏览器是否支持压缩;indeOf是找到键值对的下标
        // 进入 if,说明存在 gzip 字符,也就是说,支持压缩
        res.writeHead(200,{'Content-type':'gzip'})// 修改响应头里面的某些键值对,gzip压缩格式
        const gzip = zlib.createGzip();//zlib.createGzip()返回方法给gzip
        fs.createReadStream(filePath).pipe(gzip).pipe(res);//把客户端返回的文件弄成可读流,然后弄成压缩文件给响应体渲染出去
    } else {
        // 说明不支持
        fs.createReadStream(filePath).pipe(res);//直接把可读流渲染出去
    }
}).listen(3000);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值