2014-10-27 81 views
1

我在处理字符编码时遇到困难。我想凑以下网址:NodeJS。处理 字符编码

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的,但事情可能是错误的。

回答

5

字符来自级联:

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

此将每个chunkStringdefault encoding of utf8Buffer中的任何无效的UTF-8序列都将丢失,并在此处由replaced代替。

你要离开chunk S作为Buffer s,至该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); 
}); 
+0

解决方案开箱即用。谢谢 ! – 2014-10-27 13:35:47

2

如果您将User-Agent设置为桌面浏览器的HTML,则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'); 
}); 
+0

此解决方案也适用。它看起来像编码取决于用户代理(这是正常的?)。我更喜欢@Jonathan Lonowski的解决方案,因为它更好地解释了字符集转换,而您的工作重点是修复此特定服务的源输出。 – 2014-10-27 13:43:06

+1

它比它应该更常见,但很多后端检查User-Agent并相应地改变行为(例如,旅行网站根据您的操作系统更改价格,只发送已知可与浏览器一起使用的资源的网站等)。 – mscdex 2014-10-27 14:26:41

1

A Buffer的默认编码是UTF-8,它是一种可变宽度编码系统。 ASCII范围后的字符使用多个字节进行编码。如果您接收到latin1特定的字符(codepoints> 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(); 
+0

您的解决方案看起来很优雅,我认为它应该可以工作,但由于某种原因它不适用。你可以测试,看看它是否适合你? – 2014-10-27 13:35:20

+0

我是'console.log'在'end'事件中收到的参数,而不是'data'事件。配管到'process.stdout'也应该有效。 – 2014-10-27 13:45:54

+0

谢谢,现在它工作,它将数据转储到标准输出。你有没有办法将这个变成可以用于进一步操作的字符串?我需要一个'str'变量来进一步处理它。我发现的有关“管道连接”的解决方案与@Jonathan Lonowski的例子类似。 – 2014-10-27 13:54:28