在下载XML Feed时处理多种编码scheme
我正尝试通过以下url阅读Feed:
http://www.chinanews.com/rss/scroll-news.xml
使用请求模块 。 但我得到的东西有 ʷ ) ( й )
。
在回顾XML
我发现编码被设置为<?xml version="1.0" encoding="gb2312"?>
但试图设置编码为gb2312
,我得到未知的编码错误。
request({ url: "http://www.chinanews.com/rss/scroll-news.xml", method: "GET", headers: { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "Accept-Encoding": "gzip, deflate", "Host": "www.chinanews.com", "Accept-Language": "en-GB,en-US;q=0.8,en;q=0.6" }, "gzip": true, "encoding": "utf8" }, (err, resp, data) => { console.log(data); });
有没有一种方法,我可以得到的数据不考虑它的编码? 我应该如何处理这个?
你错过了字符编码的概念。
var iconv=require('iconv-lite'), request=require('request'); request({ url: "http://www.chinanews.com/rss/scroll-news.xml", method: "GET", headers: { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "Accept-Encoding": "gzip, deflate", "Host": "www.chinanews.com", "Accept-Language": "" // client accept language }, gzip: true, encoding: null // or 'ascii' }, (err, resp, body) => { console.log(iconv.decode(Buffer.from(body, 'ascii'), 'gb2312')); });
chunk
是node.js中的一个Buffer
实例。 根据官方文件 ,只有
'ascii' – 仅用于7位ASCII数据。 这种编码速度很快,如果设置的话,会去掉高位。
'utf8' – 多字节编码的Unicode字符。 许多网页和其他文档格式使用UTF-8。
'utf16le' – 2或4个字节,小端编码的Unicode字符。 支持代理对(U + 10000至U + 10FFFF)。
'ucs2' – 'utf16le'的别名。
'base64' – Base64编码。 从string创build缓冲区时,此编码也将正确接受RFC4648第5节中指定的“URL和文件名安全字母”。
'latin1' – 将缓冲区编码为单字节编码string(由IANA在RFC1345,第63页定义的拉丁语-1补充块和C0 / C1控制码)的一种方法。
'binary' – 别名为'latin1'。
'hex' – 将每个字节编码为两个hex字符。
目前由node.js include 支持 。 要使用node.js 本身不支持的编码,请使用iconv , iconv-lite或其他库来获取字符映射表。 这与这个答案非常相似。
Accept-Language
意味着客户Accept-Language
。 en-gb
代表English (United Kingdom)
,但不代表中文。 根据RFC 7231 zh-cn, zh
中文是zh-cn, zh
。
棘手的部分是传递编码为null来获得一个缓冲区而不是一个string。
encoding
– 编码用于响应数据的setEncoding。 如果为null
,则正文返回为Buffer
。
– 请求
var request = require('request'); var legacy = require('legacy-encoding'); var requestSettings = { method: 'GET', url: 'http://www.chinanews.com/rss/scroll-news.xml', encoding: null, }; request(requestSettings, function(error, response, body) { var text = legacy.decode(body, 'gb2312'); console.log(text); });
再次,在后续问题的背景下,“
有没有办法检测编码?
通过“发现”,我希望你的意思是,find声明。 (…而不是猜测,如果你必须猜测,那么你的通信失败了。)HTTP响应头Content-Type是传递编码(如果适用于MIMEtypes)的主要方式。 一些MIMEtypes允许在内容中声明编码,因为服务器非常合适。
在你的RSS响应的情况下。 服务器发送Content-Type:text/xml
。 这是没有编码覆盖。 内容的XML声明是<?xml version="1.0" encoding="gb2312"?>
XML规范有查找这样一个声明的程序。 它基本上等于用不同的编码读取,直到XML声明变得可以理解,然后用声明的编码重新读取。
var request = require('request'); var legacy = require('legacy-encoding'); var convert = require('xml-js'); // specials listed here: https://www.w3.org/Protocols/rfc1341/4_Content-Type.html var charsetFromContentTypeRegex = (/charset=([^()<>@,;:\"/[\]?.=\s]*)/i).compile(); var requestSettings = { method: 'GET', url: 'http://www.chinanews.com/rss/scroll-news.xml', encoding: null, }; request(requestSettings, function(error, response, body) { var contentType = charsetFromContentTypeRegex.exec(response.headers['content-type']) var encodingFromHeader = contentType.length > 1 ? contentType[1] : null; var doc = convert.xml2js(body); var encoding = doc.declaration.attributes.encoding; doc = convert.xml2js( legacy.decode(body, encodingFromHeader ? encodingFromHeader : encoding)); // xpath /rss/channel/title console.log(doc.elements[1].elements[0].elements[0].elements[0].text); });