python2.7.1编码问题

来源:互联网 发布:文明6 mac下载 编辑:程序博客网 时间:2024/05/01 06:36

    以前没有怎么接触过编码的问题。这次一接触头大了。简单介绍自己遇到的情况。编辑环境Ulipad。文件开头设置的coding=utf-8。读取的文件是utf-8格式。cmd.exe窗口gbk(chcp65001命令设置cmd窗口utf-8格式,chcp936命令设置cmd窗口gbk格式)问题出在我用程序读取文件中的url地址,在python抓取程序使用urllib2去抓取对应的网页内容。此时总是报错 urlerror no host given。

    手动输入url是抓取程序可以成功运行,但是对于文本读取的地址传进程序后就无法识别。起初google问题一直以为是编码的问题,以为是错误的编码格式导致无法识别。折腾死的。后来才知道是所谓的BOM导致的祸害。

通过一天的学习,对python的字符格式也有了个大概的了解。现在对昨天的学习进行总结下。


一,      python字符串

python字符串有个基类basestring.两个子类str与unicode。str就像是java中byte[],而unicode就类似java中的char[]。

一般的赋值那样的操作得到的对象时str型,如果想得到unicode类型必须在前面显示加一个u。(有的文章介绍含有中文不能仅仅只是加u,需要使用unicode这个函数进行转换。但我使用的python2.7.1没有这个限制,使用中文前面加u依然可以)

看一个字串是str还是unicode那就直接使用type()函数。

<span style="font-size:14px;">x = u'abc'y = u'中国'#z = unicode('中国', 'gbk')    #编译环境是utf-8 字串"中国"则是utf-8的str 用gbk解码无法成功z = unicode('中国', 'utf-8')print x, type(x)          <span style="white-space:pre"></span>#abc  <type ‘unicode’>print y, type(y) <span style="white-space:pre"></span>#中国 <type ‘unicode’>print z, type(z)          <span style="white-space:pre"></span>#中国 <type ‘unicode’>x = x + yprint x, type(x)                #abc中国 <type ‘unicode’></span>

decode与encode

了解str与unicode后。从str到unicode就是decode的过程,反过来,从unicode到str是encode过程。

<span style="font-size:14px;"></span>
<span style="font-size:14px;">x = u'abc'y = "我晕"print x, type(x), len(x)3        #abc <type ‘unicode’> 3print y, type(y), len(y)6        #****(由于我显示的窗口是gbk格式这里乱码) <type ‘str’>  6  <span style="white-space:pre"></span> #奇怪吧,"中国"当时utf-8的str时候的长度是6w = x.encode("gbk")v = y.decode("utf-8")print w, type(w), len(w)        #abc <type ‘str’> 3print v, type(v), len(v)        #中国 <type ‘unicode’> 2</span>

二,  python的读写

在介绍读写之前,说说给我带来很多困扰的bom。维基百科这么给解释的。

The BOM is a Unicode character used to signal the endianness (byte order) of a text file or stream. It is encoded at U+FEFF byte order mark (BOM). BOM use is optional, and, ifused, should appear at the start of the text stream. Beyond its specific use asa byte-order indicator, the BOM character may also indicate which of theseveral Unicode representations the text is encoded in.[1]

Because Unicodecan be encoded as 16-bit or 32-bit integers, a computer receiving theseencodings from arbitrary sources needs to know which byte order the integers areencoded in. The BOM gives the producer of the text a way to describe the textstream's endianness to the consumer of the text without requiring some contractor metadata outside of the text stream itself. Once the receiving computer hasconsumed the text stream, it presumably processes the characters in its ownnative byte order and no longer needs the BOM. Hence the need for a BOM arisesin the context of text interchange, rather than in normal text processingwithin a closed environment.

Unicode字符的字节顺序标记(BOM)是一个用于信号的文本文件或流的字节顺序。它被编码为U +FEFF。 BOM使用是可选的,如果使用,其应该出现在文本流的头部。除了它的字节顺序指标的具体使用,同时BOM字符也表示的文本的编码格式。

Unicode编码为16位或32位的整数,计算机需要知道接收的整数顺序是何种编码。生产文本者将描述文本流的编码方式以一种无需与使用文本者进行任何接触的方式告诉文本使用者,就是通过BOM告知。一旦接收计算机消耗了文本流,它处理的字符在自己的本机字节顺序和不再需要的BOM。因此,需要一个BOM中产生文本交换的上下文中,而不是在一个封闭的环境内正常文本处理。


说白了就BOM就是文本开头几个多余的东西,来告诉使用者。我这里的东西是utf-8,还是gbk编码的。

就是这东西害死人。Java里面我还没有遇到过这样的情况。


在python的open函数很有意思。两种方法。两种效果。

首先是直接打开,直接打开的文档,读入的是str,其编码就是文档的编码格式。

<span style="font-size:14px;"></span>
<span style="font-size:14px;">infile = open("../../data/test_assembleFragment.txt","r")wfile1 = open("../../data/url_1.txt","a")           wfile2 = open("../../data/url_2.txt","a")           strs = infile.read()print type(strs)                                             #<type 'str'>s = strs.decode("utf-8").encode("gbk", "ignore")             #BOM那里面的字符好像从utf-8到gbk换不过来,需要使用ignore参数忽略无法转                                                              #换的字符wfile1.write(s)s = s.decode("gbk").encode("utf-8", "ignore")wfile2.write(s)infile.close()wfile1.close()wfile2.close()</span>

如果是用codec打开读入的是unicode。

<span style="font-size:14px;"></span>
<span style="font-size:14px;">infile = codecs.open("../../data/test_assembleFragment.txt","r", encoding='UTF-8')wfile1 = codecs.open("../../data/3.txt","a",  encoding='GBK')          wfile2 = codecs.open("../../data/4.txt","a",  encoding='UTF-8')           strs = infile.read()print type(strs)                                             #<type 'str'>s = strs.encode("GBK", "ignore")print type(s)wfile1.write(s)#s = s.decode("gbk").encode("utf-8", "ignore")wfile2.write(s)infile.close()wfile1.close()wfile2.close()</span>

目前也就弄清楚这么多。以后还有什么需要不补充的再添加。


2014-9

可恶的BOM......

情况如下:文本中存储很多单词,每个单词一行。读入程序中存为list。然后程序中设置一个单词,判断该单词是否在该list中。

设置文本仅一个单词“因此”,需要判断的单词也是“因此”,但判定就是不存在该list中。

输出两个单词,发现两个单词都是“因此”

使用cmp函数比较,结果是.....-1

没办法,将后面的因此存入list,然后print list发现两个单词的编码不同....


倒数第二行输出的list的第一个单词和最后一个都是“因此”,但是第一个单词比最后一个单词多个‘\xef\xbb\xbf’......艹