Nodejs中使用iconv从gb2312转utf-8经常出错

Nodejs中使用iconv从gb2312转utf-8经常出错

/**

  • 采集39问答网 */

var n = require(‘needle’) var $ = require(‘jquery’) var iconv = require(‘iconv’).Iconv; n.get(‘http://ask.39.net/browse/313-2-1.html’,{encoding:'gb2312’},function(error,response,body){ //console.log(response.statusCode) var buf = new Buffer(body,‘binary’); var content = new iconv(‘gb2312’,‘UTF8’).convert(buf).toString() //采集到的链接 var href = {} $(content).find(’.bt’).each(function(index,value){ href[$(value).attr(‘href’)] = $(value).attr(‘href’) }) console.log(href) })

经常出现下面的错误。

         throw errnoException('EILSEQ', 'Illegal character sequence.');
                ^
Error: Illegal character sequence.
    at errnoException (D:\node.js\node_modules\iconv\lib\iconv.js:137:13)
    at convert (D:\node.js\node_modules\iconv\lib\iconv.js:85:17)
    at Iconv.convert (D:\node.js\node_modules\iconv\lib\iconv.js:108:12)
    at D:\node.js\cj39.js:11:46
    at handle_output (D:\node.js\node_modules\needle\lib\needle.js:227:16)
    at Object.Needle.response_end (D:\node.js\node_modules\needle\lib\needle.js:242:7)
    at IncomingMessage.<anonymous> (D:\node.js\node_modules\needle\lib\needle.js:187:16)
    at IncomingMessage.EventEmitter.emit (events.js:117:20)
    at _stream_readable.js:883:14
    at process._tickCallback (node.js:415:13)

4 回复

标题:Nodejs中使用iconv从gb2312转utf-8经常出错

内容: 在使用Node.js处理网页数据时,经常会遇到编码转换的问题。比如在这个例子中,我们尝试从GBK(GB2312)编码的网页内容转换为UTF-8编码,但是经常遇到错误。下面是一个具体的示例代码及其分析。

/**
 * 采集39问答网
 */
const needle = require('needle');
const $ = require('cheerio'); // 使用cheerio替代jquery,因为jQuery主要用于浏览器环境
const iconv = require('iconv-lite');

needle.get('http://ask.39.net/browse/313-2-1.html', { encoding: null }, function (error, response, body) {
    if (error) {
        return console.error(error);
    }

    // 使用iconv-lite将Buffer转换为字符串
    const decodedBody = iconv.decode(new Buffer(body), 'gb2312');

    // 采集到的链接
    const href = {};
    $('a.bt', decodedBody).each(function () {
        href[this.attribs.href] = this.attribs.href;
    });
    
    console.log(href);
});

问题解析: 原代码中的错误主要在于new Buffer(body, 'binary')这一步。首先,Buffer构造函数的binary参数已被弃用,应该直接使用Buffer.from()。其次,iconv库在处理转换时可能会抛出异常,尤其是当输入数据不符合预期的编码格式时。

解决方案:

  1. 使用iconv-lite代替原生的iconv,因为它更加稳定且易于使用。
  2. 在获取响应体时,设置encoding: null以确保获取的是原始二进制数据。
  3. 使用iconv.decode()方法将Buffer对象解码为字符串。

通过这些改进,可以有效避免非法字符序列的错误,并正确地进行编码转换。


(iconv:大人,这不是小人的错呀,错的是大…大…,错的是这个世界。) 吐槽完毕,先赞一个,这是近期看到规格最完备的求助帖,有代码有报错,难得,虽然代码贴重复一部分,虽然犯的错比较低级。。。

如果确定抓取的网页编码是gb2312,那么needle抓取后没必要转码。

var buf = new Buffer(body,'binary');
var content = new iconv('gb2312','UTF8').convert(buf).toString()

这2句可以删除,body本身已经是utf-8,可console.log(body)验证。why?见needle文档response options的decode选择说明:https://github.com/tomas/needle#response-options 另外{encoding:'gb2312'}的作用是指定post数据的编码,与response无关。

吧这两行代码删除掉console出来的是乱码。必须要转,但是转码经常会出现错误。

在将 GB2312 编码转换为 UTF-8 编码时遇到 “Illegal character sequence” 错误,通常是由于 iconv 模块在处理过程中遇到了无法识别的字符。以下是一个修改后的示例代码,使用了 iconv-lite 模块,这是一个更现代且维护得更好的库。

首先,你需要安装 iconv-liteneedle

npm install needle iconv-lite

然后,你可以使用以下代码来解决这个问题:

const needle = require('needle');
const iconvLite = require('iconv-lite');

needle.get('http://ask.39.net/browse/313-2-1.html', { encoding: null }, function (error, response, body) {
    if (error) {
        console.error(error);
        return;
    }

    // 将 GB2312 编码的数据转换为 Buffer
    const buffer = Buffer.from(body, 'binary');

    // 使用 iconv-lite 进行编码转换
    const utf8Body = iconvLite.decode(buffer, 'gb2312');

    // 解析 HTML 并提取链接
    const $ = require('cheerio').load(utf8Body);
    const hrefs = {};
    $('.bt').each((index, value) => {
        const link = $(value).attr('href');
        if (link) {
            hrefs[link] = link;
        }
    });

    console.log(hrefs);
});

解释

  1. 使用 iconv-lite: iconv-lite 是一个更加可靠和易于使用的库,用于处理字符编码转换。
  2. 传递 encoding: null: 当使用 needle 获取数据时,设置 encoding: null 可以确保返回的数据是二进制格式。
  3. 解码: 使用 iconv-lite.decode 方法将 GB2312 编码的 Buffer 转换为 UTF-8 字符串。
  4. 解析 HTML: 使用 cheerio 库来解析 HTML 并提取链接。

这样可以避免 iconv 模块可能遇到的非法字符序列问题,并且代码更简洁和易读。

回到顶部