请教一个关于 Pythin 2.7 中文乱码的问题。

2015-01-15 19:50:40 +08:00
 Anybfans

最近在自学python,发现读取文件中的中文时候会出现问题。例如下面这道题。

第 0012 题: 敏感词文本文件 filtered_words.txt,里面的内容 和 0011题一样,当用户输入敏感词语,则用 星号 * 替换,例如当用户输入「北京是个好城市」,则变成「**是个好城市」。

这些是敏感词。
北京
程序员
公务员
领导
牛比
牛逼
你娘
你妈
love
sex
jiangge

def filter_words(words):
#从文件中读取过滤单词名单
file_object = open('filtered_words.txt','r')
filtered_words = []
for line in file_object:
filtered_words.append(line.strip('\n'))
file_object.close()
print filtered_words

发现输出结果是这样的。。写完后英文可以成功过略,但是中文就不行了。请问有什么解决方法么。。谢谢了
['\xb1\xb1\xbe\xa9', '\xb3\xcc\xd0\xf2\xd4\xb1', '\xb9\xab\xce\xf1\xd4\xb1', '\xc1\xec\xb5\xbc', '\xc5\xa3\xb1\xc8', '\xc5\xa3\xb1\xc6', '\xc4\xe3\xc4\xef', '\xc4\xe3\xc2\xe8', 'love', 'sex', 'jiangge']

3601 次点击
所在节点    问与答
12 条回复
Anybfans
2015-01-15 19:53:25 +08:00
。。代码有缩进的。。发上来就不行了。。代码如下


[img]http://anybfans.qiniudn.com/py.jpg[/img]
cevincheung
2015-01-15 19:55:37 +08:00
cn = u"中文"
print cn
Anybfans
2015-01-15 19:55:39 +08:00
mV2GK
2015-01-15 20:02:57 +08:00
python中文编码问题,utf-8,gbk,unicode。。。。

可以看下下面的文章

http://fc-lamp.blog.163.com/blog/static/1745666872012121240969/
jyjmrlk
2015-01-15 20:10:09 +08:00
这其实不是乱码啦,算是 Console 输出不友好。不信试试这个:

https://gist.github.com/Masakichi/4316b3fd0f3c9350d597

另外,楼主应该用的 Windows,默认 UTF-8 编码的话像注释里这样 decode encode 一下就好。当然这个和问题没有关系啦。
Anybfans
2015-01-15 20:17:02 +08:00
@jyjmrlk 先谢谢了。
在代码注释头部已经添加了这个的
#!/usr/bin/env python
# -*- coding: utf-8 -*-


我意思是说。用户输入中文后,无法匹配到filtered_words.txt 里面的中文内容。英文的话可以成功过滤。
Anybfans
2015-01-15 20:20:46 +08:00
@mV2GK 》《 看了半天没发现list怎么转码。。从文件中读取内容的时候,读取到的中文就是\xb1\xb1\xbe\xa9这类的。 在头部注释已经给了# -*- coding: utf-8 -*-了。 先谢谢了
jyjmrlk
2015-01-15 20:42:58 +08:00
@Anybfans 我试过之后可以匹配啊,我刚指的编码是 Terminal 的编码。

另外 len('北京 ') == 6 哦,len(u'北京 ') 才等于2

至于编码问题吗,我的印象里是这样的

str.decode('某种编码') => unicode

unicode.encode('某种编码') => str

只要某种编码选择没有问题,一般还好。
Anybfans
2015-01-15 20:59:20 +08:00
@jyjmrlk 嗯 谢谢。。我再研究一下。谢谢咯
Sylv
2015-01-15 21:01:17 +08:00
你这里其实是有两个问题:

第一个问题是你发现输出是这样 '\xb1\xb1\xbe\xa9',但这其实并不是乱码,这是非 ascii 字符串在 Python 内部的存储方式。例如 "北京" 在 utf-8 编码下在 Python 内部储存的就是 '\xe5\x8c\x97\xe4\xba\xac',你可以通过 repr() 方法取得这个,print repr("北京") -> '\xe5\x8c\x97\xe4\xba\xac'。因为你 print 的是个 list,Python 不会把 list 内的元素输出成供人阅读的字符串,而是打印出内部的存储形式。所以你的那个输出是正确的,没有乱码的问题。

第二个问题就是既然没有乱码那为什么无法匹配?那是因为你的 filtered_words.txt 文件是用 Windows 下的默认 GBK 编码保存的,那么 Python 读取里面的内容也就是 GBK 编码的字符串,'\xb1\xb1\xbe\xa9' 就是 '北京' 的 GBK 编码的字节码。而你的 Python 脚本又用的是 UTF-8 的编码,估计你的输入也是 UTF-8 的编码的字符串,那么当然两个编码的字符串就无法匹配上了。同样都是 '北京','\xe5\x8c\x97\xe4\xba\xac' != '\xb1\xb1\xbe\xa9'。
解决办法是,将读取的文本解码成 unicode,或者多一步再编码成 UTF-8 编码的 str。
用 GBK 编码将输入解码成 unicode:line.decode('gbk') -> unicode。
再用 UTF-8 编码将 unicode 编码成 UTF-8 编码的 str:line.decode('gbk').encode('utf-8')。
如果你用来比对的输入也是 unicode 的话,就无需再编码成 str 了,'\xb1\xb1\xbe\xa9'.decode('gbk') = u'北京'。推荐你在内部都用 unicode 来处理,这样就能尽量避免 Python2 的编码坑。
binux
2015-01-15 21:01:27 +08:00
什么是编码
-------------

对于计算机来说,它认识的就是01,称为 1bit,然后我们一般将 8bit 称为 1byte。那么这 1byte 能表示多少个字符呢? 2^8 = 256 种。那么问题来了,对于中文来说,上万个字,怎么表示得完啊。
于是,就有了用多个 bytes 表示一个字的方法,这个表示方法就叫做编码。

而编码有各种不同的标准,比如 gb2312 比如 gb18030 比如 utf8。当你看到一个二进制串的时候,你的告诉我,它是什么编码的,别人才能理解。所以单独给出一个二进制串,它是什么编码的,是没有办法知道的,只能猜。
因为很重要,再说一遍,**一个二进制串是什么编码的,只能猜**,通过组合多个 bytes 看他是否在某个编码下合法,组合出来的字是否常见,猜!所以对于短文本,这是很不准的。甚至有一个二进制传,同时在 utf8 和 gb2312 下都是合法,合理的文字。

所以,回到你这个问题,一般来说 gb2312 是 2bytes 的,而且几乎所有的 2bytes 都能转换成 gb2312,所以,当它是一个字的时候,chardet 不会猜它是 gb2312,但是两个字的时候就有可能会。


什么是 unicode
-------------
这一堆编码有两个问题:

1. 世界上有很多语言,有更多种编码
2. gb2312 只有两字节,表示不完所有语言文字,而 utf8 是不定长的,你没法通过数二进制串知道它有几个字。

为了解决这两个问题,unicode 出现了,unicode 设计能够在编码空间内(不准确),容纳所有语言的所有字符。并且它是定长的(不准确)。所以,在 Python 中,我们提倡所有文字都使用 unicode。

但是,回到计算机体系中,计算机只认识 01,你是不能将一个 unicode 传递给别的系统的(不准确)。他们之间的传递,必须是二进制串。在这时,你必须将 unicode encode 为一个特定编码,而且这个编码是和对方系统约定好的。不然就会出现乱码,或者异常。这个过程发生在,例如:

- print 输出
- 将文字保存到文件
- 储存数据库
- 网络发包
- 调用 shell 程序

等等。

**因为很重要再说一遍,你必须和对方系统约定正确的编码**。二进制串不指定编码,别人是无法理解的。
Anybfans
2015-01-15 21:08:26 +08:00
@Sylv 哇。。明白了。。终于明白啦。。非常感谢了。。我这就研究下。。
@binux 非常感谢了。o(^▽^)o

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/162492

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX