requests之headers 'Content-Type': 'text/html'误判encoding为'ISO-8859-1'导致中文text解码错误
0.
requests不设置UA 访问baidu 得到 r.headers['Content-Type'] 是text/html 使用chrome UA: Content-Type:text/html; charset=utf-8
1.参考
iso-8859是什么? 他又被叫做Latin-1或“西欧语言”
补丁:
import requests
def monkey_patch():
prop = requests.models.Response.content
def content(self):
_content = prop.fget(self)
if self.encoding == 'ISO-8859-1':
encodings = requests.utils.get_encodings_from_content(_content)
if encodings:
self.encoding = encodings[0]
else:
self.encoding = self.apparent_encoding
_content = _content.decode(self.encoding, 'replace').encode('utf8', 'replace')
self._content = _content
return _content
requests.models.Response.content = property(content)
monkey_patch()
2.原因
In [291]: r = requests.get('http://cn.python-requests.org/en/latest/')
In [292]: r.headers.get('content-type')
Out[292]: 'text/html; charset=utf-8'
In [293]: r.encoding
Out[293]: 'utf-8'
In [294]: rc = requests.get('http://python3-cookbook.readthedocs.io/zh_CN/latest/index.html')
In [296]: rc.headers.get('content-type')
Out[296]: 'text/html'
In [298]: rc.encoding
Out[298]: 'ISO-8859-1'
response text 异常
In [312]: rc.text
Out[312]: u'\n\n<!DOCTYPE html>\n<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->\n<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->\n<head>\n <meta charset="ut
f-8">\n \n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n \n <title>Python Cookbook 3rd Edition Documentation — python3-cookbook 2.0.0 \xe6\x96\x87\xe6\xa1\xa3</tit
le>\n \n\n \n \n \n \n\n \n\n \n \n \n\n \n\n \n \n\n \n <link rel="stylesheet" href="https://media.readthedocs.org/css/sphinx_rtd_theme.css" type="text/css" />\n \n\n \n <l
ink rel="index" title="\xe7\xb4\xa2\xe5\xbc\x95"\n href="genindex.html"/>\n <link rel="search" title="\xe6\x90\x9c\xe7\xb4\xa2" href="search.html"/>\n <link rel="copyright"
title="\xe7\x89\x88\xe6\x9d\x83\xe6\x89\x80\xe6\x9c\x89" href="copyright.html"/>\n <link rel="top" title="python3-cookbook 2.0.0 \xe6\x96\x87\xe6\xa1\xa3" href="#"/>\n <link rel="next" title In [313]: rc.content
Out[313]: '\n\n<!DOCTYPE html>\n<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->\n<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->\n<head>\n <meta charset="utf
-8">\n \n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n \n <title>Python Cookbook 3rd Edition Documentation — python3-cookbook 2.0.0 \xe6\x96\x87\xe6\xa1\xa3</titl
e>\n \n\n \n \n \n \n\n \n\n \n \n \n\n \n\n \n \n\n \n <link rel="stylesheet" href="https://media.readthedocs.org/css/sphinx_rtd_theme.css" type="text/css" />\n \n\n \n <li
nk rel="index" title="\xe7\xb4\xa2\xe5\xbc\x95"\n href="genindex.html"/>\n <link rel="search" title="\xe6\x90\x9c\xe7\xb4\xa2" href="search.html"/>\n <link rel="copyright" t
itle="\xe7\x89\x88\xe6\x9d\x83\xe6\x89\x80\xe6\x9c\x89" href="copyright.html"/>\n <link rel="top" title="python3-cookbook 2.0.0 \xe6\x96\x87\xe6\xa1\xa3" href="#"/>\n <link rel="next" title=
response headers有'content-type'而且没有charset而且有'text',同时满足三个条件导致判定'ISO-8859-1'
参考文章说 python3 没有问题,实测有。
C:\Program Files\Anaconda2\Lib\site-packages\requests\utils.py
20180102 补充:# "Content-Type": "application/json" 对应 r.encoding 为 None
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'
C:\Program Files\Anaconda2\Lib\site-packages\requests\adapters.py
class HTTPAdapter(BaseAdapter):
def build_response(self, req, resp):
# Set encoding.
response.encoding = get_encoding_from_headers(response.headers)
3.解决办法
参考文章打补丁或:
20180102 补充: if resp.encoding == 'ISO-8859-1': 修改为 if r.encoding == 'ISO-8859-1' and not 'ISO-8859-1' in headers.get('content-type', ''): 即只处理按照协议最后返回的 'ISO-8859-1'
if r.encoding == 'ISO-8859-1' and not 'ISO-8859-1' in headers.get('content-type', ''):
encodings = requests.utils.get_encodings_from_content(resp.content) #re.compile(r'<meta.*?charset #源代码没有利用这个方法
if encodings:
resp.encoding = encodings[0]
else:
resp.encoding = resp.apparent_encoding #models.py chardet.detect(self.content)['encoding'] 消耗计算 # resp.text >>> if self.encoding is None: encoding = self.apparent_encoding
print 'ISO-8859-1 changed to %s'%resp.encoding
requests之headers 'Content-Type': 'text/html'误判encoding为'ISO-8859-1'导致中文text解码错误的更多相关文章
- Jsoup问题---获取http协议请求失败 org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml.
Jsoup问题---获取http协议请求失败 1.问题:用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不 ...
- Jsoup获取部分页面数据失败 org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml.
用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不符合要求. 请求代码如下: private static ...
- Jsoup获取部分页面数据失败 Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml
用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不符合要求. 请求代码如下: private static ...
- {"timestamp":"2019-11-12T02:39:28.949+0000","status":415,"error":"Unsupported Media Type","message":"Content type 'text/plain;charset=UTF-8' not supported","path":&quo
在Jmeter运行http请求时报错: {"timestamp":"2019-11-12T02:39:28.949+0000","status&quo ...
- 遇到问题之“postman报Unsupported Media Type: Content type 'text/plain;charset=UTF-8' not supported”
postman报Unsupported Media Type: Content type 'text/plain;charset=UTF-8' not supported postman之所以报Uns ...
- the request doesn't contain a multipart/form-data or multipart/form-data stream, content type header
the request doesn't contain a multipart/form-data or multipart/form-data stream, content type header ...
- Jmeter发送post请求报错Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
常识普及: Content-type,在Request Headers里面,告诉服务器,我们发送的请求信息格式,在JMeter中,信息头存储在信息头管理器中,所以在做接口测试的时候,我们维护Conte ...
- Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported告诉你,你的请求头是application/x- ...
- SharePoint自动化系列——Add content type to list.
转载请注明出自天外归云的博客园:http://www.cnblogs.com/LanTianYou/ 将创建好的content type(若是跨web application需要事先publish c ...
随机推荐
- python之内置函数(二)与匿名函数、递归函数初识
一.内置函数(二)1.和数据结构相关(24)列表和元祖(2)list:将一个可迭代对象转化成列表(如果是字典,默认将key作为列表的元素).tuple:将一个可迭代对象转化成元组(如果是字典,默认将k ...
- CF209C Trails and Glades
题目链接 题意 有一个\(n\)个点\(m\)条边的无向图(可能有重边和自环)(不一定联通).问最少添加多少条边,使得可以从\(1\)号点出发,沿着每条边走一遍之后回到\(1\)号点. 思路 其实就是 ...
- Day049--jQuery的文档操作和事件介绍
今日内容 DOM操作(CRUD) js中DOM document.createElement('p') appendChild() insertBefore() removeChild() 创建元素 ...
- source insight如何删除没用的project 及其常见问题
4年09月05日 ⁄ 综合 ⁄ 共 439字 ⁄ 字号 小 中 大 ⁄ 评论关闭 我正在中文路径下加载了一个工程,结果一点击打开,source insight程序就会出现错误提示,要求关闭.我想可能是 ...
- redis源码解析(1):redisObject对象说明
Redis在实现键值对数据库时,并没有直接使用数据结构,而是基于已有的数据结构创建了一个对象系统,每种对象至少包含一种数据结构. redis3.0 中对象结构: typedef struct redi ...
- python list的使用
list列表的常用方法有: #!/usr/bin/env python # -*- coding:utf- -*- #以下方法全在python2..x版本运行,请3.x以上的小伙伴们在print(放入 ...
- SpringCloud笔记二:搭建项目基础框架
目录 搭建框架 新建父工程 新建子工程api 新建子工程提供者provider 新建消费者consumer 总结 搭建框架 我们的SpringCloud微服务框架是父子工程,有一个父工程,剩下的都是子 ...
- Entity Framework入门教程(5)---EF中的持久化场景
EF中的持久性场景 使用EF实现实体持久化(保存)到数据库有两种情况:在线场景和离线场景. 1.在线场景 在线场景中,context是同一个上下文实例(从DbContext派生),检索和保存实体都通过 ...
- [物理学与PDEs]第4章第2节 反应流体力学方程组 2.1 粘性热传导反应流体力学方程组
1. 记号: $Z=Z(t,{\bf x})$ 表示未燃气体在微团中所占的百分比 ($Z=1$ 表示完全未燃烧; $Z=0$ 表示完全燃烧). 2. 物理化学 (1) 燃烧过程中, 通过化学反应 ...
- Coursera, Big Data 2, Modeling and Management Systems (week 4/5/6)
week4 streaming data format 下面讲 data lakes schema-on-read: 从数据源读取raw data 直接放到 data lake 里,然后再读到mode ...