Я пытаюсь прочитать фид по следующему URL-адресу:
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);
});
Есть ли способ получить данные независимо от кодировки? Как мне подойти к этому?
Сложная часть - передать кодировку как null, чтобы получить буфер вместо строки.
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);
});
Опять же, в контексте последующего вопроса "
Есть ли способ обнаружить кодировку?
"Определить", надеюсь, вы имеете в виду, найдите декларацию. (... в отличие от угадывания. Если вам нужно угадать, у вас есть сообщение об ошибке). Заголовок ответа HTTP Content-Type является основным способом передачи кодировки (если применимо к типу MIME). Некоторые типы MIME позволяют объявлять кодировку внутри контента, так как серверы вполне справедливо полагаются на это.
В случае вашего ответа в 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);
});
Вы пропустили концепцию кодирования символов.
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
- экземпляр Buffer
в node.js. Согласно официальной документации, есть только
'ascii' - только для 7-разрядных данных ASCII. Эта кодировка выполняется быстро и будет разделять верхний бит, если он установлен.
'utf8' - Юникод-кодированные многобайтовые символы. Многие веб-страницы и другие форматы документов используют UTF-8.
'utf16le' - 2 или 4 байта, кодированные в Юникоде символы, закодированные в маленьком конце. Поддерживаются суррогатные пары (U + 10000 до U + 10FFFF).
'ucs2' - Псевдоним 'utf16le'.
'base64' - кодировка Base64. При создании буфера из строки эта кодировка также будет правильно принимать "URL и имя файла", как указано в RFC4648, раздел 5.
'latin1' - способ кодирования буфера в однобайтную закодированную строку (как определено IANA в RFC1345, стр. 63, как блок дополнения Latin-1 и коды управления C0/C1).
'binary' - Псевдоним для 'latin1'.
'hex' - кодировать каждый байт в виде двух шестнадцатеричных символов.
в настоящее время поддерживается node.js include. Для использования кодировки не нативно поддерживаемые node.js, использование Iconv, Iconv-лайт или других библиотек, чтобы захватить таблицу отображения символов. Это очень похоже на этот ответ.
Accept-Language
подразумевает языки, принятые клиентом. en-gb
представляет English (United Kingdom)
, но не китайский. Китайский - zh-cn, zh
, согласно RFC 7231.