杰瑞科技汇

python request 乱码

问题根源

乱码的根本原因是 编码不一致

  1. 服务器 发送数据时,使用了某种编码(GBK)。
  2. 你的 Python 代码 在读取数据时,默认使用了另一种编码(通常是 requests 推断的 ISO-8859-1)。
  3. 当这两种编码不匹配时,解码后的自然就是一堆看不懂的乱码。

解决方案

下面我将从最简单、最推荐的解决方案开始,逐步介绍其他情况的处理方法。

使用 response.text 并手动指定编码(最推荐)

这是最直接、最常用的方法。requestsResponse 对象有一个 encoding 属性,你可以直接设置它。

步骤:

  1. 检查服务器编码:服务器会在 HTTP 响应头中通过 Content-Type 字段告诉客户端它使用了什么编码。Content-Type: text/html; charset=gbk,你可以先打印响应头来查看。

  2. 手动设置编码:在获取 response.text 之前,将正确的编码赋值给 response.encoding

示例代码:

import requests
# 假设这是一个返回GBK编码内容的网站
url = 'http://example.com/some-gbk-encoded-page' 
# 这里用知乎作为例子,它的部分页面是GBK编码
url = 'https://www.zhihu.com/question/278960545'
try:
    response = requests.get(url)
    # 1. 打印响应头,查看 Content-Type
    print("原始响应头:")
    print(response.headers)
    print("-" * 30)
    # 2. 如果看到 charset=gbk 或其他编码,就手动设置
    # 即使 response.headers 里没有 charset,但你知道是GBK,也可以手动设置
    response.encoding = 'gbk' 
    # 3. 现在再获取 text,就不会乱码了
    html_content = response.text
    # 打印前500个字符,检查是否正常
    print(html_content[:500])
except requests.exceptions.RequestException as e:
    print(f"请求失败: {e}")

为什么这是最佳实践? 因为 response.text 会自动帮你处理编码和解码,得到一个可以直接使用的字符串,而 response.content 是原始字节流,你需要自己处理编码,优先使用 response.text 并正确设置 encoding


使用 response.content 并手动解码

如果你需要处理二进制数据(如图片、PDF),或者想更底层地控制解码过程,可以使用 response.contentresponse.content 返回的是原始的字节串(bytes),你需要用 .decode() 方法将其解码成字符串。

示例代码:

import requests
url = 'http://example.com/some-gbk-encoded-page'
try:
    response = requests.get(url)
    # response.content 是 bytes 类型
    # 直接用 .decode() 指定正确的编码
    html_content = response.content.decode('gbk')
    # 打印前500个字符
    print(html_content[:500])
except requests.exceptions.RequestException as e:
    print(f"请求失败: {e}")

什么时候用这个? 当你明确需要字节流时(要把下载的图片保存到文件),或者当你对 response.text 的自动推断结果不满意,想完全掌控解码过程时。


requests 自动推断编码(不推荐用于已知乱码的情况)

requests 会尝试从响应头的 Content-Type 中提取 charset,如果找不到,它会默认使用 ISO-8859-1 编码来解码 response.textISO-8859-1 是一个“安全”的编码,因为它不会将任何字节解码成特殊字符,但几乎肯定不是你想要的中文编码。

这个方法只适用于服务器明确告知了正确编码的情况。

import requests
url = 'https://www.baidu.com' # 百度首页通常是UTF-8
try:
    response = requests.get(url)
    # 让 requests 自己去猜编码
    # 如果服务器头里是 Content-Type: text/html; charset=utf-8,那就没问题
    html_content = response.text 
    print(html_content[:500])
except requests.exceptions.RequestException as e:
    print(f"请求失败: {e}")

如果服务器没有提供 charset,或者提供了错误的 charset,这个方法就会失败,导致乱码。


实战演练:一个典型的乱码问题

假设你爬取一个老旧的论坛,页面显示为乱码。

观察现象

import requests
url = 'http://some-old-forum.com/article/123'
response = requests.get(url)
print(response.text) # 输出类似:´ÓÒâ´®ÄÚÈÝ´ó¶à...

调试:检查响应头

print(response.headers)

可能会看到类似这样的输出:

{
    'Content-Type': 'text/html; charset=GBK',  # <-- 找到了!是GBK
    'Server': 'nginx/1.0.0',
    ...
}

应用解决方案 在代码中添加一行,明确告诉 requests 使用 GBK 编码。

import requests
url = 'http://some-old-forum.com/article/123'
response = requests.get(url)
# 关键的一行:手动设置编码
response.encoding = 'gbk' 
# 现在获取的内容就是正常的中文了
article_content = response.text
print(article_content)

总结与最佳实践

方法 适用场景 优点 缺点
response.encoding = '...' 强烈推荐,当你知道或通过响应头推断出编码时。 简单、直接,response.text 返回可直接使用的字符串。 需要提前知道正确的编码。
response.content.decode('...') 需要处理二进制数据,或想手动控制解码过程时。 灵活性高,能获取最原始的字节。 需要手动处理,代码稍显繁琐。
默认 response.text 服务器明确提供了正确的 charset是标准文本(如UTF-8)。 代码最简洁。 对老旧或配置不当的服务器容易出错。

黄金法则:

  1. 遇到乱码,第一件事是 print(response.headers),查看 Content-Type 里的 charset
  2. charsetgbk, gb2312, big5 等中文编码,立即使用 response.encoding = 'gbk' 来解决。
  3. 如果没有 charset,但页面内容明显是中文,可以尝试常见的中文编码(如 gbk, utf-8)进行测试。
  4. 优先使用 response.text,只在必要时使用 response.content
分享:
扫描分享到社交APP
上一篇
下一篇