【问题标题】:NodeJS. Dealing with � characters encoding节点JS。处理�字符编码
【发布时间】:2014-12-22 04:49:19
【问题描述】:

我在处理字符编码时遇到了困难。我正在尝试抓取以下网址:

http://www.google.com/movies?near=Montreal&date=0

我的代码如下所示:

var http = require('http');
var url = require('url');
var Iconv  = require('iconv').Iconv;

var location = 'montreal';

var googleMovies = url.parse("http://www.google.com/movies?near=" + location);

var req = http.request(googleMovies, function(response) {
    var str = '';
    response.on('data', function(chunk) {
        str += chunk;
    });
    response.on('end', function() {

        var iconv = new Iconv('latin1', 'UTF-8');
        str = iconv.convert(str).toString();

        console.log(str);
    });
});
req.end()

我第一次尝试不使用:

    var iconv = new Iconv('latin1', 'UTF-8');
    str = iconv.convert(str).toString();

但这导致了 � 字符。

我已经测试了本页上面列出的源代码:

http://nlp.fi.muni.cz/projects/chared/

它似乎将其检测为 latin1,但情况可能是错误的。

【问题讨论】:

    标签: node.js character-encoding


    【解决方案1】:

    如果您将User-Agent 设置为桌面浏览器,则HTML 中的元标记和响应标头中的Content-Type 会将charset 设置为UTF-8 而不是latin1。示例:

    var dest = url.parse('http://www.google.com/movies?near=montreal');
    dest.headers = {
      'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36',
    };
    
    http.get(dest, function(response) {
      var str = '';
    
      response.on('data', function(chunk) {
        str += chunk;
      }).on('end', function() {
        console.log(str);
      }).setEncoding('utf8');
    });
    

    【讨论】:

    • 此解决方案也有效。看起来编码取决于用户代理(这是正常的吗?)。我更喜欢@Jonathan Lonowski 的解决方案,因为它更好地解释了字符集转换,而您的解决方案专注于修复此特定服务的源输出。
    • 它可能比它应该的更常见,但是许多后端检查User-Agent 并相应地改变行为(例如,旅游网站根据您的操作系统更改价格,网站只发送已知可与浏览器一起使用的资源等)。
    【解决方案2】:

    �字符来自串联:

    response.on('data', function(chunk) {
        str += chunk;
    });
    

    这会将每个chunk 转换为带有default encoding of utf8StringBuffers 中任何作为 UTF-8 无效的序列都将丢失并在此时替换为 �。

    您需要将chunks 保留为Buffers,直到convert() 之后。它们可以在Array 中收集并与Buffer.concat() 结合使用。

    var chunks = [];
    
    response.on('data', function (chunk) {
        chunks.push(chunk);
    });
    
    response.on('end', function () {
        var iconv = new Iconv('latin1', 'UTF-8');
        var str = iconv.convert(Buffer.concat(chunks)).toString();
        console.log(str);
    });
    

    【讨论】:

      【解决方案3】:

      Buffer 的默认编码是 UTF-8,这是一种可变宽度编码系统。 ASCII 范围之后的字符使用多个字节进行编码。如果您接收到特定于 latin1 的字符(代码点 > 127),它们将设置第一位,UTF-8 解码器会将其视为多字节字符,最终导致未映射的代码点(显示为 �) .

      iconv 有一个流解码器,您可以将响应流通过管道传输到该解码器。

      http.request(googleMovies, function (response) {
          var iconv = new Iconv('latin1', 'UTF-8');
          response.pipe(iconv).pipe(process.stdout);
          //or response.pipe(iconv).on('data', console.log);
      }).end();
      

      【讨论】:

      • 您的解决方案看起来很优雅,我认为它应该可以工作,但由于某种原因它没有。你能测试一下它是否适合你吗?
      • 我是console.logging 在end 事件而不是data 事件中收到的参数。管道到process.stdout 也应该可以工作。
      • 谢谢,现在它可以工作了,它将数据转储到标准输出中。你有没有办法把它变成一个可用于进一步操作的字符串?我需要一个“str”变量来进一步使用它。我发现的所有关于“输入字符串”的解决方案都类似于@Jonathan Lonowski 的示例。
      • 您必须使用与之前相同的方法:监听data,concat,然后使用end 上的字符串。只有这一次您必须将侦听器附加到 iconv
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      • 2021-04-11
      • 2017-05-12
      • 1970-01-01
      • 1970-01-01
      • 2022-12-10
      相关资源
      最近更新 更多