Python3爬虫实战:深入解析Unicode、bytes与文件编码处理
本文针对Python3爬虫中常见的编码错误,深入解析Unicode与bytes的转换机制。详细说明了字符串encode与bytes decode的区别,以及在不同文件写入模式('w'与'wb')下如何正确处理编码参数。通过网页抓取实例,展示了如何避免TypeError和UnicodeEncodeError,确保数据正确存储。
在进行Python爬虫开发时,尝试下载网页内容并将其全部写入txt文件,过程中遇到了报错。
具体错误包括:TypeError: write() argument must be str, not bytes;AttributeError: 'URLError' object has no attribute 'code';以及UnicodeEncodeError: 'gbk' codec can't encode character '\xa0' in position 5747: illegal multibyte sequence。
这些错误明显指向编码问题。由于网上相关资料较少且表述不够清晰,经过一整晚的研究,逐渐理清了其中的逻辑。
从基础说起,由于各国语言文字存在差异,早期计算机为表示不同语言采用了多种编码方式(如中文的gb2312)。这导致了兼容性问题,因此出现了Unicode(万国码)。在Python3中,字符串类型str默认采用Unicode编码格式,因此能够正确显示多种语言文字而不会出现乱码。
编码是指将抽象字符(Unicode)转换为二进制形式(bytes)表示的过程,对应Python3中的encode方法。解码则是将特定方式表示的二进制数据还原为Unicode,对应decode方法。
下图展示了编码的核心流程:
一、字符的编码与解码
在Python中,bytes类型的数据使用带‘b’前缀的单引号或双引号表示。
以下代码示例清晰地解释了上述流程:
s='你好'
print(s)#输出结果:你好
print(type(s))#输出结果:<class 'str'>
s=s.encode('UTF-8')
print(s)#输出结果:b'\xe4\xbd\xa0\xe5\xa5\xbd'
print(type(s))#输出结果:<class 'bytes'>
s=s.decode('UTF-8')
print(s)#输出结果:你好
print(type(s))#输出结果:<class 'str'>需要注意的是,如果对str类型字符调用decode会报错,同样,对bytes类型字符调用encode也会引发错误。
二、文件编码处理
在Python3中,字符在计算机内存中以Unicode形式存储。若要将字符写入硬盘,Python3会以bytes形式存储,因此必须对字符进行encode操作。简而言之,若以‘w’模式写入文件,内容必须是str类型;若以‘wb’模式写入,内容必须是bytes类型。文章开头出现的多种错误,正是由于写入模式与内容数据类型不匹配所致。
s1 = '你好'
#如果是以‘w'的方式写入,写入前一定要进行encoding,否则会报错
with open('F:\\1.txt','w',encoding='utf-8') as f1:
f1.write(s1)
s2 = s1.encode("utf-8")#转换为bytes的形式
#这时候写入方式一定要是‘wb',且一定不能加encoding参数
with open('F:\\2.txt','wb') as f2:
f2.write(s2)有人可能会问,为何在系统中用文本编辑器打开以bytes形式写入的2.txt文件时,显示的是‘你好’而非‘b'\xe4\xbd\xa0\xe5\xa5\xbd'’?这是因为文本编辑器在打开文件时,会自动对其进行decode操作,从而呈现可读内容。
三、网页编码处理
网页编码的处理方法与文件类似。例如,使用urlopen下载网页后,若通过decode('utf-8')进行解码,则必须以‘w’模式写入文件。如果仅使用read()而不进行编码处理,则必须采用‘wb’模式写入:
当以‘w’方式写入时:
response= url_open('https://www.jb51.net/article/157034.htm ' ,timeout=5 )
#此处以UTF-8方式进行解码,解码后的数据以unicode的方式存储在html中
html = response.read().decode('UTF-8')
print(type(html))#输出结果:<class 'str'>
#这时写入方式一定要加encoding,以encoding
# 即UTF-8的方式对二进制数据进行编码才能写入
with open('F:\DownloadAppData\html.txt',"w" , encoding='UTF-8') as f:
f.write(html)当以‘wb’方式写入时:
response= url_open('https://www.jb51.net/article/157034.htm ' ,timeout=5 )
html = response.read()#此处不需要进行解码,下载下来
print(type(html))#输出结果:<class 'bytes'>
with open('F:\DownloadAppData\html.txt',"wb" ) as f:
f.write(html)若在Python3中对urlopen获取的网页进行字符搜索(例如使用lxml.etree),必须先进行decode操作。
总结
以上就是本文的全部内容,希望这些内容对大家的Python学习或工作有所帮助。感谢支持,如需了解更多相关信息,请查阅相关链接。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









