Python 请求模块编码提供不同的编码,然后是HTML编码

Python 请求模块编码提供不同的编码,然后是HTML编码,python,encoding,python-requests,Python,Encoding,Python Requests,请求模块编码提供与HTML页面中实际设置的编码不同的编码 代码: import requests URL = "http://www.reynamining.com/nuevositio/contacto.html" obj = requests.get(URL, timeout=60, verify=False, allow_redirects=True) print obj.encoding ISO-8859-1 输出: import requests URL = "http://www

请求模块
编码
提供与HTML页面中实际设置的编码不同的编码

代码:

import requests
URL = "http://www.reynamining.com/nuevositio/contacto.html"
obj = requests.get(URL, timeout=60, verify=False, allow_redirects=True)
print obj.encoding
ISO-8859-1
输出:

import requests
URL = "http://www.reynamining.com/nuevositio/contacto.html"
obj = requests.get(URL, timeout=60, verify=False, allow_redirects=True)
print obj.encoding
ISO-8859-1
其中,HTML中的实际编码集为
UTF-8
content=“text/HTML;charset=UTF-8”

我的问题是:

  • 为什么
    requests.encoding
    显示的编码与HTML页面中描述的编码不同
  • 我正试图用这种方法将编码转换成UTF-8,因为当我用ISO-8859-1解码并用UTF-8编码时,它已经在UTF-8中了,所以值会发生变化,也就是说,
    á
    改变成这个
    Ã


    有没有办法将所有类型的编码转换为UTF-8?

    请求将首先检查HTTP头中的编码:

    print obj.headers['content-type']
    
    输出:

    text/html
    
    无法正确分析编码猜测的类型,因此它指定默认ISO-8859-1


    有关详细信息,请参见。

    请求将
    响应设置为
    ISO-8859-1
    ,前提是您有
    text/*
    响应且响应标题中未指定任何内容类型

    见:

    只有在HTTP头中不存在显式字符集且
    内容类型
    头包含
    文本
    时,请求才会这样做在这种情况下,RFC 2616指定默认字符集必须是
    ISO-8859-1
    。在这种情况下,请求遵循规范。如果需要不同的编码,可以手动设置
    Response.encoding
    属性,或使用原始
    Response.content

    我的

    您可以通过在
    内容类型
    标题中查找
    字符集
    参数进行测试:

    resp = requests.get(....)
    encoding = resp.encoding if 'charset' in resp.headers.get('content-type', '').lower() else None
    
    HTML文档在
    标题中指定内容类型,而此标题才是权威的:

    
    
    HTML5还定义了一个
    标记,请参见

    如果HTML页面包含具有不同编解码器的标题,则应而不是将其重新编码为UTF-8。在这种情况下,您必须至少更正该标题

    使用BeautifulSoup:

    # pass in explicit encoding if set as a header
    encoding = resp.encoding if 'charset' in resp.headers.get('content-type', '').lower() else None
    content = resp.content
    soup = BeautifulSoup(content, from_encoding=encoding)
    if soup.original_encoding != 'utf-8':
        meta = soup.select_one('meta[charset], meta[http-equiv="Content-Type"]')
        if meta:
            # replace the meta charset info before re-encoding
            if 'charset' in meta.attrs:
                meta['charset'] = 'utf-8'
            else:
                meta['content'] = 'text/html; charset=utf-8'
        # re-encode to UTF-8
        content = soup.prettify()  # encodes to UTF-8 by default
    
    类似地,其他文件标准也可规定特定编码;例如,XML始终是UTF-8,除非由
    XML声明指定,这也是文档的一部分。

    请求HTTP
    内容类型
    响应头和
    chardet
    。对于常见的
    text/html
    ,它假定默认值为
    ISO‌-8859-1
    。问题是请求不知道任何关于HTML元标记的信息,这些元标记可以指定不同的文本编码,例如

    一个好的解决方案是使用BeautifulSoup的“”功能,如下所示:

    from bs4 import UnicodeDammit
    import requests
    
    
    url = 'http://www.reynamining.com/nuevositio/contacto.html'
    r = requests.get(url)
    
    dammit = UnicodeDammit(r.content)
    r.encoding = dammit.original_encoding
    
    print(r.text)
    

    给定的代码段会为
    URL
    like
    产生
    None
    类型错误http://www.uraniumenergy.com/contact_us/contact_information
    你能说说为什么会发生这种情况以及如何避免吗?@6thsense:不知道;当我尝试它时,我没有得到任何错误。你有回溯吗?很抱歉回复晚了。我已经添加了问题的回溯,当我执行时,
    dir(soup)
    我没有得到
    select\u one
    我认为这是导致错误的原因。@6thsense:upgrade beautifulsou;这种方法相当新(在4.4.0中添加,于2015年7月发布)。@6thsense:或者,使用
    soup。选择(…)
    ,如果返回的列表不是空的,则使用第一个元素。