在下载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-Languageen-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); });