我在处理字符编码方面遇到了困难。我正试图抓取以下网址:
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,但事情可能是错误的。
答案 0 :(得分:7)
�字符来自串联:
response.on('data', function(chunk) {
str += chunk;
});
这会使用default encoding
of utf8
将每个chunk
转换为String
。 Buffer
中任何无效的UTF-8序列都会丢失,并在此时被�取代。
您希望将chunk
作为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);
});
答案 1 :(得分:2)
如果您将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');
});
答案 2 :(得分:1)
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();