再也不用担心网页编码的坑了!

栏目: Python · 发布时间: 6年前

内容简介:再也不用担心网页编码的坑了!

首先,response.content返回的内容 是二进制内容

response.text 则是根据设置的encoding来解码

# Try charset from content-type  
content = None  
encoding = self.encoding  
  
if not self.content:  
  return str('')  
  
# Fallback to auto-detected encoding.  
if self.encoding is None:  
    encoding = self.apparent_encoding  
  
# Decode unicode from given encoding.  
try:  
    content = str(self.content, encoding, errors='replace')  
except (LookupError, TypeError):

我们可以看到 ,当encoding为None的时候,

编码是通过chardet.detect来获取的,

def apparent_encoding(self):  
"""The apparent encoding, provided by the chardet library."""  
    return chardet.detect(self.content)['encoding']

那么chardet.detect 又是干嘛的呢?

简单的讲,就是根据给定的字节,来返回他的编码

至于他是如何实现的,欢迎去看源代码。。。

上面说到了当encoding为None的时候,requests是如何设置encoding的

那么encoding 默认编码是啥呢?继续查看源代码

我们在adapters.py 里面找到了~

response.encoding = get_encoding_from_headers(response.headers)

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'

简单讲就是 如何返回头里面没有content_type,则encoding为None

如果charset在参数里面的话,则使用charset设置的值(看下图,github返回的)

再也不用担心网页编码的坑了!

如果text在参数里面的话,则使用 ISO-8859-1

然后你打印下 你乱码网页的encoding,发现,还真是 ISO-8859-1

再也不用担心网页编码的坑了!

你会很奇怪,为啥当content-type为text/html的时候,编码为iso-8859-1呢?

再也不用担心网页编码的坑了!

现在常见的编码不是utf8么,requests怎么这么傻*呢...

然后发现是rfc2016的规定。。。

rfc2016的链接在 https://www.ietf.org/rfc/rfc2616.txt

感兴趣的同学可以自行查阅...

再也不用担心网页编码的坑了!

最后总结

当返回头没有content_type 的时候,encoding使用chardet.detect 猜测出来的编码(一般都是很准的)

当返回头里面有content_type 的时候,如果有charset=xxx,则encoding的编码为chatset的值。如果只是text/html,则编码为ISO-8859-1

那么当你发现response.text返回乱码的时候,怎么办呢。。。

只要先设置编码为None...

再打印.text就可以了..

response.encoding = None  
response.text

本来呢,本篇文章到此结束了。。。但是呢。。。

科普个小知识

有几种方法可以知道网页的编码呢?

  1. 我们上面讲过的 response.headers中的content_type
  2. 通过chardet.detect猜测出来(上面讲过的)
  3. 网页源代码中的 meta(且有charset的值)如下面的,则表示网页编码为gb2312(不过呢,有时候并不是很准,这个是前端瞎xx写的,这时候就可以用chardet.detect来猜测了...)

方法3的代码如何写呢(如下)

def get_encodings_from_content(content):  
"""Returns encodings from given content string.  
    :param content: bytestring to extract encodings from.  
    """  
    warnings.warn((  
'In requests 3.0, get_encodings_from_content will be removed. For '  
        'more information, please see the discussion on issue #2266. (This'  
        ' warning should only appear once.)'),  
        DeprecationWarning)  
  
    charset_re = re.compile(r'<meta.*?charset=["\']*(.+?)["\'>]', flags=re.I)  
    pragma_re = re.compile(r'<meta.*?content=["\']*;?charset=(.+?)["\'>]', flags=re.I)  
    xml_re = re.compile(r'^<\?xml.*?encoding=["\']*(.+?)["\'>]')  
  
    return (charset_re.findall(content) +  
            pragma_re.findall(content) +  
            xml_re.findall(content))

你会看到requests3.0版本的时候,这个方法会去掉,这又是为什么呢。。。

截图自己看把,地址在https://github.com/requests/requests/issues/2266

再也不用担心网页编码的坑了!

如果还有猜测编码的方法,欢迎留言

完...


以上所述就是小编给大家介绍的《再也不用担心网页编码的坑了!》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

解密硅谷

解密硅谷

[美]米歇尔 E. 梅西纳(Michelle E. Messina)、乔纳森 C. 贝尔(Jonathan C. Baer) / 李俊、李雪 / 机械工业出版社 / 2018-12 / 50.00

《解密硅谷》由身处硅谷最中心的连续创业者米歇尔·梅西纳和资深的投资人乔纳森·贝尔联合撰写,二人如庖丁解牛一般为读者深入剖析硅谷成功的原因:从硅谷的创新机制、创业生态、投资领域的潜规则、秘而不宣的价值观等角度,让阅读本书的人能够在最短的时间内,拥有像硅谷人一样的商业头脑,从而快速发现机遇,顺利地躲过创业的坑,熬过创业生死挑战中的劫数,带领初创公司顺利地活下去,并实现快速增长。 如果初创公司能够......一起来看看 《解密硅谷》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试