Nodejs http.request()方法返回内容中文乱码问题

Nodejs http.request()方法返回内容中文乱码问题

写了一段代码想获取传入url页面的title:

exports.getTitleFrom = function getTitleFrom(response,url){
    var title;
    if(url && url.trim()){
        var options = {method:'GET', port:80};
        url = url.trim();
        if(url.indexOf('http://') == 0) url = url.replace('http://', '');
        if(url.indexOf('/') != -1){
            options.hostname = url.substring(0, url.indexOf('/'));
            options.path = url.substring(url.indexOf('/'));
        } else {
            options.hostname = url;
        }
        var req = http.request(options, function(res){
            res.on('data', function (chunk) {
                var match = chunk.toString().match('<title>[^\0]*</title>');
                if(match && match.length > 0){
                    title = match[0].replace('<title>', '').replace('</title>', '');
                    console.log('获取到对应的URL与TITLE:');
                    console.log(url + ' <-> ' + title);
                    response.send({title : title});
                }
            });
        });
        req.on('error', function(e) {
            console.log('problem with request: ' + e.message);
        });
        req.end();
    }
}

经测试英文网页没问题,中文也有一些没问题,但是就是另外一些站点如百度、淘宝等返回的内容都是中文乱码的。想请教一下如何解决?


5 回复

Node.js http.request() 方法返回内容中文乱码问题

在使用 Node.js 的 http.request() 方法请求网页内容时,如果目标网页包含中文字符,可能会遇到乱码问题。这通常是因为服务器返回的内容编码没有正确处理。

示例代码及解决方案

以下是修改后的代码示例,其中添加了对响应内容编码的检测和转换:

const http = require('http');

exports.getTitleFrom = function getTitleFrom(response, url) {
    var title;
    if (url && url.trim()) {
        var options = { method: 'GET', port: 80 };
        url = url.trim();
        if (url.indexOf('http://') === 0) url = url.replace('http://', '');
        
        if (url.indexOf('/') !== -1) {
            options.hostname = url.substring(0, url.indexOf('/'));
            options.path = url.substring(url.indexOf('/'));
        } else {
            options.hostname = url;
        }

        const req = http.request(options, function (res) {
            let rawData = '';
            res.setEncoding('utf8'); // 设置正确的编码
            
            res.on('data', function (chunk) {
                rawData += chunk;
            });

            res.on('end', function () {
                try {
                    // 尝试将内容转换为字符串并提取 title
                    const content = Buffer.from(rawData, res.headers['content-encoding'] || 'utf8').toString();
                    const match = content.match(/<title>[^<]*<\/title>/);
                    if (match && match.length > 0) {
                        title = match[0].replace('<title>', '').replace('</title>', '');
                        console.log('获取到对应的URL与TITLE:');
                        console.log(url + ' <-> ' + title);
                        response.send({ title: title });
                    }
                } catch (e) {
                    console.error(`解析错误: ${e.message}`);
                }
            });
        });

        req.on('error', function (e) {
            console.log('请求出现问题: ' + e.message);
        });

        req.end();
    }
}

关键点解释

  1. 设置正确的编码

    res.setEncoding('utf8');
    

    这行代码确保从服务器接收到的数据被正确解码为 UTF-8 编码。

  2. 处理响应数据

    res.on('data', function (chunk) {
        rawData += chunk;
    });
    

    将每次接收到的数据块累积起来,最后进行统一处理。

  3. 提取 title

    const content = Buffer.from(rawData, res.headers['content-encoding'] || 'utf8').toString();
    const match = content.match(/<title>[^<]*<\/title>/);
    

    使用正则表达式从内容中提取 <title> 标签,并将其转换为字符串。

通过这些调整,可以有效地解决中文乱码问题,确保从服务器获取的中文内容能够正确显示。


var match = chunk.toString().match(’<title>[^\0]*</title>’); 问题在这里,chunk是buffer,不一定是完整的字符串。遇到中文,可能存在一个文字的半个字符丢失的情况,所以乱码咯。

十分感谢!

在使用 http.request() 方法请求包含中文字符的网页时,可能会遇到中文乱码问题。这是因为默认情况下,Node.js 并没有指定返回数据的编码格式。为了解决这个问题,你需要在接收到响应时设置正确的编码。

以下是修改后的代码示例:

const http = require('http');

exports.getTitleFrom = function getTitleFrom(response, url) {
    var title;
    if (url && url.trim()) {
        var options = { method: 'GET', port: 80 };
        url = url.trim();
        if (url.indexOf('http://') === 0) url = url.replace('http://', '');
        if (url.indexOf('/') !== -1) {
            options.hostname = url.substring(0, url.indexOf('/'));
            options.path = url.substring(url.indexOf('/'));
        } else {
            options.hostname = url;
        }

        var req = http.request(options, function (res) {
            // 设置接收数据的编码格式
            res.setEncoding('utf-8');
            
            let rawData = '';
            res.on('data', function (chunk) {
                rawData += chunk;
            });

            res.on('end', function () {
                var match = rawData.match(/<title>[^<]*<\/title>/);
                if (match && match.length > 0) {
                    title = match[0].replace('<title>', '').replace('</title>', '');
                    console.log('获取到对应的URL与TITLE:');
                    console.log(url + ' <-> ' + title);
                    response.send({ title: title });
                }
            });
        });

        req.on('error', function (e) {
            console.log('problem with request: ' + e.message);
        });

        req.end();
    }
}

解释:

  1. 设置编码:通过调用 res.setEncoding('utf-8'),你可以确保响应数据以 UTF-8 编码进行处理。
  2. 累积数据:使用一个变量 rawData 来累积所有分块数据,而不是在每次 data 事件中直接处理。
  3. 匹配逻辑:将匹配逻辑移至 end 事件回调中,以确保接收到完整的数据后进行匹配。

这样可以确保在处理含有中文字符的数据时不会出现乱码问题。

回到顶部