Python Requests中文编码问题

由于需要帮助一个用户查询退款渠道,用Python的Requests类库封装调用了微信的退款查询接口。但是返回的中文总是乱码。尝试了设置# encoding=utf-8,还有sys encoding设定以及字符串encode(‘utf-8’)转换函数, 依旧是乱码。顺着调用路径找到了请求退款时使用了Requests包去处理。初步怀疑问题可能在这里。

# encoding=utf-8

import requests
import sys 
reload(sys) 
sys.setdefaultencoding("utf-8")

# data = ''
# url = 'https://gw.tenpay.com/gateway/normalrefundquery.xml'
# response = requests.post(url, data=data, timeout=5)
# result = response.text
# ... 省略一些操作,得到最终结果 result
result = u'\xe6\x94\xaf\xe4\xbb\x98\xe7\x94\xa8\xe6\x88\xb7\xe7\x9a\x84\xe9\x9b\xb6\xe9\x92\xb1'
print result.encode('utf-8') #输出乱码 支付用户ç
print result.encode('Latin-1', 'ignore').decode('utf-8')

其实之前也遇到过一次这种问题,记得当时尝试了几种转码方案。最后找到了答案 将result.encode(‘Latin-1’, ‘ignore’).decode(‘utf-8’) 就可以正常输出正常中文了。

今天正好有时间就看了下为什么要转换成latin-1?

  1. 分析代码发现requests请求回来时用了response.text取出数据。
  2. 打印了response.encoding 输出结果居然是’ISO-8859-1′

为什么会有’ISO-8859-1’编码,怀疑是requests做了一些编码转换。搜索了下requests源码,果然找到了requests/util.py一段代码:

def get_encoding_from_headers(headers):
    """Returns encodings from given HTTP Header Dict.
    :param headers: dictionary to extract encoding from.
    :rtype: str
    """

    content_type = headers.get('content-type')

    if not content_type:
        return None

    content_type, params = cgi.parse_header(content_type)

    if 'charset' in params:
        return params['charset'].strip("'\"")

    if 'text' in content_type:
        return 'ISO-8859-1'

发现requests果然对代码做了编码转换,当获取的xml中没有编码时。会默认采用ISO-8859-1编码,也称为Latin-1编码。

所以自己程序流程中需要先将unicode进行Latin-1编码再解码成utf-8。得到正确的结果。Unicode编码在Python 2.x中还真是一个头疼的角色,以后还需要深入研究下。

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>