无法在Python中使用ISO-2022-JP解码邮件标题中带有圆圈数字的日语字符

问题描述 投票:0回答:1

我正在处理一封电子邮件,其中原始主题包含带圆圈数字的日语字符,即“メール送信②”。

我在按照 RFC2047 进行处理时收到了以下格式的主题。

subject:=?iso-2022-jp?B?GyRCJWEhPCVrQXc/Li0iGyhC?=

从主题头中,我可以理解,

GyRCJWEhPCVrQXc/Li0iGyhC
是原始字符串使用
iso-2022-jp
编码后的base64格式。

我正在 python-2.6 中执行以下过程,以便取回日语字符。

>>> import binascii
>>> import base64
>>> s='GyRCJWEhPCVrQXc/Li0iGyhC'
>>> type(s)
<type 'str'>
>>> s_bytes=binascii.a2b_base64('GyRCJWEhPCVrQXc/Li0iGyhC')
>>> s_bytes
'\x1b$B%a!<%kAw?.-"\x1b(B'
>>> s_unicode=unicode(s_bytes,'iso-2022-jp','strict')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'iso2022_jp' codec can't decode bytes in position 13-14: illegal multibyte sequence

但是当尝试使用将 s_bytes 转换为 unicode 时,我收到 UnicodeDecode 错误

iso-2022-jp
由于圈出的数字而进行编码。

以下是我的一些观察:

  1. 如果我在上面的代码中使用“replace”代替“strict”,则圈起的字符将被“�”替换。

     >>> s_unicode=unicode(s_bytes,'iso-2022-jp','replace')
     >>> s_unicode
     u'\u30e1\u30fc\u30eb\u9001\u4fe1\ufffd'
     >>> print(s_unicode.encode('utf-8'))
    メール送信�
    
  2. 如果我使用“忽略”,它将忽略圈出的字符并给出剩余的日语字符。

如果主题标头使用“iso-2022-jp”进行编码,那么为什么我无法将其解码回来以及为什么它会抛出 unicodeDecode 错误?

为了重新验证收到的输入,当我尝试使用

此站点
解码主题subject:=?iso-2022-jp?B?GyRCJWEhPCVrQXc/Li0iGyhC?=时,我得到了原始主题,即“メール送信②”

所以我不确定我是否做错了什么或者 python-2.6 是否有任何限制

我还尝试使用其他编码进行解码,例如 -

euc_jp
shift_jis
cp932
。 在所有这些情况下,虽然我没有收到 UnicodeDecode 错误,但最终的字符串是乱码,如
%a!<%kAw?.-"

>>> import binascii
>>> import base64
>>> s='GyRCJWEhPCVrQXc/Li0iGyhC'
>>> type(s)
<type 'str'>
>>> s_bytes=binascii.a2b_base64('GyRCJWEhPCVrQXc/Li0iGyhC')
>>> s_bytes
'\x1b$B%a!<%kAw?.-"\x1b(B'
>>> eucjp_unicode=unicode(s_bytes,'euc_jp','strict')
>>> eucjp_unicode
u'\x1b$B%a!<%kAw?.-"\x1b(B'
>>> print(eucjp_unicode.encode('utf-8'))
%a!<%kAw?.-"
python python-2.7 unicode
1个回答
2
投票

首先解码Base64字符串:

import base64
seq = base64.b64decode('GyRCJWEhPCVrQXc/Li0iGyhC?=')
print(seq)
# b'\x1b$B%a!<%kAw?.-"\x1b(B'

这是一个 ISO-2022-JP 字节序列。 ISO-2022-JP 支持多种不同字符集之间的切换。

\x1b$B
切换到 JIS X 0208-1983(每个字符使用 2 个字节)。
\x1b(B
切换到 ASCII,因此 JIS X 0208-1983 序列为
%a!<%kAw?.-"
。问题字符是由
-"
表示的最后一个字符,其前导字节为
\x2D
,尾随字节为
\x22

前导字节对应于 JIS X 0208-1983 的第 13 行,这是一个包含 NEC 特殊字符的扩展集。

所以

\x2D\x22
就是角色②。

需要注意的是,并非所有 iso-2022-jp 的编码器/解码器对都支持第 13 行。不幸的是,Python 编解码器不支持。

Windows 等效项,以及 WHATWG 编码规范和 Web 浏览器实现。

有必要使用替代方案。

endec
模块提供与WHATWG编码规范兼容的编码和解码解析器。

安装模块:

pip install endec

然后从前面的代码开始:

import endec
result = endec.decode(seq, "iso-2022-jp")
print(result)
# メール送信②

编辑:

如评论中所示,

endec
模块正处于 alpha 开发阶段。 Python 缺乏对 ISO-2022-JP 的 Microsoft 和 Web 实现的支持,但扩展字符的使用并不频繁,因此谨慎的做法是默认使用核心 Python 编解码器并回退到
endec
作为最后的手段。

try:
    result = seq.decode('iso-2022-jp')
except UnicodeDecodeError:
    result = endec.decode(seq, "iso-2022-jp")
© www.soinside.com 2019 - 2024. All rights reserved.