Работа с несколькими схемами кодирования при загрузке канала XML

1

Я пытаюсь прочитать фид по следующему 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);
});

Есть ли способ получить данные независимо от кодировки? Как мне подойти к этому?

Теги:
httprequest
encoding

2 ответа

0

Сложная часть - передать кодировку как 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); 
});
  • 0
    Есть ли способ, которым я мог бы определить кодировку? Существует множество страниц, которые необходимо проанализировать сценарию, и все они могут иметь разные схемы кодирования. Так что я никогда не узнаю заранее о кодировке
0

Вы пропустили концепцию кодирования символов.

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.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню