Python 3字符串解码

时间:2016-08-04 12:01:57

标签: string python-3.x unicode

我从Apache日志文件中读取数据。有一些文本被编码。喜欢这一行:

192.168.1.17 - - [04/Aug/2016:18:45:00 +0800] "GET /d/?q=\xa9\xfa\xa4\xd1\xb7|\xa7\xf3\xa6n HTTP/1.1" 302 3734 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"

我要解码'\ xa9 \ xfa \ xa4 \ xd1 \ xb7 | \ xa7 \ xf3 \ xa6n'。

在python 2中,我使用代码:

print(line.decode('string-escape').decode('big5'))

结果:

明天會更好

但是我无法在python 3中编写正确的代码。

我尝试使用代码:

with open('access.log', 'r') as f:
    line = f.read()
    print(bytes(line, 'latin-1').decode('big5'))

结果:

\xa9\xfa\xa4\xd1\xb7|\xa7\xf3\xa6n

或者这段代码:

with open('access.log', 'rb') as f:
    line = f.read()
    print(line.decode('big5'))

结果:

\xa9\xfa\xa4\xd1\xb7|\xa7\xf3\xa6n

似乎因为使用Python 3读取表单文件,'\ x'变为'\ x'。所以,如果有人帮我解决这个问题?谢谢。

1 个答案:

答案 0 :(得分:2)

如果你有" \ xDD"在文件中它与Python代码中的不同 - 在Python代码中," \ xDD"序列在编译时被翻译,并且在程序存储器中,只是由十六进制数字" DD"表示的字节。保持。如果您阅读" x \ DD"来自文件的序列,在程序存储器中将有四个字节 - 一个用于序列的每个ASCII字符 - 所以对于 "版权所有\ xA9"你有记忆中的字符" \"," x"," a"," 9" ('编译时间'在Python中是一个透明的步骤,当一个人运行程序时会发生。)

所以,如果您已经阅读了Python3中的序列,那么当打印到您的终端时,您会看到类似" \ xa9 \ xfa"的序列。当你应该看到"明"你必须这样做:

  1. 透明地将字符串转换为字节对象(使用 latin1 codec) - (或将您的文件作为字节对象读取,打开它 二进制模式开始)
  2. 使用" unicode_escape"将对象解码回文本编解码器。这将解析" \ xDD"在内存中序列成单个字节。

  3. 透明地将您的unicode对象转换为字节(是的,再次) - 这次不是四个字符" \,x,a,9" bytes对象在内存位置有一个0xa9(169)字节。

  4. 再次从这个bytes对象解码为一个字符串,这次使用big5解码。你有 - 你有一个带有你想要的中文字符的字符串对象(文本),

  5. 最后一个str对象可以在任何支持字符的终端或GUI界面中打印(打印界面应该从Python字符串透明地进行最后一次编码转换)。如果要使用BIG5编码将这些字符写入文件,请在打开要写入的文件时明确地传递该编码。 (或者使用utf-8,具体取决于您的系统。)

    所以,在代码中,即:

    with open('access.log', 'r') as f:
        line = f.read()
        step1 = line.encode("latin1")
        step2 = step1.decode("unicode_escape")
        step3 = step2.encode("latin1")
        final_text = step3.decode("big5")
        print(final_text)
    

    TL; DR 在Python3中," string_scape"编解码器是" unicode_escape" - 但是你必须将它解码为一个字节对象来开始。