Python:解码由unicode代码点和unicode文本组成的字符串

Dar*_*ush 3 python unicode

解析一些 HTML 内容我得到以下字符串:

\n\n
\xd0\x90\xd0\x91\xd0\x92\\u003d\\"res\n
Run Code Online (Sandbox Code Playgroud)\n\n

处理它的常见建议似乎是使用 unicode_escape 进行解码。然而,这会导致以下结果:

\n\n
\xc3\x90\xc3\x90\xc3\x90="res\n
Run Code Online (Sandbox Code Playgroud)\n\n

转义字符得到正确解码,但西里尔字母由于某种原因被破坏。除了使用正则表达式提取所有看起来像 unicode 字符串的内容,使用 unicode_escape 仅解码它们,然后将所有内容放入新字符串中,还有哪些其他方法可以在 Python 中使用 unicode 代码点解码字符串?

\n

Mar*_*ers 5

unicode_escape将输入视为Latin-1 编码;任何不表示 Python 字符串文字转义序列的字节都会被解码,将字节直接映射到 Unicode 代码点。您给它的是 UTF-8 字节,因此西里尔字符用 2 个字节表示,每个字节解码为两个 Latin-1 字符,其中一个是 U+00D0 \xc3\x90,另一个不可打印:

\n\n
>>> print repr(\'\xd0\x90\xd0\x91\xd0\x92\\\\u003d\\\\"res\')\n\'\\xd0\\x90\\xd0\\x91\\xd0\\x92\\\\u003d\\\\"res\'\n>>> print repr(\'\xd0\x90\xd0\x91\xd0\x92\\\\u003d\\\\"res\'.decode(\'latin1\'))\nu\'\\xd0\\x90\\xd0\\x91\\xd0\\x92\\\\u003d\\\\"res\'\n>>> print \'\xd0\x90\xd0\x91\xd0\x92\\\\u003d\\\\"res\'.decode(\'latin1\')\n\xc3\x90\xc3\x90\xc3\x90\\u003d\\"res\n
Run Code Online (Sandbox Code Playgroud)\n\n

这种错误解码称为Mojibake,可以通过重新编码为 Latin-1,然后从正确的编解码器(在您的情况下为 UTF-8)解码来修复:

\n\n
>>> print \'\xd0\x90\xd0\x91\xd0\x92\\u003d\\\\"res\'.decode(\'unicode_escape\')\n\xc3\x90\xc3\x90\xc3\x90="res\n>>> print \'\xd0\x90\xd0\x91\xd0\x92\\u003d\\\\"res\'.decode(\'unicode_escape\').encode(\'latin1\').decode(\'utf8\')\n\xd0\x90\xd0\x91\xd0\x92="res\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,如果转义序列编码超出 Latin-1 范围 (U+0000-U+00FF) 的代码点,则此操作将会失败。\\uhhhh

\n\n

与上述相同的 Python 3 使用codecs.encode()

\n\n
>>> import codecs\n>>> codecs.decode(\'\xd0\x90\xd0\x91\xd0\x92\\\\u003d\\\\"res\', \'unicode_escape\').encode(\'latin1\').decode(\'utf8\')\n\'\xd0\x90\xd0\x91\xd0\x92="res\'\n
Run Code Online (Sandbox Code Playgroud)\n