一篇文章彻底搞懂Python字符编码方式(中文编码,UTF-8,unicode,gb,gbk,中文乱码,爬虫中文乱码)

这篇具有很好参考价值的文章主要介绍了一篇文章彻底搞懂Python字符编码方式(中文编码,UTF-8,unicode,gb,gbk,中文乱码,爬虫中文乱码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

一、字符编码方式的来龙去脉。

1.字符集的含义。

2.编码方式演化过程

1.ASCII

2.GB2312、GBK

3.Unicode

4.UTF-8

二、Python的字符编码及相关操作

1.window系统的字符编码

2.Python的字符编码

1.Python中str与bytes的区别和联系

2.Python encode()方法【对str进行编码】

3.Python decode()方法【对bytes进行解码】

三.Pyhton中文乱码产生原因及常见问题的解决方法

1.中文乱码产生的原因

2.使用Requests获得网站内容后,发现中文显示乱码。

3.非法字符抛出异常。

4.读写文件的中文乱码

总结


前言

Python的字符编码问题特别是涉及到中文的显示时,乱码、报出错误一直是让新手头疼的事情。可能通过百度能搜索到解决方法,但是根据网上的方法即使解决了错误,也很可能不知道为什么这个方法能够解决这个错误。下面我根据自己的学习体验,对Python的字符编码进行一个浅显的梳理,以期对新入门Python的朋友有所帮助,如有错误望不吝赐教。


一、字符编码方式的来龙去脉。

1.字符集及字符编码的含义。

要彻底解决字符编码的问题就不能不去了解到底什么是字符集。计算机从本质上来说只认识二进制中的0和1。计算机并不识字,它实际上是把文本看做是一串“图片”,每张“图片”对应一个字符。计算机程序在显示文本时,必须借助一个记录这个文字“图片”如何显示的“图片”集合,从中找到每一个字符对应“图片”的数据,并依样画葫芦地把这个字“画”到屏幕上。这个“图片”就被称为“字模”,而记录字模显示数据的集合就被称为“字符集”。

为方便程序查找,每个字符的字模数据在字符集中必须是有序排列的,而且每个字符都会被分配一个独一无二的ID,这个ID就是字符的编码。而在计算机进行字符数据处理时,总是用这个编码代表它表示的那个字符。也就是字符编码格式。

2.编码方式演化过程

1.ASCII

美国人发明了计算机,制定了一套叫ASCII编码格式,用于表示26个英文字母大小写.每个编码一个字节,每个字节8位二进制位(今天的计算机大部分都已经是64位了,也就是一个字节64位二进制)。ASCII 码使用指定的7 位或8 位二进制数组合来表示128 256 种可能的字符。这样在大部分情况下,英文与二进制的转换就变得容易多了。

2.GB2312、GBK

但是对于中国人来说,8位的二进制ASCII码完全不够表示几千个汉字的需要,为了解决这个问题中国国家标准总局1980年发布《信息交换用汉字编码字符集》提出了GB2312编码,用于解决汉字处理的问题。1995年又颁布了《汉字编码扩展规范》(GBK)(GB2312是简体汉字编码规范,但GBK是大字符集,不仅包含了简体中文,繁体中文还包括了日语、韩语等所有亚洲文字的双字节字符。)。最新汉字编码标准GB18030,其中已经可以支持中日韩以及藏文、蒙文,维吾尔文等少数民族文字。这样我们就解决了计算机处理汉字的问题了。
 

3.Unicode


日本人也推出了一套shift_JIS编码,用于表示日本
韩国人也推出了一套Euc_kr编码,用于表示韩文

全世界有上百种语言,每种语言都推出一套编码,而且互不兼容的话,是非常麻烦的一件事,只能自己跟自己玩。
于是Unicode编码应运而生,Unicode把所有语言都统一到一套编码里,实现了编码大统一,各国之间的编解码再也不会出现乱码了.Unicode一般用两个字节表示一个字符,极为生僻的字符会用到四个字节。Unicode又被称为统一码、万国码;它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。


4.UTF-8

问题又来了,美国人说,我本来一个字节就够用了,现在用Unicode编码的话至少一个字符要用到两个字节,多出来的一个字节不是白白浪费内存空间嘛,这确实是个问题。于是大家一商量又推出了一套叫做UTF-8的编码格式。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:

字符 ASCII Unicode UTF-8
A 01000001 00000000 01000001 01000001
x 01001110 00101101 11100100 10111000 10101101

从上面的表格还可以发现,UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。

二、Python的字符编码及相关操作

了解了编码格式的演化过程,下面就进入编码格式的具体工作方式:

1.window系统的字符编码

Python的字符编码与系统字符编码息息相关,在了解Python编码前我们先看一下系统字符编码相关的知识。

计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件:

python encoding=utf-8,Python字符编码,python,爬虫,网络协议,前端,http

浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器:

python encoding=utf-8,Python字符编码,python,爬虫,网络协议,前端,http

所以你看到很多网页的源码上会有类似<meta charset="UTF-8" />的信息,表示该网页正是用的UTF-8编码。

2.Python的字符编码

在Python 3版本中,字符串类型是str是以Unicode编码的,也就是说Python的字符串支持多语言,在内存中以Unicode表示,一个字符对应若干个字节如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。在操作字符串时,我们经常遇到str和bytes的互相转换,为了避免乱码问题,应当始终坚持使用UTF-8编码对str和bytes进行转换。我们可以通过decode和encode方法对str和bytes进行转换,具体如下。

python encoding=utf-8,Python字符编码,python,爬虫,网络协议,前端,http
 

 下面具体分析一下在Python中,str与bytes的区别和转换。

1.Python中str与bytes的区别和联系

str主要在程序运行过程中使用运行于内存,unicode编码。bytes主要用于存储和网络传输。

字符串类型是str是以Unicode编码的。

str='字符编码'             #与str=u'字符编码'等效,只是省略了u. str为字符串是Unicode编码
print(str)
print(type(str))          #类型为 str

'''
输出:
字符编码
<class 'str'>
'''

在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。bytes类型,通过ASCII编码,如果字节存在中文会报错

bytes=b'coding'
print(bytes)
print(type(bytes))

'''
输出:
b'coding'
<class 'bytes'>
'''

bytes_error=b'中文'   #bytes为 bytes类型,通过ASCII编码,如果字节存在中文会报错!!

'''
输出:
SyntaxError: bytes can only contain ASCII literal characters.
'''

为解决这个问题,可以用通过字符串过渡,也就是先将中文存于字符串(Unicode编码),再通过encode方法选择合适编码方式进行编码,具体如下所示   

str='中文ch'
bytes_ch=str.encode('utf-8')
print(bytes_ch)
print(type(bytes_ch))
'''
输出:
b'\xe4\xb8\xad\xe6\x96\x87ch' #一个中文由3个字节表示,无法用ASCII码输出,就输出16进制表示
<class 'bytes'>
'''

在操作字符串时,我们经常遇到str和bytes的互相转换,通过deconde和encode进行str与bytes的转换,前提是使用同样的编码,否则就会产生乱码问题,具体我们后面会进行分析,为了避免乱码问题,应当始终坚持使用UTF-8编码对str和bytes进行转换。下面我们对encode和decode进行详细讲解: 

2.Python encode()方法【对str进行编码】

encode()方法为字符串类型(str)提供的方法,用于将 str 类型转换成 bytes 类型,这个过程也称为“编码”。encode() 方法的语法格式如下:

1

str.encode([encoding="utf-8"][,errors="strict"])

参数 含义
str 表示要进行转换的字符串。
encoding = "utf-8" 指定进行编码时采用的字符编码,该选项默认采用 utf-8 编码。例如,如果想使用简体中文,可以设置 gb2312。

当方法中只使用这一个参数时,可以省略前边的“encoding=”,直接写编码格式,例如 str.encode("UTF-8")。
errors = "strict" 指定错误处理方式,其可选择值可以是:
  • strict:遇到非法字符就抛出异常。
  • ignore:忽略非法字符。
  • replace:用“?”替换非法字符。
  • xmlcharrefreplace:使用 xml 的字符引用。
该参数的默认值为 strict。

注意:使用 encode() 方法对原字符串进行编码,不会直接修改原字符串,如果想修改原字符串,需要重新赋值。

将 str 类型字符串“编码方式”转换成 bytes 类型。

1

2

3

>>> str = "编码方式"

>>> str.encode('utf-8')

b'\xe7\xbc\x96\xe7\xa0\x81\xe6\x96\xb9\xe5\xbc\x8f'

此方式默认采用 UTF-8 编码,也可以手动指定其它编码格式,例如:

1

2

3

>>> str = "编码方式"

>>> str.encode('GBK')

b'\xb1\xe0\xc2\xeb\xb7\xbd\xca\xbd'

3.Python decode()方法【对bytes进行解码】

和 encode()方法正好相反,decode()方法用于将 bytes类型的二进制数据转换为 str 类型,这个过程也称为“解码”。

decode() 方法的语法格式如下:

1

bytes.decode([encoding="utf-8"][,errors="strict"])

参数 含义
bytes 表示要进行转换的二进制数据。
encoding="utf-8" 指定解码时采用的字符编码,默认采用 utf-8 格式。当方法中只使用这一个参数时,可以省略“encoding=”,直接写编码方式即可。

注意,对 bytes 类型数据解码,要选择和当初编码时一样的格式。
errors = "strict" 指定错误处理方式,其可选择值可以是:
  • strict:遇到非法字符就抛出异常。
  • ignore:忽略非法字符。
  • replace:用“?”替换非法字符。
  • xmlcharrefreplace:使用 xml 的字符引用。
该参数的默认值为 strict。

将bytes类型字符串“编码方式”转换成str类型。

1

2

3

4

>>> str = "编码方式"

>>> bytes=str.encode()

>>> bytes.decode()

'编码方式'

注意:如果编码时采用的不是默认的 UTF-8 编码,则解码时要选择和编码时一样的格式,否则会抛出异常,例如:

1

2

3

4

5

6

7

8

9

>>> str = "编码方式"

>>> bytes = str.encode("GBK")

>>> bytes.decode()  #默认使用 UTF-8 编码,会抛出以下异常

Traceback (most recent call last):

  File "<pyshell#10>", line 1, in <module>

    bytes.decode()

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd3 in position 1: invalid continuation byte

>>> bytes.decode("GBK")

'编码方式'


三.Pyhton中文乱码产生原因及常见问题的解决方法

1.中文乱码产生的原因

中文乱码问题个根本原因就是几种常见中文编码之间存在兼容性,一图胜千言

python encoding=utf-8,Python字符编码,python,爬虫,网络协议,前端,http

所谓兼容性可以简单理解为子集,同时存在也不冲突。图中我们可以看出,ASCII被所有编码兼容,而最常见的UTF8与GBK之间除了ASCII部分之外没有交集,这也是平时业务中最常见的导致乱码场景,使用UTF8去读取GBK编码的文字,可能会看到各种乱码。由于在文件存储和网络传输中具体是使用哪种编码并不明确,所以在读取解码时如果使用的解码方式不对应,就会产生乱码。

现将常见的几种情况逐一进行梳理,以供大家学习

2.使用Requests获得网站内容后,发现中文显示乱码。

例如:

import requests
from bs4 import BeautifulSoup

url='http://w3school.com.cn'
response=requests.get(url)
soup=BeautifulSoup(response.text,'lxml')
xx=soup.find('div',id='d1').h2.text
print(xx)

输出
ÁìÏ鵀 Web ¼¼Êõ½Ì³Ì - È«²¿Ãâ·Ñ

得到的结果是:ÁìÏ鵀 Web ¼¼Êõ½Ì³Ì - È«²¿Ãâ·Ñ

这是因为代码中获得的网页的响应体response和网站的编码方式不同,键入response.enconding得到的结果是ISO-8859-1。意思是Requests基于HTTP头部推测的文本编码方式是ISO-8859-1,实际网站真正使用的编码是gb2312。我们只需要声明response的正确编码方式为gb2312就可以了。

response.encoding='gb2312'。

(如果还不能解决,有可能是网页数据进行了压缩,可以使用response.content替换response.text。content会自动解码gzip和defate传输编码的响应数据,具体可以再去百度学习)

3.非法字符抛出异常。

当我们将某个字符串从GBK解码为Unicode的时候(也可能是用其他编码方式,比如'UTF-8'),可以采用上面介绍的decode方法,具体如下:

str.decode('GBK')

但实际可能会遇到如下异常

UnicodeDecodeError: 'gbk' codec can't decode bytes in position 7-8: illegal multibyte sequence

出错原因是,字符串内混入了多种编码,于是出现了非法字符,如标点符号全角半角、全角空格的不同编码实现方式存储等,只要出现一个非法字符就会报错。解决方法很简单就是采用ignore忽略,具体可以参照上面对decode函数的详细介绍。

str.decode('GBK','ignore')

4.读写文件的中文乱码

在使用Python3读取和保存文件时一定要注明编码方式。

同时在操作系统中保存的文件也应该明确系统存储时的编码方式,具体可以参照前面对系统编码方式的介绍,如记事本默认的编码方式时ANSI编码(gbk),读取时就应该使用gbk进行decode

另外,jison的保存中,如果希望能在记事本中读取中文文本,可以设置参数,ensure_ascii=false

import json
str='中文CH'
with open('ch.json','w',encoding='UTF-8') as f:
    json.dump([str],f,ensure_ascii=False)

总结

以上内容仅仅是个人学习中的一点体会,内容多为网络摘选,如有侵权可联系我处理,不对之处望不吝赐教。文章来源地址https://www.toymoban.com/news/detail-799237.html

到了这里,关于一篇文章彻底搞懂Python字符编码方式(中文编码,UTF-8,unicode,gb,gbk,中文乱码,爬虫中文乱码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 目标检测扩(六)一篇文章彻底搞懂目标检测算法中的评估指标计算方法(IoU(交并比)、Precision(精确度)、Recall(召回率)、AP(平均正确率)、mAP(平均类别AP) )

    ​ 基本在目标检测算法中会碰到一些评估指标、常见的指标参数有:IoU(交并比)、Precision(精确度)、Recall(召回率)、AP(平均正确率)、mAP(平均类别AP)等。这些评估指标是在评估阶段评价训练的网络好坏的重要依据。 计算方法 IoU: 用来评价目标检测算法的对象定

    2024年04月13日
    浏览(46)
  • 一篇文章搞懂Docker、DockerCompose

    大型项目组件较多,运行环境也较为复杂,部署时会碰到一些问题: 依赖关系复杂,容易出现兼容性问题 开发、测试、生产环境有差异 例如一个项目中,部署时需要依赖于node.js、Redis、RabbitMQ、MySQL等,这些服务部署时所需要的函数库、依赖项各不相同,甚至会有冲突。给部

    2024年01月18日
    浏览(47)
  • 一篇文章彻底清楚shellcode(精品)

    1.没开沙箱(此时我们可以系统调用get shell) (一)32位程序系统调用 32位程序有别于64位程序,32位通过栈传参,我们常用的寄存器有4个数据寄存器(eax,ebx,ecx,edx),2个变址寄存器(esi,edi),2个指针寄存器(esp,ebp). 下边我们就来看一种系统调用方式及其构造: 执行上述shellcode即可g

    2024年02月09日
    浏览(41)
  • 一篇文章搞懂华为的ACL

    随着网络的飞速发展,网络安全问题日益突出。访问控制列表 (ACL, Access Control List) 可以通过对网络中报文流的精确识别,与其他技术结合,达到控制网络访问行为、防止网络攻击和提高网络带宽利用率的目的,从而切实保障网络环境的安全性和网络服务质量的可靠性。 访问

    2024年02月06日
    浏览(43)
  • 一篇文章搞懂Git与Github

    Git 是一个开源的 分布式版本控制系统 ,Github 是 全球最大的同性交友网站 基于 Git 的 代码托管平台 ,因为只支持 Git 作为 唯一的版本库 格式进行托管,故名 GitHub,就是一个平台上面有无数个 Git 仓库——Git 版的百度云,承担存储远程仓库的作用。 唯一版本库是什么意思?

    2024年02月06日
    浏览(49)
  • 一篇文章让你搞懂内存函数

    库函数memcmp介绍 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。 这个函数在遇到 ‘\\0’ 的时候并不会停下来。 如果source和destination有任何的重叠,复制的结果都是未定义的。 库函数memcmp的代码形式 看代码 memcmp将arr1中的内容拷贝到arr2中,总共

    2024年02月17日
    浏览(42)
  • 一篇文章,带你彻底掌握接口测试!

    一、什么是接口测试? 所谓接口,是指同一个系统中模块与模块间的数据传递接口、前后端交互、跨系统跨平台跨数据库的对接。而接口测试,则是通过接口的不同情况下的输入,去对比输出,看看是否满足接口规范所规定的功能、安全以及性能方面的要求。 二、为什么要

    2024年02月10日
    浏览(50)
  • 一篇文章彻底理解自定义View

    目录 一.View的基础  1.view的基础概念 2.view的位置和事件event几种表示法 3.view的滑动

    2024年02月01日
    浏览(46)
  • 搞懂TVS管,有这篇文章就够了

    摘要:本文主要介绍TVS的工作原理、关键参数和选型。 TVS(Transient Voltage Suppressors,瞬态电压抑制器)又称雪崩击穿二极管,是一种高效电路保护器件,主要是保护电路不受瞬态高压尖峰脉冲(静电或雷击浪涌)的冲击。 TVS是采用半导体工艺制成的单个PN结或多个PN结集成的器件,

    2023年04月08日
    浏览(50)
  • 一篇文章带你搞懂前端Cookie

    浏览器Cookie相信各位点进这篇文章的小伙伴应该不陌生了,它是前端领域中一个非常重要的内容,当然也是面试的一个考点,不知道各位小伙伴是否真正掌握了Cookie呢?当然没有掌握也是没有关系的,可以跟着小编的脚步一起来学习一下前端Cookie,没有熟练掌握的小伙伴看完这

    2024年02月04日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包