之前用的一直是utf-8编码,几乎不会出现乱码问题。奈何公司的分词软件支持的输入和输出编码都是gbk,因此必须进行转码,一个非常痛苦的过程,如实记录下遇到的问题,供以后参考
标准utf8输出
#!/usr/bin/python # -*- coding: utf8 -*- #################### deal with base64 file ################### import gensim, logging from gensim.models import Doc2Vec import os import multiprocessing import numpy as np import base64 import codecs import g_url_text_pb2 import re import sys reload(sys) sys.setdefaultencoding('utf8') logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) def newFile(): global count fw = open('baike_url_part_000.chinese','w') with open('baike_url_part_000.result') as f: for line in f: base64Test = base64.b64decode(line) model=g_url_text_pb2.TextInfo() model.ParseFromString(base64Test) doc = model.title.decode('gbk', 'ignore')+' '+(model.content.decode('gbk', 'ignore')) doc = "".join(doc.split())#处理/r/t/n等 fw.write("".join(doc)+"\n") newFile()
转gbk输出
先不管那些奇怪的^@^F等字符,转成gbk编码写入文件,加个encode就行啦
doc = doc.encode('gbk','ignore') doc = "".join(doc.split()) fw.write("".join(doc)+"\n")
打开一看,纳尼,怎么变成了这样!这是什么鬼!
冷静……查看一下编码格式
file baike_url_part_000.chinese
然而……只显示了data……好忧伤……
baike_url_part_000.chinese: data
再看一下?好吧……binary。。
file -i baike_url_part_000.chinese baike_url_part_000.chinese: application/octet-stream; charset=binary
iconv 文件编码转换
iconv [选项…] [文件…]
输入/输出格式规范:
-f, –from-code=名称 原始文本编码
-t, –to-code=名称 输出编码
信息:
-l, –list 列举所有已知的字符集
输出控制:
-c 从输出中忽略无效的字符
-o, –output=FILE 输出文件
-s, –silent 关闭警告
–verbose 打印进度信息
# utf 转 gbk iconv -c -f utf-8 -t gb2312 file
傻瓜命令行工具enca
好了,这时候就要用神器啦!傻瓜命令行工具enca – 不但能智能识别文件的编码,而且还支持成批转换!心动了吗?心动不如行动!来!安装!so easy~
sudo apt-get install enca
常用的命令格式如下
#检查文件的编码 #enca -L 当前语言 -x 目标编码 文件名 enca -L zh_CN file #将文件编码转换为"UTF-8"编码 enca -L zh_CN -x UTF-8 file #如果不想覆盖原文件 enca -L zh_CN -x UTF-8 < file1 > file2 #把当前目录下的所有文件都转成utf-8 enca -L zh_CN -x utf-8 *
这里我们这么用👇
$ enca -L zh_CN baike_url_part_000.chinese Simplified Chinese National Standard; GB2312
locale
发现是GB2312,说明不是代码的问题。但是为什么显示出来是乱码呢?那只是因为显示的时候使用的字符编码方式和实际内容的字符编码不一致,所以解决方式当然就是双方都用同一种编码方式喽。简单的命令就可以实现啦
export LC_ALL=
关于locale,强烈推荐看看Locale 详解,然后搞明白以下三个环境变量的优先级:LCALL>LC*>LANG。locale相关的各个环境变量的作用参见这里。
处理^@^F^A等特殊字符
虽然可以显示了,但中间还有许多不能识别的字符
看一下这些字符的ascii对照表
然后一键替换,下面是将^@替换为空格的例子
sed -i "s/[\x00]/ /g" baike_url_part_000.chinese
然而不可见字符这么多,总不能一个个替换吧!在python中直接用正则做替换,在split前加上一行代码
doc = re.sub(r'[\x00-\x0F]+',' ', doc) doc = "".join(doc.split()) fw.write("".join(doc)+"\n")
顺便提一下,在python中,字符串前加r代表此字符串为原样显示,不转义。就像字符串’\n’转义是换行,若其前加上字母r,即r’\n’,则不进行转义,结果将原样显示’\n’。
这样,才算真正解决了这里的乱码问题。