Requests 库 ISO-8859-1 编码问题
Requests.Response 的 encoding 保存了网页的编码类型,如:
In [5]: resp = requests.get('http://www.baidu.com') In [6]: resp.encoding Out[6]: 'utf-8'
值取自于服务器的 HTTP 响应头中 Content-type 字段的 charset:
Content-Type:text/html; charset=utf-8
服务端不会返回 charset 的情况下默认为 ISO-8859-1。为了识别出页面的编码,还可以考虑 HTML 中的 charset,以下为我写的一个提取函数:
def get_charset_from_html(html): """从 HTML 中提取编码类型 """ import re search = (re.search(r'charset=["\']([^"]+)["\']', html) or re.search('charset=\w+', html)) if not search: return None search_result = search.group() if search_result.find('=') > -1: return search_result.split('=')[1] \ .strip().replace("'", "") \ .replace('"', "") return None def test_get_charset_from_html(): assert(get_charset_from_html("<meta charset='gbk2312'/>") == "gbk2312") assert(get_charset_from_html("<meta charset=\"gbk2312\"/>") == "gbk2312") assert(get_charset_from_html("<meta charset=gbk2312/>") == "gbk2312") assert(get_charset_from_html("content='text/html; charset=GBK'>") == "GBK")
所以,可以这样相对较好的方法取 HTML:
def url_to_html(url, headers=default_headers, timeout=10): req = requests.get(url, timeout=timeout, headers=headers) # requests 未能正确识别的编码就默认返回 ISO-885901 # 所以尝试从 HTML 中找定义的编码 if req.text and req.encoding == 'ISO-8859-1': encoding = get_charset_from_html(req.text) # XXX 如果页面也没定义编码?遇到再说吧 if encoding: req.encoding = encoding return req.text