使用urllib调用REST API时UTF-8编码丢失问题求助
问题描述
使用urllib向REST API发起HTTP请求,所有数据均为UTF-8编码的JSON格式。遇到的问题是:通过API读取特殊字符(如90°C的°编码为0xc2 0xb0)是正确的,但回传时编码丢失(°变为0xb0)。
测试情况:将响应以字节写入文件时编码正确,但用json.loads解析后写入文件,编码丢失。测试代码如下:
resp = urllib.request.urlopen(req,context=context) r = resp.read() print(f'resp: {r}') f = open('test-utf8','wb') f.write(r) f.close() content = json.loads(r) print(content) f = open('test2-utf8','w') f.write(content['descrizione']) f.close()
用json.loads解析后的数据发起新请求时,报错:
unable to decode byte 0xb0 near '"'
尝试使用encode('utf-8')和decode('utf-8')处理后发送请求仍无效,请问问题出在哪里?
问题分析与解决
核心问题
- 文件写入未指定UTF-8编码:使用
open('test2-utf8','w')时,Python默认采用系统编码(如Windows下的GBK)写入,将Unicode字符°(U+00B0)直接转为单字节0xB0,而非UTF-8要求的双字节0xC2 0xB0,导致编码信息丢失。 - 请求序列化未遵循UTF-8规范:直接对解析后的字符串做encode/decode操作,没有用
json.dumps()正确序列化JSON,导致生成的字节流中出现单独的0xB0(UTF-8中续字节不能单独存在),触发API解码错误。
解决方法
写入文件强制指定UTF-8编码
修改文件打开方式,明确指定encoding='utf-8',确保字符按UTF-8编码写入:f = open('test2-utf8','w', encoding='utf-8') f.write(content['descrizione']) f.close()发起请求时正确序列化JSON数据
使用json.dumps()将字典序列化为UTF-8编码的字节流,而非手动处理字符串编码:# 序列化数据为UTF-8编码的JSON字节 payload = json.dumps(content, ensure_ascii=False).encode('utf-8') # 构造请求,指定Content-Type头说明编码 req = urllib.request.Request( url, data=payload, headers={'Content-Type': 'application/json; charset=utf-8'} ) # 发送请求 resp = urllib.request.urlopen(req, context=context)ensure_ascii=False:避免特殊字符被转义为\u00b0这类ASCII序列,保留原字符。encode('utf-8'):将序列化后的字符串转为符合要求的UTF-8字节流。
规范读取响应的编码处理
读取响应时先按正确编码解码为字符串,再解析JSON,减少潜在编码问题:resp = urllib.request.urlopen(req, context=context) # 从响应头获取编码,默认使用UTF-8 encoding = resp.info().get_content_charset('utf-8') response_str = resp.read().decode(encoding) content = json.loads(response_str)
内容的提问来源于stack exchange,提问作者calabrone
相关产品推荐
相关产品推荐

