【问题标题】:python requests.get() returns improperly decoded text instead of UTF-8?python requests.get() 返回不正确解码的文本而不是 UTF-8?
【发布时间】:2017-10-27 10:55:33
【问题描述】:

当服务器的content-type'Content-Type:text/html'时,requests.get()返回编码不正确的数据。

但是,如果我们将内容类型明确设为'Content-Type:text/html; charset=utf-8',它会返回正确编码的数据。

此外,当我们使用urllib.urlopen() 时,它会返回正确编码的数据。

以前有没有人注意到这一点?为什么requests.get() 会这样?

【问题讨论】:

    标签: python utf-8 python-requests


    【解决方案1】:

    受过教育的猜测(上面提到的)可能只是检查Content-Type 标头是否由服务器发送(对受过教育的 imho 的使用非常误导)。

    对于响应标头Content-Type: text/html,结果为ISO-8859-1(HTML4 的默认值),无论任何内容分析(即HTML5 的默认值是UTF-8)。

    对于响应标头Content-Type: text/html; charset=utf-8,结果为UTF-8

    对我们来说幸运的是,requests 使用 chardet 库并且通常效果很好(属性 requests.Response.apparent_encoding),所以您通常想要这样做:

    r = requests.get("https://martin.slouf.name/")
    # override encoding by real educated guess as provided by chardet
    r.encoding = r.apparent_encoding
    # access the data
    r.text
    

    【讨论】:

    • 对于第 374 行的第 13 行为 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 的网页,r.encoding = r.apparent_encoding 的方法不起作用(é 显示为 é)。但是,更改为 r.encoding = 'UTF-8' 工作正常。可以使用代码在r.text 中搜索"Content-Type" ... charset=... 条目,然后在进一步访问r.text 之前设置r.encoding。这会很笨拙,但比将编码设置为 UTF-8 更通用。
    • 好吧,毕竟这是一个猜测;)。我想你意识到r.apparent_encoding 的值是由chardet 库设置的——当然——它可能猜错了。您还应该知道,您不应该访问r.text 之前r.encoding 设置为所需的值(使用r.apparent_encoding 或任何所需的方法)。我建议您阅读 chardet 库文档 (chardet.readthedocs.io/en/latest),如果您想以自己的方式猜测它——它可以提供您寻求的解决方案。
    【解决方案2】:

    来自requests documentation

    当您发出请求时,Requests 会根据 HTTP 标头对响应的编码进行有根据的猜测。访问 r.text 时会使用 Requests 猜测的文本编码。您可以使用 r.encoding 属性找出 Requests 使用的编码,并对其进行更改。

    >>> r.encoding
    'utf-8'
    >>> r.encoding = 'ISO-8859-1'
    

    检查用于您的页面的编码请求,如果它不是正确的,请尝试强制它成为您需要的。

    关于requestsurllib.urlopen 之间的区别 - 他们可能使用不同的方式来猜测编码。就是这样。

    【讨论】:

      【解决方案3】:

      text/html 的默认假定内容编码是 ISO-8859-1 aka Latin-1 :( 参见 RFC-2854。UTF-8 太年轻而无法成为默认值,它诞生于 1993 年,大约在同一时间作为 HTML 和 HTTP。

      使用.content 访问字节流,或使用.text 访问解码后的Unicode 流。如果 HTTP 服务器不关心正确的编码,.text 的值可能是关闭的。

      【讨论】:

      • 就我而言,这就是答案。 @bubak 给出的答案有效,但它对所有转换的性能都很差。 content 是关键
      • 我能够做这样的事情,以确保如果我们不能转换为我想要的,我们至少得到了一些东西。我还发现处理内容比设置编码要快得多。尝试:lContent = lResponse.content.decode('UTF-8') 除外:lContent = lResponse.content.decode(lResponse.apparent_encoding)
      【解决方案4】:

      得到响应后,使用response.content 而不是response.text,这将是编码utf-8

      response = requests.get(download_link, auth=(myUsername, myPassword),  headers={'User-Agent': 'Mozilla'})
      print (response.encoding)
      if response.status_code is 200:
          body = response.content
      else:
          print ("Unable to get response with Code : %d " % (response.status_code))
      

      【讨论】:

      • 这救了我的命。谢谢!
      猜你喜欢
      • 2016-09-27
      • 1970-01-01
      • 2016-12-21
      • 2012-05-04
      • 1970-01-01
      • 2019-05-23
      • 1970-01-01
      • 2014-11-02
      相关资源
      最近更新 更多