最近在自学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']
1
Anybfans OP |
2
cevincheung 2015-01-15 19:55:37 +08:00
cn = u"中文"
print cn |
3
Anybfans OP |
4
mV2GK 2015-01-15 20:02:57 +08:00
python中文编码问题,utf-8,gbk,unicode。。。。
可以看下下面的文章 http://fc-lamp.blog.163.com/blog/static/1745666872012121240969/ |
5
jyjmrlk 2015-01-15 20:10:09 +08:00 1
这其实不是乱码啦,算是 Console 输出不友好。不信试试这个:
https://gist.github.com/Masakichi/4316b3fd0f3c9350d597 另外,楼主应该用的 Windows,默认 UTF-8 编码的话像注释里这样 decode encode 一下就好。当然这个和问题没有关系啦。 |
6
Anybfans OP @jyjmrlk 先谢谢了。
在代码注释头部已经添加了这个的 #!/usr/bin/env python # -*- coding: utf-8 -*- 我意思是说。用户输入中文后,无法匹配到filtered_words.txt 里面的中文内容。英文的话可以成功过滤。 |
7
Anybfans OP @mV2GK 》《 看了半天没发现list怎么转码。。从文件中读取内容的时候,读取到的中文就是\xb1\xb1\xbe\xa9这类的。 在头部注释已经给了# -*- coding: utf-8 -*-了。 先谢谢了
|
8
jyjmrlk 2015-01-15 20:42:58 +08:00 1
@Anybfans 我试过之后可以匹配啊,我刚指的编码是 Terminal 的编码。
另外 len('北京 ') == 6 哦,len(u'北京 ') 才等于2 至于编码问题吗,我的印象里是这样的 str.decode('某种编码') => unicode unicode.encode('某种编码') => str 只要某种编码选择没有问题,一般还好。 |
10
Sylv 2015-01-15 21:01:17 +08:00 2
你这里其实是有两个问题:
第一个问题是你发现输出是这样 '\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 的编码坑。 |
11
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 程序 等等。 **因为很重要再说一遍,你必须和对方系统约定正确的编码**。二进制串不指定编码,别人是无法理解的。 |