这一篇放在NLP下面 但其实与机器学习/神经网络没啥关系,不过广义上看 也是在"自然语言处理"中遇到的问题..
linux下 发现一些奇怪的问题,看起来为空的字符串,长度却是1:
控制台运行的部分代码如下:
my_list = []
[my_list.append(x) for line in qfl_df['text'] for x in jieba.cut(line) if len(x) == 1]
my_counter = Counter(my_list)
print(my_counter.most_common())
('觉', 1),
('颠', 1),
('彘', 1),
('魋', 1),
('节', 1),
('饩', 1),
('粟', 1),
('殆', 1),
('', 1),
('抚', 1),
('尊', 1),
('匹', 1),
('宅', 1),
('璞', 1),
('石', 1),
('蜃', 1),
('蛤', 1),
('羇', 1),
('縻', 1),
('坑', 1),
('抑', 1),
('庞', 1),
('涓', 1),
('殊', 1),
('柬', 1),
('畎', 1),
('亩', 1),
('闺', 1),
('', 1),
('佃', 1),
('伏', 1),
('单', 1),
而再打印my_counter中这些看起来为空的字符的长度, 长度确实为1而不是0.. 也奇怪,还可以有多个..
找到其中一条被cut的句子, 某行x: line = qfl_df['text'][x: x+1].text.values.tolist()[0]
print(line) 从打印信息上看出错的行表面上是: '楚季者、王子敖之曾孙也。蚠冒主章者,王子无钧也。令尹孙叔敖者、章之子也。左司马戍者、庄王之曾孙也。叶公诸梁者、戍之第三弟也。楚大夫申无畏者,又氏文氏。\n
jieba.lcut(line)的结果 看起来是正常的, 不会出现似空非空的东西
这一段话的原文是: '楚季者、王子敖之曾孙也。蚠冒主蒍章者,王子无钧也。令尹孙叔敖者、蒍章之子也。左司马戍者、庄王之曾孙也。叶公诸梁者、戍之第三弟也。楚大夫申无畏者,又氏文氏。\n'
我做了繁简转换后,记录对应关系,后期只使用简体的line:
line = zhconv.convert(origi_line, 'zh-hans')
[print(x,x.encode(), "AAAA") for x in line]
楚 b'\xe6\xa5\x9a' AAAA
季 b'\xe5\xad\xa3' AAAA
者 b'\xe8\x80\x85' AAAA
、 b'\xe3\x80\x81' AAAA
王 b'\xe7\x8e\x8b' AAAA
子 b'\xe5\xad\x90' AAAA
敖 b'\xe6\x95\x96' AAAA
之 b'\xe4\xb9\x8b' AAAA
曾 b'\xe6\x9b\xbe' AAAA
孙 b'\xe5\xad\x99' AAAA
也 b'\xe4\xb9\x9f' AAAA
。 b'\xe3\x80\x82' AAAA
蚠 b'\xe8\x9a\xa0' AAAA
冒 b'\xe5\x86\x92' AAAA
主 b'\xe4\xb8\xbb' AAAA
b'\xf0\xab\x87\xad' AAAA
章 b'\xe7\xab\xa0' AAAA
者 b'\xe8\x80\x85' AAAA
, b'\xef\xbc\x8c' AAAA
王 b'\xe7\x8e\x8b' AAAA
子 b'\xe5\xad\x90' AAAA
无 b'\xe6\x97\xa0' AAAA
钧 b'\xe9\x92\xa7' AAAA
也 b'\xe4\xb9\x9f' AAAA
。 b'\xe3\x80\x82' AAAA
令 b'\xe4\xbb\xa4' AAAA
尹 b'\xe5\xb0\xb9' AAAA
孙 b'\xe5\xad\x99' AAAA
叔 b'\xe5\x8f\x94' AAAA
敖 b'\xe6\x95\x96' AAAA
者 b'\xe8\x80\x85' AAAA
、 b'\xe3\x80\x81' AAAA
b'\xf0\xab\x87\xad' AAAA
章 b'\xe7\xab\xa0' AAAA
之 b'\xe4\xb9\x8b' AAAA
子 b'\xe5\xad\x90' AAAA
也 b'\xe4\xb9\x9f' AAAA
。 b'\xe3\x80\x82' AAAA
左 b'\xe5\xb7\xa6' AAAA
司 b'\xe5\x8f\xb8' AAAA
马 b'\xe9\xa9\xac' AAAA
戍 b'\xe6\x88\x8d' AAAA
者 b'\xe8\x80\x85' AAAA
、 b'\xe3\x80\x81' AAAA
庄 b'\xe5\xba\x84' AAAA
王 b'\xe7\x8e\x8b' AAAA
之 b'\xe4\xb9\x8b' AAAA
曾 b'\xe6\x9b\xbe' AAAA
孙 b'\xe5\xad\x99' AAAA
也 b'\xe4\xb9\x9f' AAAA
。 b'\xe3\x80\x82' AAAA
叶 b'\xe5\x8f\xb6' AAAA
公 b'\xe5\x85\xac' AAAA
诸 b'\xe8\xaf\xb8' AAAA
梁 b'\xe6\xa2\x81' AAAA
者 b'\xe8\x80\x85' AAAA
、 b'\xe3\x80\x81' AAAA
戍 b'\xe6\x88\x8d' AAAA
之 b'\xe4\xb9\x8b' AAAA
第 b'\xe7\xac\xac' AAAA
三 b'\xe4\xb8\x89' AAAA
弟 b'\xe5\xbc\x9f' AAAA
也 b'\xe4\xb9\x9f' AAAA
。 b'\xe3\x80\x82' AAAA
楚 b'\xe6\xa5\x9a' AAAA
大 b'\xe5\xa4\xa7' AAAA
夫 b'\xe5\xa4\xab' AAAA
申 b'\xe7\x94\xb3' AAAA
无 b'\xe6\x97\xa0' AAAA
畏 b'\xe7\x95\x8f' AAAA
者 b'\xe8\x80\x85' AAAA
, b'\xef\xbc\x8c' AAAA
又 b'\xe5\x8f\x88' AAAA
氏 b'\xe6\xb0\x8f' AAAA
文 b'\xe6\x96\x87' AAAA
氏 b'\xe6\xb0\x8f' AAAA
。 b'\xe3\x80\x82' AAAA
b'\n' AAAA
终于抓到了几个 b'\xf0\xab\x87\xad' b'\xf0\xab\x93\xa7' 这样的字符 好像decode转换不了成正常的中文:
In [1]: b'\xf0\xab\x93\xa7'.decode()
Out[1]: ''
In [2]: b'\xf0\xab\x93\xa7'.decode('gbk')
Out[2]: '皤摟'
In [3]: b'\xf0\xab\x93\xa7'.decode('gb2312')
---------------------------------------------------------------------------
UnicodeDecodeError Traceback (most recent call last)
in
----> 1 b'\xf0\xab\x93\xa7'.decode('gb2312')
UnicodeDecodeError: 'gb2312' codec can't decode byte 0x93 in position 2: illegal multibyte sequence
试试 b'\xf0\xab\x93\xa7'.decode('gbk') 的结果是 '皤摟', 仍然不符合预期
刚开始以为是 zhconv 这个库不行,又换了一个opencc来转换, 还是同样的问题。那去源码看看/打印:
opencc中 关键的self._dict_chain_data 打印结果部分如下
'葯': '药',
'葷': '荤',
'蒍': '',
'蒐': '搜',
'蒓': '莼',
'蒔': '莳',
'蒕': '蒀',
'蒙': '蒙',
'蒞': '莅',
'蒭': '',
'蒼': '苍',
'蓀': '荪',
'蓆': '席',
'蓋': '盖',
'蓧': '',
'蓮': '莲',
'蓯': '苁',
'蓴': '莼',
'蓽': '荜',
这个转换关系 是在字典中的, 比如上面的来自这个文件 opencc\dictionary\TSCharacters.txt :(windows下用notpad打开看到):
葤 荮
葦 苇
葯 药
葷 荤
蒍
蒐 搜
蒓 莼
蒔 莳
蒕 蒀
蒙 蒙
蒞 莅
蒭
蒼 苍
蓀 荪
蓆 席
蓋 盖
蓧
蓮 莲
蓯 苁
蓴 莼
蓽 荜
'楚季者、王子敖之曾孙也。蚠冒主章者,王子无钧也。' 这句话在windows中可以正常复制粘贴,但粘贴到linux下就会报错 或 看起来自动省略 字(至少我手上的centos/ubuntu多台机器都是这样)
问题大概找到了:应该是这些繁体字对应的简体字的编码问题。
Windows的默认编码为GBK,Linux的默认编码为UTF-8。在Windows下编辑的中文,在Linux下显示为乱码。 看到有文章 为了解决此问题,修改Linux的默认编码为GBK。 但我觉得好像强制直接修改不太合适。
有一种不太合适的临时解决方法 可能是 在windows而不是linux运行。
linux下:
In [41]: ' '.join(jieba.cut(origi_line))
Out[41]: '楚季者 、 王子 敖 之 曾孙 也 。 蚠 冒主 蒍 章者 , 王子 无钧 也 。 令尹 孙叔敖 者 、 蒍 章 之子 也 。 左 司马 戍者 、 庄王 之 曾孙 也 。 叶公 诸梁者 、 戍 之 第三 弟 也 。 楚 大夫 申 无畏 者 , 又 氏 文氏 。 \n'
In [42]: ' '.join(jieba.cut(line))
Out[42]: '楚季者 、 王子 敖 之 曾孙 也 。 蚠 冒主 章者 , 王子 无钧 也 。 令尹 孙叔敖 者 、 章之子 也 。 左 司马 戍者 、 庄王 之 曾孙 也 。 叶公 诸梁者 、 戍 之 第三 弟 也 。 楚 大夫 申 无畏 者 , 又 氏 文氏 。 \n'
win下:
' '.join(jieba.cut(origi_line))
Out[13]: '楚季者 、 王子 敖 之 曾孙 也 。 蚠 冒主 蒍 章者 , 王子 无钧 也 。 令尹 孙叔敖 者 、 蒍 章 之子 也 。 左 司马 戍者 、 庄王 之 曾孙 也 。 叶公 诸梁者 、 戍 之 第三 弟 也 。 楚 大夫 申 无畏 者 , 又 氏 文氏 。 \n'
' '.join(jieba.cut(line))
Out[14]: '楚季者 、 王子 敖 之 曾孙 也 。 蚠 冒主 章者 , 王子 无钧 也 。 令尹 孙叔敖 者 、 章之子 也 。 左 司马 戍者 、 庄王 之 曾孙 也 。 叶公 诸梁者 、 戍 之 第三 弟 也 。 楚 大夫 申 无畏 者 , 又 氏 文氏 。 \n'
还搜到 ideographic description characters相关,在linux下 可能能用这样的转换替代? 这个还得再花些时间研究下
搜了很多 后来又想到,这个问题 其实产生的影响: 从人的角度看 可读性不太好。 但好像对程序运行,对于我想要的计算结果 影响比较小。
比如计算词频时,对于这样的字 程序仍然会正常占位计算。 会影响jieba.cut, 但这样的字 可能比较难(机率较小)会组成一个词组, 所以实际影响结果 也还好。可以作为遗留问题将来跟进,不阻塞当前的工作。