requests模块

有些RESTful api返回中文时是Unicode转义序列

response.request.post(url, json=json_data)
print(response.text)  # 中文变成了Unicode转义序列
print(response.json())  #  正常显示中文

首先,这个问题取决于服务端接口返回的原始内容。 当服务端返回原始内容时就把中文以Unicode转义序列的形式返回,就会遇到这个问题。
而如果服务端在返回时,原始内容中就直接以中文显示,则不会有任何问题。

对于服务器端以Unicode转义序列返回时,reponse.text会显示转义序列,这毫无疑问。 但reponse.json()就可以显示中文,这是为什么呢? response.json()相当于json.load(reponse.text), 在将其转化为dict的过程中,转义序列就正常转回中文字符了。
python早期会在使用json格式传播数据时,把非ascii字符都使用unicode转义序列放在json数据中。例如json.dumps(dict),里面参数ensure_ascii参数的默认值就是True。

而正常情况下,我们直接打印转义序列就可以看到中文。

a = "\u60a8\u597d\uff01\u6211\u662f\u4e00\u4e2aAI\u52a9\u624b\uff0c\u6211\u5e76\u4e0d\u77e5\u9053\u60a8\u7684\u5177\u4f53\u59d3\u540d\uff0c\u56e0\u4e3a\u60a8\u8fd8\u6ca1\u6709\u544a\u8bc9\u6211\u3002\u5982\u679c\u60a8\u613f\u610f\u5206\u4eab\uff0c\u53ef\u4ee5\u544a\u8bc9\u6211\u60a8\u7684\u540d\u5b57\u54e6\u3002"

print(a)

输出结果:
您好!我是一个AI助手,我并不知道您的具体姓名,因为您还没有告诉我。如果您愿意分享,可以告诉我您的名字哦。

response.encoding: 此属性是requests库根据响应内容推测到的编码。推测的规则是优先检查响应头里的content-type,如果里面有明确的字符编码,直接采纳,否则会再做BOM检测等等其他方式。当查看responese.text属性时,就会使用此属性的编码来动态将二进制内容进行解码。
response.content : 该属性用于直接查看请求响应的二进制内容
response.text: 该属性被调用时会动态将响应的二进制内容进行解码成普通文本。 解码时会基于一定的判断逻辑来猜测报文的编码(gbk,utf-8等等),比如从http headers中查找。如果已经明确编码,可以直接通过设置response.encoding = 'utf-8'来指定编码。
response.json(): 此函数用于将response.text内容加载为dict,或列表。 前提是response.text内容得是一个有效的json或json列表。 有时会发现,response.text是一个合法的json会json列表时,但里面的中文内容显示为Unicode转义序列,但使用response.json()就可以看到原始的中文内容。 这个问题上面已经讲过。

请求流式响应
当我们希望对服务端的响应进行流式处理时,在发送请求时传递参数stream=True。
但需要注意的是,stream=True参数控制的是客户端获取数据的方式,而不能改变服务端对数据的发送方式。即,服务端还是一次性发送所有数据,只是客户端没有一次性将数据接收到内存中,而是分块读取,这样当数据较大时,可以缓解客户端的内存压力。
iter_content(chunk_size=1, decode_unicode=False)
这个函数通过chunk_size参数控制单次读取的块大小,decode_unicode参数控制是否将字节数据进行解码,当然使用的解码编码是存放在response.encoding属性中的。

iter_lines(chunk_size=512, decode_unicode=False, delimiter=None)
这个函数默认是按行读取,当然也可以设置delimiter来控制使用其他分隔符。如果一个块即chunk_size大小的块中没有遇到换行符,那么会将新的块的内容合并在旧块上一起查找换行符。
其实iter_lines函数内部是调用了iter_content函数的。并且,根据AI的回答,内部的iter_content函数接收了iter_lines函数的chunk_size的参数,但decode_unicode是以False来运行的,也就是先接收字节数据,定位换行符后,按照换行符拆分的内容返回给iter_lines,这时再通过iter_lines函数的decode_unicode参数来判定是否需要解码。 这里值得注意的是,在不进行解码的情况下,仍然有办法定位换行符,因为每种编码中的换行符都是固定的字节码,是可以直接在字节数据中识别到的。

但我们一般使用iter_lines时都会让其解码,因为这个函数一般都用于传送文本内容,而不是图片或视频等内容。现在的大模型流式响应内容时,也是会以server-sent-event方式按照一行一个固定的json结构内容来推送的。需要注意的是,在调用模型api时,不能只在requests.post(url, stream=True)这个参数就能让服务端以sse方式返回数据,就像前面说的,这个参数只控制客户端接收数据的方式。一般大模型的api都在body中传递指定的参数内容来告诉服务端是否要以sse方式返回数据。

posted @ 2025-05-17 22:22  RolandHe  阅读(58)  评论(0)    收藏  举报