这是我最近遇到过几次的问题。这是我最近的经历:
尝试浏览https://www.scape.sc/release.php?id=48,该页面包含日语文本。这个页面的日文完全是乱码,显示为unicode方形字符、符号和各种拉丁重音字符。即使在html源代码中也是如此,所以我不认为这是字体选择的问题。
该网站使用我从webhint.io 文章中了解到的一种声明字符集的过时方法,<META Http-equiv="Content-Type" Content="text/html; charset=utf8">
. 尽管文章确实提到这在当今不应该成为问题。
这是我在浏览器中访问原始 html 时的样子:
<TR><TD>2.</TD><TD>記憶ã¨ç©º</TD><TD> <I>(kioku to sora)</I></TD></TR>
过去,我发现在互联网档案馆的 Wayback Machine 上搜索存在此问题的旧版本网站会正确显示日文字符。我目前的情况也是如此。
在 Wayback Machine 的以下两个示例中,第一个链接来自 2016 年的捕获,页面源和呈现的页面都使用有效/未损坏的日语字符。第二个是 2023 年的,显示的乱码与我在自己的机器上看到的一样,这让我更有信心这不是我的问题。
2016 年的原始 html:
<tr><td>2.</td><td>記憶と空</td><td> <i>(kioku to sora)</i></td></tr>
2023 年的原始 html:
<tr><td>2.</td><td>記憶ã¨ç©º</td><td> <i>(kioku to sora)</i></td></tr>
我怀疑这是网站管理员的错误,可能是 2016 年至今的某个时候在文本编辑器中对网站进行更改时出现了一些字符集不匹配。这听起来合理吗?有什么方法可以恢复“损坏的”unicode 并避免依赖 Wayback Machine 上旧的站点捕获吗?
TL;DR:网站曾经包含有效的 unicode,现在不再包含。怎么会出现这样的问题呢?最终用户能否反转/使问题文本清晰?
文本采用UTF-8双重编码。也就是说,UTF-8 数据被误解为传统单字节编码之一(可能是 Windows-1252),然后再次从该编码转换为 UTF-8。(例如,以
記
UTF-8 表示的相同字节也在記
Windows-1252 中表示,并且这三个字符再次存储为 UTF-8。)换句话说,这是网站管理员方面的错误。(实际上,我的猜测是他们升级了 MySQL 数据库服务器,因为当前版本处理 UTF-8 Unicode 字符串,而网站时代的 MySQL 4.x 用于处理“latin1”,这或多或少是原始字节值.这方面的一些证据是,侧边栏链接说
-közi-
不是双重编码的,手写的艺术家页面也不是。在MySQL中,编码可以在DB端,在PHP客户端,甚至每个-连接;很容易导致不匹配并获得双编码文本,特别是对于较旧的 MySQL 配置。)浏览器通常没有任何功能来处理此类损坏;据他们所知,字符集声明是 100% 正确的,错误的是输入数据。扩展或“用户脚本”(GreaseMonkey 风格)可能会起作用;您也许还可以从本地保存的页面恢复文本。
恢复文本的大致过程是:
iconv
通过或其他编码转换器提供它,指定 UTF-8 作为输入,指定 Windows-1252(或其他候选旧代码页)作为输出。在这种情况下,常规 iconv 有点太严格了,Python 的 cp1252 编码也是如此,因为它们都拒绝使用 cp1252 中“未定义”的字符槽(例如,将 U+0081 翻译回字节 0x81),因此编码器需要稍微定制一下:
请注意,这会损坏
-közi-
侧边栏链接,该链接根本没有经过双重编码。该站点使用的方法完全适合其编写时的情况。它并不完全是“过时的”,它只是“不再是最方便的选项”,但仍然 100% 支持 - 与页面的HTML 4.01 标记的其余部分相同(而本文讨论的是 HTML 5)。
无论哪种方式,声明都是正确的;HTML 确实是用 UTF-8 编码的。真正的问题是 UTF-8 编码的内容。
当前网站的文本可能实际上使用的是较旧的编码,例如 Shift JIS、EUC 或 ISO-2022-JP,而不是它声称的 UTF-8。
因此,如果是这种情况,则数据没有损坏,只是不在所公布的编码中。
一个提供识别某些日语编码提示的网站是https://www.sljfaq.org/afaq/encodings.html
有多种用于更改编码的工具,例如 iconv 和 recode。我会先尝试这些。