我从 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'。那么如果有人帮我解决这个问题呢?谢谢。
最佳答案
如果文件中有“\xDD”,则与 Python 代码中的“\xDD”不同 - 在 Python 代码中,“\xDD”序列在编译时被转换,而在程序内存中,只是字节由十六进制数字“DD”表示的被保留。如果从文件中读取“x\DD”序列,则在程序存储器中将有四个字节 - 一个字节对应序列的每个 ASCII 字符 - 因此对于 “\xa9”在内存中包含字符“\”、“x”、“a”、“9”(Python 中的“编译时间”是运行程序时发生的一个透明步骤)。
所以,如果你读过Python3中的一个序列,当打印到你的终端时,当你应该看到“明”时,会显示一个像“\xa9\xfa”这样的序列,你必须这样做:
- 将字符串透明地转换为字节对象(使用 latin1 编解码器) -(或将文件读取为字节对象,然后将其打开 二进制模式开始)
使用“unicode_escape”编解码器将对象解码回文本。这会将“\xDD”序列解析为内存中的单个字节。
将您的 unicode 对象透明地转换为字节(是的,再次)- 这次,字节对象在内存位置中将有一个 0xa9 (169) 字节,而不是四个字符“\,x,a,9”。
再次从此字节对象解码为字符串,这次使用 big5 解码。现在你已经有了一个带有你想要的汉字的字符串对象(文本),
最后一个 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” - 但您必须首先应用它解码字节对象。
关于string - Python 3 字符串解码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38766794/