2014-10-27 90 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