Python中如何分析包含不同中文编码格式的log文件?

工作上需要分析一些客户发过来的文件,但是实际发现文件编码很混乱,怀疑是客户也是把几个来源的内容不做转码而拼凑的,file -I 识别不了:

$ file -I logs/mv1.txt
logs/mv1.txt: text/plain; charset=unknown-8bit

用 atom 打开文件,大致如下: Log

写了一个函数把乱码部分提取出来,想重新编码


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转换失败,尝试逐行处理...")

核心思路:

  1. 先用chardet检测整体编码倾向
  2. 逐行尝试多种编码(UTF-8、GBK、GB2312等)
  3. 统计各编码出现的频率
  4. 提取中文内容进行分析
  5. 提供统一转换为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’),诶!

回到顶部