axios爬取网页中文乱码

3,453 阅读1分钟

本菜鸡用 axios 写了一个爬虫,原网页是gb2312编码的,最后输出的中文是乱码。

百度了一圈:

  • 如果网站可以返回utf-8编码的网页,那么万事大吉。设置headers如下:
headers:{
    'Content-Type': 'text/html;charset=utf-8'
}
  • 如果网站不能返回utf-8编码的网页,可以用iconv-lite进行转码

使用 iconv-lite 进行转码

首先需要安装:

npm i iconv-lite

这是一个大神用js写的一个转码库(github链接

安装后尝试对得到的数据解码:

axios.get(pageUrl).then(function(res){
	let result = iconv.decode(res.data, 'gb2312');
	console.log(result);
});

然后你会得到一个警告🙃,中文依旧乱码:

Iconv-lite warning: decode()-ing strings is deprecated. Refer to https://github.com/ashtuchkin/iconv-lite/wiki/Use-Buffers-when-decoding

原因:根据网上查到的资料,axios 会将请求到的结果会转换成utf-8格式(但是我这里实际上是gb2312),而这种转换是有损的(也就是无法转换回gb2312)。已经损坏的数据无法再正确转码,所以我们需要得到没有经过转换的原始数据。

正确用法

配置 axios 直接拿 buffer 数据,iconv-lite 可以直接解析buffer数据:

axios.get(pageUrl, {
    responseType: 'arraybuffer'
}).then(function(res){
	let result = iconv.decode(res.data, 'gb2312');
	console.log(result);
});

最后得到的中文是没有乱码的,下面是我的爬虫代码:

let axios = require('axios');
let url = require('url');
const fs = require('fs');
const iconv = require('iconv-lite');
let httpUrl = "https://www.dy2018.com/html/bikan/";


// 正则表达式
const reg = /<td height="26">.*?<b>.*?<a href="(.*?)".*?>(.*?)<\/a>.*?<\/b>.*?<\/td>/igs;
let testRes, result = [];
let baseUrl = url.parse(httpUrl).protocol + "//" + url.parse(httpUrl).host;
console.log(baseUrl)
axios.get(httpUrl, {
    responseType: 'arraybuffer'
}).then(function(res){
    console.log(res.data);
    let r = iconv.decode(res.data, 'gb2312');
    while(testRes = reg.exec(r)){
        result.push({
            title: testRes[2],
            url: url.resolve(baseUrl, testRes[1])
        })
    }
    console.log(result);
    // 将爬取数据另存为json文件
    fs.writeFile('ret.json', JSON.stringify(result,null,2), 'utf-8', (err) => {
        if (err) throw err;
        console.log('done');
    });
}).catch(function(e){
    console.log(e);
});