• python编码问题


    以抓取网易图片的程序为例说明python的编码问题,主要涉及python中文乱码,unicode和str类型转换,python解释器处理编码方式等问题。

     1 #coding:utf-8
     2 import sys 
     3 reload(sys) 
     4 sys.setdefaultencoding('utf-8') 
     5 
     6 import re
     7 import requests
     8 import os
     9 import urllib
    10 
    11 def down_pic(url):
    12     pic_html = requests.get(url)
    13     if pic_html.status_code == 200:
    14         pic_html_text = pic_html.text
    15         #print pic_html.encoding
    16         #print pic_html_text
    17 
    18         #获取所有图片url,选择图片均为大图
    19         pic_gallery_patt = r'"oimg": "(.+?.jpg)"'
    20         #获取图片链接的主题
    21         title_patt = r'<title>(.+?)</title>'
    22         #获取图片的名称
    23         img_name_patt = r'"id": "(.+?)",'
    24 
    25         img_text = re.findall(pic_gallery_patt, pic_html_text)
    26         title_name = re.findall(title_patt, pic_html_text)
    27         file_name = re.findall(img_name_patt, pic_html_text)
    28 
    29         #创建文件夹,需要处理转义符
    30         curr_path = os.getcwd()
    31         curr_path = curr_path.replace('\', '/')
    32         file_dir = curr_path + '/'
    33         if os.path.exists(file_dir):
    34             file_dir += title_name[0]        
    35         file_dir += '/'
    36         #curr_path 是str类型,title_name[0]是unicode类型
    37         #print type(file_dir)
    38         #直接将unicode作为参数传入mkdir()方法,Python将先使用源代码文件声明的字符编码进行编码然后写入
    39         os.mkdir(file_dir)
    40         
    41         print '开始下载......'
    42 
    43         for dic in zip(img_text,file_name):
    44             #requests模块抓取的网页内容为unicode类型,可以用encode可以转换为utf-8编码的str类型
    45             img_utf8_url = dic[0]
    46             #生成图片存储路径
    47             file_name_str = dic[1]
    48             file_type = ".jpg"
    49             #unicode类型和str类型连接生成新对象为unicode类型
    50             filepath = file_dir + file_name_str + file_type           
    51             print img_utf8_url, filepath  
    52             #filepath为unicode类型,normcase函数会把filepath自动处理成系统可以使用的字符串
    53             #filepath = os.path.normcase(filepath)         
    54             urllib.urlretrieve(img_utf8_url, filepath)
    55 
    56         print '下载完成......'
    57 
    58 
    59 if __name__ == '__main__':
    60     pic_url = r'http://news.163.com/photoview/00AP0001/37116.html?from=tj_day#p=96A9I01H00AP0001'
    61     down_pic(pic_url)

    1.python中的str和unicode

      首先,程序的第一步是用requests模块获取网页,pic_html.text获得响应内容,以 unicode表示(如果用pic_html.content,内容将以bytes表示)。

    file_dir += title_name[0]是为了生成文件目录,但是file_dir是str类型,title_name[0]是unicode类型,连接之后是什么类型呢?用type函数查看file_dir发现是unicode类型。说明一个unicode类型和str类型连接得到的是unicode类型。

      下面解释一下str和unicode:

      str和unicode都是basestring的子类。严格意义上说,str其实是字节串,它是unicode经过编码后的字节组成的序列。对UTF-8编码的str'汉'使用len()函数时,结果是3,因为实际上,UTF-8编码的'汉' == 'xE6xB1x89'。

      unicode才是真正意义上的字符串,对字节串str使用正确的字符编码进行解码后获得,并且len(u'汉') == 1。

      我们看一下unicode的解释:

      Unicode字符串
      Unicode是书写国际文本的标准方法。如果你想要用你的母语如北印度语或阿拉伯语写文本,那么你需要有一个支持Unicode的编辑器。类似地,Python允许你处理Unicode文本——你只需要在字符串前加上前缀u或U。例如,u"This is a Unicode string."。

      记住,在你处理文本文件的时候使用Unicode字符串,特别是当你知道这个文件含有用非英语的语言写的文本。  

      str其实是字节串,它是unicode字符串经过编码(encode)后的字节组成的序列。unicode是str字符串经过解码(encode)后的字符串
      encode和decode的使用:

      (unicode字符串).encode是指将unicode转换成其他格式的编码
      例:u'中文'.encode('utf8')将unicode字符串(u'中文')转换成utf8编码

      (str字符串).decode是指将其他格式的编码转换成unicode
      例:'中文'.decode('utf8')将utf8字符串转换成unicode编码

      就像下面这样使用

    1 s = '你好'
    2 print s
    3 s.decode('utf-8')
    4 print s
    5 s1 = u'你好'
    6 print s1
    7 s1 = s1.encode('utf-8')
    8 print s1

      但是如果你直接在IDLE这样用就会报错,因为终端的默认编码设置为ascii,即s的编码是ascii,然而decode('utf-8')却是将utf8字符串转换成unicode编码。

      如果decode('ascii')呢?由于ASCII无法将中文转成unicode,所以它仍然会报错了。

      2. python中文乱码

    1 s1 = u'你好'
    2 print s1
    3 s1 = s1.encode('utf-8')
    4 print s1

      在IDLE中,print s1会输出乱码,因为print只是把字节串传递给操作系统,而由操作系统决定以何种编码输出。对于unicode,就依赖于stdout的输出编码。由于stdout的默认输出编码为ascii,所以出错。同样s1转码后,以ascii编码输出utf8编码的字符串也会出错。

      如果你要处理的程序中有中文,最好在开头加上:

    1 #coding:utf-8  
    2 import sys 
    3 reload(sys) 
    4 sys.setdefaultencoding('utf-8') 

      推荐utf-8,不推荐cp936。

      建议: 使用字符编码声明,并且同一工程中的所有源代码文件使用相同的字符编码声明。

      如果你用sublime text2编写python程序,可能sublime text2已经把编码默认设为utf-8。但是为了万无一失,同样在文件头加上上述代码。

      不管是str还是unicode,字符串在python内部的表示都是unicode编码,它相当于一种统一的中间编码。所以经常会需要从其他编码成unicode,或者从unicode解码到其他编码。这就意味着,对于代码文件,或者其他内容,不管这些内容的编码是ASCII还是UTF-8,python都会把这些内容转换成它所接受的编码—即unicode。
      python解析器读取代码文件本身时,会试图把它转成unicode。但是上面的代码文件中出现了中文,并且文件头上没有任何的编码声明,python就会试图采用默认的ASCII编码来把中文转成unicode,但是显然,ASCII无法将中文转成unicode,所以它报错了。
      在文件的第一行加上声明:#coding=编码字符串,注意声明的编码必须与文件实际保存的编码一致

      3.什么os.mkdir()和urllib.urlretrieve(url, filepath)能够接受unicode类型?

       可以参考对python读写文件的解释:

      open()打开文件时,read()读取的是str,读取后需要使用正确的编码格式进行decode()。
      write()写入文件时,如果参数是 unicode,则需要使用你希望写入的编码进行encode();如果是其他编码格式的str,则需要先用该str的编码进行decode(),转成 unicode后再使用写入的编码进行encode();如果直接将unicode作为参数传入write()方法,Python将先使用源代码文件声明的字符编码进行编码然后写入。

      os.mkdir()和urllib.urlretrieve(url, filepath)同理。

  • 相关阅读:
    206. 反转链表
    JAVA 排序总结
    Codeforces Round #674 (Div. 3)
    【BM模板】
    【 lca 】最近公共祖先
    【 欧拉函数 】GCD
    【 裴蜀定理 】Border
    【调和级数 && 欧拉常数】 Harmonic Number
    【Lucas定理】组合数取模算法
    【 最短路 && 思维 】Escape Plan
  • 原文地址:https://www.cnblogs.com/lkprof/p/3260773.html
Copyright © 2020-2023  润新知