传智播客Python培训之5分钟战胜Python字符编码

2017-11-07 来源: 中国网 作者:

  本文内容针对的是Python 2.7,因为3的编码已经有了很大的改善并且实际原理一样,更改一下操作命令即可。在本篇文章中,不谈复杂的理论,就传智播客总结的经验,教你字符处理八字真言:确定编码,同类交互。了解完本文后,你就可以轻松解决文字处理,特殊平台下的编码和爬虫编码等问题了。

  1. 原理 

  为了理解方便,这里不谈理论只做类比,具体想要进一步了解各种编码的理论的百度一下或搜索传智播客官网咨询就好了。

  (1)首先说一下我们为什么会碰到各式各样的编码问题:

  因为我们没有统一编码;

  因为我们没有用对命令(传对数据)。

  (2)再说一下编码是什么,Python的编码看似复杂,实际上可以看做只有两类编码:Unicode,二进制。

  Unicode 相信都很熟悉:,就是\u0000这样的;

  二进制编码也很简单,就是\x00\x00这样的,平常看到的utf-8,cp936都是二进制编码;

  二进制编码是具象的,10001100原样就可以存储,而Unicode是抽象的,不能这样存。

  #coding=utf8

  # Unicode编码演示

  print('Unicode:')

  print(repr('Unicode编码'))`

  # 二进制编码演示

  print(u'二进制编码:')

  print(repr('Unicode编码'))`

  # 这里只是看个样子,代码不必去深究

  (3)再说怎么做,就是只有同种编码之间才可以操作,举个简单的类比:

  就把一串数据比为烤鸭,我们作为人和鸭子不同种看待烤鸭的态度完全不一样。

  我们看到的是晚上的配菜,鸭子看到的是自己二舅。

  如果我用鸭子的眼光逛烤鸭店的时候就会出问题。

  因为我在烤鸭店看到了都是自己的二舅。

  这里说的同种就是我们熟悉的各种编码方式:utf-8,unicode,ucs-bom

  这也就是编码问题的核心,非常重要。

  (4)最后说一下Python的环境

  本身代码是用Ascii解码的,文件里有Ascii无法解码的内容的话要告知Python怎么解码。

  内部大量命令都是默认接受Unicode。

  # 告知的命令就是下面这一行,删掉就会报错

  #coding=utf8

  print(u'测试编码')

  2. 具体操作 

  拿到各种编码的内容自然是不用说,那么如果我们想要自己构造怎么做呢,看下面:

  #coding=utf8

  # 字符串前面加u会默认构造出Unicode的字符串

  unicodeString = u'Unicode字符串'

  # 字符串前面什么都不加会构造出默认编码(首行限定了现在的utf8)的字符串

  utf8String = 'Utf-8字符串'

  # 当然,没有首行,默认的编码是Ascii

  那么他们之间怎么转换呢,同样很简单:

  # 接上一段程序

  # Unicode转化为二进制编码中的一种:utf8

  unicodeString.encode('utf8')

  # 二进制编码根据自己的编码种类转化为Unicode

  utf8String.decode('utf8')

  # 如果二进制编码中混进了奇怪的东西可以根据需求用特殊的decode策略

  print(repr('u8字\x00符串'.decode('utf8', 'replace')))

  那么怎么样会出现问题呢:

  # 接着上一段程序说

  # 如果我们把他们转化成同样的编码方式就可以操作(例如相加)

  print(repr(unicodeString + utf8String.decode('utf8')))

  print(repr(unicodeString.encode('utf8') + utf8String))

  # 但如果不转化,当然就会出现满世界的烤鸭二舅啦

  unicodeString + utf8String

  # 所以另一方面也发现,编码转换是需要我们告诉程序怎么做的

  # 所有`decode`操作都会生成Unicode编码,这是为了方便之前说的大量接受Unicode的内部命令

  所以我们需要确定程序使用的编码,这是我们需要告诉程序的东西。一方面在操作字符串的时候确定是同种编码,另一方面在使用非自己写的命令时,一般使用Unicode,或者使用接收二进制编码的命令。

  #coding=utf8

  # 这里拿写入文件举例

  # 一般使用Unicode

  with open('Unicode.txt', 'w') as f: f.write(u'Unicode测试')

  # 或者使用接收二进制编码的命令

  with open('Utf8.txt', 'wb') as f: f.write('Utf8测试')

  # 你可以反过来做个测试,自然会报错

  # 二进制的命令方便了在不知道怎么解码的情况下也能进行操作(写入文件)

  3. 建议的使用习惯 

  我们为什么会碰到各式各样的编码问题:因为我们没有统一编码,因为我们没有用对命令(传对数据)。所以这里再重申一下八字真言:确定编码,同类交互,碰到问题,问一下自己,我现在是哪种编码?同一种编码才能交互,那我应该是哪种编码?

  在这里,传智播客给出了一些使用习惯建议:

  确定一种内部编码,内部编码的选择优先级如下:程序必须使用的编码、第三方包使用的编码、你喜欢的编码、Unicode;

  在输出时再更改到特定的编码;

  记得在开始整个程序之前确定内部的编码,否则编码一团糟会产生很多不必要的bug;

  不要迷信内部Unicode,例如Evernote开发就应该根据第三方包使用的Utf8确定内部编码。

  4. 疑难问题解答 

  (1)编码识别

  说了要确定编码,那么拿到一串二进制要怎么确定编码呢?最简单的方法是chardet:(需要安装)

  python -m pip install chardet

  使用非常简单:

  #coding=utf8

  from chardet import detect

  print(detect('这是一串utf8的测试字符'))

  # 结果:`{'confidence': 0.99, 'encoding': 'utf-8'}`

  另外例如抓取网站,那么头文件中很有可能有提示如何解码,记得不要忘记了。

  (2)编码转换

  很可能因为字符串中参杂了奇怪的东西,导致即使编码种类正确,依旧无法解码。这里可以使用decode的第二个参数:

  #coding=utf8

  # 字符串中混进了\x00

  rubbishUtf8String = 'Utf-8字\x00符串'

  print(repr(rubbishUtf8String.decode('utf8', 'replace')))

  print(repr(rubbishUtf8String.decode('utf8', 'ignore')))

  (3)特殊平台下编码

  很多人都说Windows是个坑,即使在Python 3下面也一样。因为中文文件名出来都是乱码。这里使用一个取巧的方法:平台编码再特殊,起码命令行读取和创建一个文件夹不会出乱码吧。

  import sys, os

  for folder in os.walk('.').next()[1]:

  print(folder.decode(sys.stdin.encoding))

  同样的输入输出也可以这样做优化:

  import sys

  def sys_print(msg):

  print(msg.encode(sys.stdin.encoding))

  def sys_input(msg):

  return raw_input(msg.encode(sys.stdin.encoding)).decode(sys.stdin.encoding)

  (4)文件写入

  如果抓下来一个内容不知道怎么解码,但还是想要写入文件怎么办?写入文件的时候制定用二进制命令即可:

  #coding=utf8

  import urllib

  with open('Utf8.txt', 'wb') as f: f.write('Utf8测试')

  # 比如抓了个网页,不知道编码也可以写入文件进行一系列操作

  content = urllib.urlopen('http://www.baidu.com').read()

  with open('baidu.txt', 'wb') as f: f.write(content)

  (5)裸Unicode字符

  Unicode存成六个Ascii字符怎么办?其实也可以decode

  #coding=utf8

  # 这是普通的Unicode

  s = u'测'

  for i in s: print(i)

  print(repr(s))

  # 这是裸Unicode,实际存成了六个Ascii

  s = repr(s)[2:-1]

  for i in s: print(i)

  print(repr(s))

  # 转化其实也很简单

  s = s.decode('unicode-escape')

  for i in s: print(i)

  print(repr(s))

返回枣庄大众网首页>>

初审编辑:张敏

责任编辑:徐梦

相关新闻
推荐阅读
  • 枣庄市学习贯彻党的十九大精神宣讲团成立

    11月6日,枣庄市学习贯彻党的十九大精神宣讲团成立暨宣讲工作动员会在市政大厦召开。会议传达了市委书记、市人大常委会主任李同道关于开展好党的十九大精神集中宣讲活动的批示。市委常委、宣传部部长李爱杰出席并...[详细]

    2017-11-07枣庄日报