我正在解码包含带圆圈数字的日语字符的邮件主题,即“メール送信①”。
我按照 RFC2047 采用以下格式的主题。
subject:=?iso-2022-jp?B?GyRCJWEhPCVrQXc/Li0hGyhC?=
我正在 python-2.6 中执行以下过程,以便取回日语字符。
>>> import base64
>>> s='GyRCJWEhPCVrQXc/Li0hGyhC'
>>> type(s)
<type 'str'>
>>> s_bytes=base64.b64decode(s)
>>> s_bytes
'\x1b$B%a!<%kAw?.-"\x1b(B'
>>> s_decode=s_bytes.decode('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 时收到 UnicodeDecode 错误
iso-2022-jp
由于圈出的数字而进行编码。
如果主题标头使用“iso-2022-jp”进行编码,那么为什么我无法将其解码回来以及为什么它会抛出 unicodeDecode 错误?
为了重新验证收到的输入,当我尝试使用
此站点解码主题
subject:=?iso-2022-jp?B?GyRCJWEhPCVrQXc/Li0hGyhC?=
时,我得到了原始主题,即“メール送信①”。
那么有人可以解释一下这种情况是否是由于 python 的限制而发生的吗?
首先解码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")