Python中如何分析包含不同中文编码格式的log文件?
工作上需要分析一些客户发过来的文件,但是实际发现文件编码很混乱,怀疑是客户也是把几个来源的内容不做转码而拼凑的,file -I 识别不了:
$ file -I logs/mv1.txt
logs/mv1.txt: text/plain; charset=unknown-8bit
用 atom 打开文件,大致如下:

写了一个函数把乱码部分提取出来,想重新编码
if __name__ == "__main__":
cont = get_content("mv1.txt")
#print cont.decode('gbk')
print cont.decode('gb2312')
但是总是提示错误:
UnicodeDecodeError: 'gb2312' codec can't decode bytes in position 0-1: illegal multibyte sequence
客户比较强势,我这边推动不了客户修改 log 文件格式,不知道大伙有解决方案么?
Python中如何分析包含不同中文编码格式的log文件?
10 回复
按行读,分别解码
import re
import chardet
def analyze_mixed_encoding_log(log_file_path):
"""
分析包含不同中文编码的日志文件
支持自动检测并转换GBK、GB2312、UTF-8等编码
"""
encodings_to_try = ['utf-8', 'gbk', 'gb2312', 'big5']
results = {
'total_lines': 0,
'encoding_stats': {},
'error_lines': [],
'content_analysis': {}
}
try:
with open(log_file_path, 'rb') as f:
raw_data = f.read()
# 方法1: 使用chardet自动检测整体编码
detected = chardet.detect(raw_data)
print(f"整体检测编码: {detected['encoding']} (置信度: {detected['confidence']:.2%})")
# 方法2: 逐行分析混合编码
lines = raw_data.split(b'\n')
results['total_lines'] = len(lines)
for i, line_bytes in enumerate(lines):
if not line_bytes:
continue
line_decoded = None
used_encoding = None
# 尝试多种编码
for encoding in encodings_to_try:
try:
line_decoded = line_bytes.decode(encoding)
used_encoding = encoding
break
except UnicodeDecodeError:
continue
# 记录编码统计
if used_encoding:
results['encoding_stats'][used_encoding] = results['encoding_stats'].get(used_encoding, 0) + 1
# 提取中文内容分析
chinese_chars = re.findall(r'[\u4e00-\u9fff]+', line_decoded)
if chinese_chars:
for char in chinese_chars:
results['content_analysis'][char] = results['content_analysis'].get(char, 0) + 1
else:
results['error_lines'].append(i + 1)
# 输出分析结果
print(f"\n=== 分析结果 ===")
print(f"总行数: {results['total_lines']}")
print(f"\n编码分布:")
for encoding, count in results['encoding_stats'].items():
percentage = (count / results['total_lines']) * 100
print(f" {encoding}: {count}行 ({percentage:.1f}%)")
if results['error_lines']:
print(f"\n解码失败的行号: {results['error_lines'][:10]}") # 只显示前10个
if results['content_analysis']:
print(f"\n出现频率最高的10个中文词汇:")
sorted_chars = sorted(results['content_analysis'].items(), key=lambda x: x[1], reverse=True)
for char, count in sorted_chars[:10]:
print(f" '{char}': {count}次")
return results
except FileNotFoundError:
print(f"错误: 找不到文件 {log_file_path}")
return None
except Exception as e:
print(f"分析过程中出错: {str(e)}")
return None
# 使用示例
if __name__ == "__main__":
# 替换为你的日志文件路径
log_file = "mixed_encoding.log"
analysis_results = analyze_mixed_encoding_log(log_file)
# 如果需要统一转换为UTF-8保存
if analysis_results:
with open(log_file, 'rb') as f:
content = f.read()
# 尝试用检测到的编码读取,然后转UTF-8
detected = chardet.detect(content)
try:
unified_content = content.decode(detected['encoding']).encode('utf-8')
with open('converted_utf8.log', 'wb') as f:
f.write(unified_content)
print("\n已转换为UTF-8保存为: converted_utf8.log")
except:
print("\n转换失败,尝试逐行处理...")
核心思路:
- 先用
chardet检测整体编码倾向 - 逐行尝试多种编码(UTF-8、GBK、GB2312等)
- 统计各编码出现的频率
- 提取中文内容进行分析
- 提供统一转换为UTF-8的选项
主要用到的库:
chardet: 编码检测re: 正则提取中文- 内置的编解码器
处理逻辑:
- 二进制模式读取文件
- 对每行数据尝试多种解码方式
- 记录解码成功的编码类型
- 用正则
[\u4e00-\u9fff]匹配中文字符
这样就能处理GBK、UTF-8、GB2312混在一起的日志文件了。如果某行解码失败,会记录行号方便后续检查。
一句话建议: 先用chardet检测整体编码,再逐行尝试多种解码方式最稳妥。
cont 就是按行读的思路了,把乱码的那行 “content” 单独拿出来了,但是不知道怎么解码才对
用 chardet.detect 得到的结果是:<br> {'confidence': 0.3888443803816883, 'language': 'Turkish', 'encoding': 'Windows-1254'}<br>
感觉没啥参考价值。
起码得让客户告诉你都有些什么编码
那到底是什么编码呢
#2 中文一般就 2-3 种编码,从 utf8, gbk, big5 挨个试呗。
#2 还有,不要用 gb2312,用 gb18030
这个看来按二进制切片解析然后分段 decode 了
谢谢楼上几位,原来是 cont.decode(‘utf8’).encode(‘gb18030’),诶!

