Python requests 编码问题

本文介绍了在使用Python爬取网易云音乐评论时遇到的中文乱码问题及其解决过程。问题源于requests库对网页编码判断不准确,导致中文字符无法正确解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景介绍

接着上一篇文章《Python 安装 pyecharts 和 WordCloud 报错解决》中所说,我跟着教程去爬取了网易云音乐某首歌的热评,出现了中文字符乱码的问题,而教程则没有这个问题。折腾了很久 encode 和 decode 之后仍未解决,最后想了想会不会是我自己的问题,而不是数据原始编码的问题?比对了我和作者的代码之后,我发现是爬虫课的嵩天老师给的通用爬虫框架惹的祸,且听我细细道来。

二、问题分析

我的代码(关键部分)

try:
    r = requests.post(url, headers=headers, data=user_data)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.encoding) # Windows-1256
except:
    traceback.print_exc()

这里我套用了爬虫课学到了的 try - raise_for_status - except 异常处理,这个没有问题,关键在于这一行r.encoding = r.apparent_encoding,它的作用是把修改响应头的编码为 request 分析后认为可能性最大的编码,这里它认为编码是 Windows-1256。我尝试之后发现,如果不修改 r.encoding,那么它的值是 UTF-8,也就是说网易云音乐服务器返回给我们的请求头里的编码是真正的编码,而 requests 却判断错误了,导致程序没有用正确的编码来处理中文字符。

问题又来了,为什么 r.apparent_encoding 会判断错误呢?首先还是得先说明一下为什么会在已经有 r.encoding 的情况下还要提供 r.apparent_encodinig 这个属性。

一般来说,如果 requests 得到的响应头没有指定编码或者响应头的编码不能被正常提取出来,requests 这个库会默认把 r.encoding 设置为 ISO-8859-1 (别名:latin-1) 。事实上响应的内容多数情况下不会是 ISO-8859-1,这就导致了响应 body 里的中文不能被正常解析。于是,requests 为它的响应对象增加了一个 apparent_encoding 属性,这个属性实际上是通过另一个 Python 编码检测模块 chardet 来实现的,这个结果仅仅是一种较高可能性,仍然可能会出错。

三、问题解决

我的想法是,以后爬取得到响应的时候,先判断一下 r.encoding 是否为 ISO-8859-1,如果是的话就说明响应的编码方式没有被正确获取到,这时候在运用 r.encoding = r.apparent_encoding 尝试修正。
(如果 r.apparent_encodiing 猜出来的编码仍是错误的话…)


写完文章的两个小时后发现r.encoding = r.apparent_encoding 打印 r.encoding 显示的是 utf-8,是正确的,也就是说这个是个概率事件?每一次计算可能会有不同的结果?不管怎么说程序中先判断一下 r.encoding 总是没有错的。

### Python requests库解决乱码问题编码设置 在使用Python的`requests`库时,如果遇到乱码问题,通常是由于响应内容的编码方式与实际解码方式不一致导致的。以下是几种常见的解决办法: #### 方法一:使用`apparent_encoding` 可以通过`apparent_encoding`属性来自动推断正确的编码方式,并将其设置为`response.encoding`。例如: ```python import requests res = requests.get("https://www.baidu.com/") res.encoding = res.apparent_encoding # 自动推断编码 print(res.text) ``` 这种方法适用于大多数情况下需要自动检测编码的场景[^1]。 #### 方法二:手动指定编码 如果已知目标网页的编码方式,可以直接将正确的编码方式赋值给`response.encoding`。例如: ```python import requests response = requests.get('https://example.com') response.encoding = 'utf-8' # 手动指定编码为UTF-8 print(response.text) ``` 此方法适合于明确知道目标网页编码的情况[^2]。 #### 方法三:检查`Content-Type`头中的编码信息 部分网页会在HTTP响应头的`Content-Type`字段中声明其编码方式。可以通过解析该字段来获取正确的编码。例如: ```python import requests response = requests.get('https://example.com') content_type = response.headers.get('Content-Type', '') if 'charset=' in content_type: encoding = content_type.split('charset=')[-1] response.encoding = encoding print(response.text) ``` 这种方式可以确保从服务器返回的元信息中提取正确的编码[^3]。 #### 方法四:使用第三方库`chardet`或`charset-normalizer` 对于复杂的编码检测场景,可以借助第三方库如`chardet`或`charset-normalizer`进行编码检测。例如: ```python import requests import chardet response = requests.get('https://example.com') detected_encoding = chardet.detect(response.content)['encoding'] response.encoding = detected_encoding print(response.text) ``` #### 方法五:直接操作字节流 如果以上方法均无法解决问题,可以尝试直接操作字节流并手动解码。例如: ```python import requests response = requests.get('https://example.com') decoded_text = response.content.decode('utf-8') # 手动解码为UTF-8 print(decoded_text) ``` 通过上述方法之一,通常可以有效解决`requests`库中的乱码问题。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值