这两天写了个监测网页的爬虫,作用是跟踪一个网页的变化,但运行了一晚出现了一个问题。。。。希望大家不吝赐教!
我用的是python3,错误在对html response的decode时抛出,代码原样为:
response = urllib.urlopen(dsturl) content = response.read().decode('utf-8')
抛出错误为
File "./unxingCrawler_p3.py", line 50, in getNewPhones content = response.read().decode() UnicodeDecodeError: 'utf8' codec can't decode byte 0xb2 in position 24137: invalid start byte
之前运行都没问题,经过一晚上就出现了。。。。最不明白的是在它声明为utf-8编码的网页中为什么会出现utf-8无法解析的字符?
后来经过热心网友的提醒,才发现需要使用decode('utf-8', 'ignore')
为了彻底闹明白python的编码问题,特分享下文,希望对大家熟悉python的编码问题带来些帮助
1.从字节说起:
一个字节包括八个比特位,每个比特位表示0或1,一个字节即可表示从00000000到11111111共2^8=256个数字。一个ASCII编码使用一个字节(除去字节的最高位作为作奇偶校验位),ASCII编码实际使用一个字节中的7个比特位来表示字符,共可表示2^7=128个字符。比如ASCII编码中的01000001(即十进制的65)表示字符'A',01000001加上32之后的01100001(即十进制的97)表示字符'a'。现在打开Python,调用chr和ord函数,我们可以看到Python为我们对ASCII编码进行了转换。如图
第一个00000000表示空字符,因此ASCII编码实际上只包括了 字母、标点符号、特殊符号等共127个字符。因为ASCII是在美国出生的,对于由字母组成单词进而用单词表达的英文来说也是够了。但是中国人、日本人、 韩国人等其他语言的人不服了。中文是一个字一个字,ASCII编码用上了浑身解数256个字符都不够用。
因此后来出现了Unicode编码。Unicode编码通常由两个字节组成,共表示256*256个字符,即所谓的UCS-2。某些偏僻字还会用到四个字节,即所谓的UCS-4。也就是说Unicode标准也还在发展。但UCS-4出现的比较少,我们先记住: 最原始的ASCII编码使用一个字节编码,但由于语言差异字符众多,人们用上了两个字节,出现了统一的、囊括多国语言的Unicode编码。
在Unicode中,原本ASCII中的127个字符只需在前面补一个全零的字节即可,比如前文谈到的字符‘a':01100001,在Unicode中变成了00000000 01100001。不久,美国人不开心了,吃上了世界民族之林的大锅饭,原本只需一个字节就能传输的英文现在变成两个字节,非常浪费存储空间和传输速度。
人们再发挥聪明才智,于是出现了UTF-8编码。因为针对的是空间浪费问题,因此这种 UTF-8编码是可变长短的 ,从英文字母的一个字节,到中文的通常的三个字节,再到某些生僻字的六个字节。解决了空间问题,UTF-8编码还有一个神奇的附加功能,那就是兼容了老大哥的ASCII编码。一些老古董软件现在在UTF-8编码中可以继续工作。
注意除了英文字母相同,汉字在Unicode编码和UTF-8编码中通常是不同的。比如"htmlcode">
import sys sys.getdefaultencoding()
可查看Python3的默认编码。"" src="/UploadFiles/2021-04-08/201609060847282.png">
3.Python3中的"" src="/UploadFiles/2021-04-08/201609060847283.png">
\x表示后面是十六进制, \xe4\xb8\xad即是二进制的 11100100 10111000 10101101。也就是说汉字‘中'encode成字节形式,是 11100100 10111000 10101101。同理,我们拿 11100100 10111000 10101101也就是 \xe4\xb8\xad来decode回来,就是汉字‘中'。完整的应该是 b'\xe4\xb8\xad',在Python3中, 以字节形式表示的字符串则必须加上 前缀b,也就是写成上文的b'xxxx'形式。
前文说的Python3的默认编码是UTF-8,所以我们可以看到,Python处理这些字符的时候是以UTF-8来处理的。因此从上图可以看到,就算我们通过encode('utf-8')特意把字符encode为UTF-8编码,出来的结果还是相同:b'\xe4\xb8\xad'。
明白了这一点,同时我们知道"" src="/UploadFiles/2021-04-08/201609060847284.png">
4.Python3中的"" src="/UploadFiles/2021-04-08/201609060847285.png">
b'\\u4e2d'还是b'\u4e2d,一个斜杠貌似没影响。同时可以 发现在shell窗口中,直接输 '\u4e2d'和输入b '\u4e2d'.decode('unicode-escape')是相同的,都会打印出汉字‘中', 反而是 '\u4e2d'.decode('unicode-escape')会报错。说明 说明Python3不仅支持Unicode,而且一个‘\uxxxx'格式的 Unicode字符 可被辨识且被等价于str类型。
如果我们知道一个Unicode字节码,怎么变成UTF-8的字节码呢。懂了以上这些,现在我们就有思路了,先decode,再encode。代码如下:
"" src="/UploadFiles/2021-04-08/201609060847287.png">
"htmlcode">
import codecs
file = codecs.open( "a.txt", "r", "unicode-escape" )
u = file.read()
print(u)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
更新日志
- 金元萱.1996-迷迷糊糊【宝丽金】【WAV+CUE】
- 齐秦《燃烧爱情》马来西亚版[WAV+CUE][1G]
- 动力火车《结伴》2024最新 [FLAC分轨][1G]
- 郑源《擦肩而过》[WAV+CUE][1.2G]
- 黑鸭子2008-江南四月天[首版][WAV+CUE]
- 黑鸭子2008-再醉一次·精选[首版][WAV+CUE]
- Elgar-Motdamour-UlfWallin,RolandPontinen(2024)[24bit-96kHz]FLAC
- 苏永康《 笑下去》 新曲+精选[WAV+CUE][1G]
- 周传雄《发觉》[WAV+CUE][1.1G]
- 证声音乐图书馆《真夏派对 x 浩室》[320K/MP3][67.19MB]
- 张镐哲.1994-无助【波丽佳音】【WAV+CUE】
- Relic.2024-浮在虛无的诗意【SEEAHOLE】【FLAC分轨】
- 群星.2001-台语(原主唱)排行总冠军黄金典藏版6CD【柯达唱片】【WAV+CUE】
- 证声音乐图书馆《真夏派对 x 浩室》[FLAC/分轨][379.1MB]
- 徐良《东西世界》[WAV+CUE][1.1G]