【问题标题】:Decoding a combination of windows-1252 and quoted printable HTML解码 windows-1252 和引用的可打印 HTML 的组合
【发布时间】:2018-03-29 08:31:38
【问题描述】:

我收到了一段表示 HTML 的文本,例如:

<html>\r\n<head>\r\n<meta http-equiv=3D\"Content-Type\" content=3D\"text/html; charset=3DWindows-1=\r\n252\">\r\n<style type=3D\"text/css\" style=3D\"display:none;\"><!-- P {margin-top:0;margi=\r\nn-bottom:0;} --></style>\r\n</head>\r\n<body dir=3D\"ltr\">This should be a pound sign: =A3 and this should be a long dash: =96 \r\n</body>\r\n</html>\r\n

从 HTML &lt;meta&gt; 标记中我可以看到这段 HTML 应该被编码为 Windows-1252。

我正在使用 node.js 来解析这段带有cheerio 的文本。然而,使用https://github.com/mathiasbynens/windows-1252 对其进行解码并没有帮助:windows1252.decode(myString); 会返回相同的输入字符串。

我认为的原因是该输入字符串已经在标准 node.js 字符集中进行了编码,但它实际上 表示 一段windows-1252 编码的 HTML(如果这有意义的话?)。

检查= 前面的那些奇怪的十六进制数字,我可以看到有效的windows-1252 代码,例如:

  • 这个=\r\n 和这个\r\n 应该以某种方式代表Windows 世界中的回车,
  • =3D: HEX 3D 是 DEC 61 这是一个等号: =,
  • =96:HEX 96 是 DEC 150,这是一个“短划线”符号:(某种“长减号”),
  • =A3: HEX A3 是 DEC 163 这是一个井号:£

我无法控制那段 HTML 的生成,但我应该解析并清理它并返回 £(而不是 =A3)等。

现在,我知道我可以将转换保存在内存映射中,但我想知道是否已经存在涵盖整个 windows-1252 字符集的编程解决方案?

参照。这是整个转换表:https://www.w3schools.com/charsets/ref_html_ansi.asp

编辑:

输入的 HTML 来自 IMAP 会话,因此上游似乎存在我无法控制的 7 位/8 位“引用的可打印编码”(参见 https://en.wikipedia.org/wiki/Quoted-printable)。

与此同时,我意识到了这种额外的编码,我尝试了这个quoted-printable(参见https://github.com/mathiasbynens/quoted-printable)库,但没有成功。

以下是 MCV(根据要求):

var cheerio = require('cheerio');
var windows1252 = require('windows-1252');
var quotedPrintable = require('quoted-printable');

const inputString = '<html>\r\n<head>\r\n<meta http-equiv=3D\"Content-Type\" content=3D\"text/html; charset=3DWindows-1=\r\n252\">\r\n<style type=3D\"text/css\" style=3D\"display:none;\"><!-- P {margin-top:0;margi=\r\nn-bottom:0;} --></style>\r\n</head>\r\n<body dir=3D\"ltr\">This should be a pound sign: =A3 and this should be a long dash: =96 \r\n</body>\r\n</html>\r\n'
const $ = cheerio.load(inputString, {decodeEntities: true});
const bodyContent = $('html body').text().trim();
const decodedBodyContent = windows1252.decode(bodyContent);

console.log(`The input string: "${bodyContent}"`);
console.log(`The output string: "${decodedBodyContent}"`);

if (bodyContent === decodedBodyContent) {
  console.log('The windows1252 output seems the same of as the input');
}

const decodedQp = quotedPrintable.decode(bodyContent)
console.log(`The decoded QP string: "${decodedQp}"`);

前面的脚本产生以下输出:

The input string: "This should be a pound sign: =A3 and this should be a long dash: =96"
The output string: "This should be a pound sign: =A3 and this should be a long dash: =96"
The windows1252 output seems the same of as the input
The decoded QP string: "This should be a pound sign: £ and this should be a long dash: "

在我的命令行上,我看不到长破折号,我不确定如何正确解码所有这些=&lt;something&gt; 编码字符?

【问题讨论】:

  • 看来你在这里很不走运。
  • 我认为您需要提供更完整的minimal reproducible example。首先,文本是如何从任何地方进入您的程序的?

标签: html node.js character-encoding windows-1252 quoted-printable


【解决方案1】:

似乎通过 IMAP 接收到的消息提供了 2 种不同编码的组合:

  • 实际字符串是根据“引用的可打印”编码 (https://en.wikipedia.org/wiki/Quoted-printable) 编码的,因为我认为通过 IMAP 通道(TCP 套接字连接)传输该信息时 7 位/8 位映射存在问题
  • 内容的逻辑表示(电子邮件正文),它是带有&lt;meta&gt; 标签和 Windows-1252 字符集的 HTML

这些 HTML 块也存在一个“问题”,它们包含大量 Windows 风格的回车符 (\r\n)。在我的情况下,我必须预处理字符串来处理这个问题:删除那些回车。

以下 MCV 示例应显示清理和验证表示电子邮件正文的字符串内容的过程:

var quotedPrintable = require('quoted-printable');
var windows1252 = require('windows-1252');

const inputStr = 'This should be a pound sign: =A3 \r\nand this should be a long dash: =96\r\n';
console.log(`The original string: "${inputStr}"`);

// 1. clean the "Windows carriage returns" (\r\n)
const cleandStr = inputStr.replace(/\r\n/g, '');
console.log(`The string without carriage returns: "${cleandStr}"`);

// 2. decode using the "quoted printable protocol"
const decodedQp = quotedPrintable.decode(cleandStr)
console.log(`The decoded QP string: "${decodedQp}"`);

// 3. decode using the "windows-1252"
const windows1252DecodedQp = windows1252.decode(decodedQp);
console.log(`The windows1252 decoded QP string: "${windows1252DecodedQp}"`);

给出这个输出:

The original string: "This should be a pound sign: =A3
and this should be a long dash: =96
"
The string without carriage returns: "This should be a pound sign: =A3 and this should be a long dash: =96"
The decoded QP string: "This should be a pound sign: £ and this should be a long dash: "
The windows1252 decoded QP string: "This should be a pound sign: £ and this should be a long dash: –"

请注意在 Windows-1252 解码阶段之前/之后呈现不同的“长破折号字符”。

Afaik,这与 UTF-8 编码/解码无关。我能够从中找出程序的“解码顺序”:https://github.com/mathiasbynens/quoted-printable/issues/5

我不确定的一件事是,我运行这段代码的操作系统是否会对文件的字符集/编码或字符串流产生某种影响。

我用过的npm包是:

【讨论】:

    猜你喜欢
    • 2013-12-14
    • 2012-02-06
    • 2012-05-14
    • 2012-10-12
    • 2013-06-22
    • 2021-01-23
    • 1970-01-01
    • 2015-11-18
    • 2010-09-24
    相关资源
    最近更新 更多