文档章节

Python+Requests编码识别Bug

Cnlouds
 Cnlouds
发布于 2015/08/16 20:05
字数 526
阅读 846
收藏 7

Requests 是使用 Apache2 Licensed 许可证的 HTTP 库。用 Python 编写,更友好,更易用。

Requests 使用的是 urllib3,因此继承了它的所有特性。Requests 支持 HTTP 连接保持和连接池,支持使用 cookie 保持会话,支持文件上传,支持自动确定响应内容的编码,支持国际化的 URL 和 POST 数据自动编码。现代、国际化、人性化。

最近在使用Requests的过程中发现一个问题,就是抓去某些中文网页的时候,出现乱码,打印encoding是ISO-8859-1。为什么会这样呢?通过查看源码,我发现默认的编码识别比较简单,直接从响应头文件的Content-Type里获取,如果存在charset,则可以正确识别,如果不存在charset但是存在text就认为是ISO-8859-1,见utils.py。


def get_encoding_from_headers(headers):
    """Returns encodings from given HTTP Header Dict.

    :param headers: dictionary to extract encoding from.
    """
    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'

其实Requests提供了从内容获取编码,只是在默认中没有使用,见utils.py:


def get_encodings_from_content(content):
    """Returns encodings from given content string.

    :param content: bytestring to extract encodings from.
    """
    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))



还提供了使用chardet的编码检测,见models.py:

@property
def apparent_encoding(self):
    """The apparent encoding, provided by the lovely Charade library
    (Thanks, Ian!)."""
    return chardet.detect(self.content)['encoding']



如何修复这个问题呢?先来看一下示例:

>>> r = requests.get('http://cn.python-requests.org/en/latest/')
>>> r.headers['content-type']
'text/html'
>>> r.encoding
'ISO-8859-1'
>>> r.apparent_encoding
'utf-8'
>>> requests.utils.get_encodings_from_content(r.content)
['utf-8']

>>> r = requests.get('http://reader.360duzhe.com/2013_24/index.html')
>>> r.headers['content-type']
'text/html'
>>> r.encoding
'ISO-8859-1'
>>> r.apparent_encoding
'gb2312'
>>> requests.utils.get_encodings_from_content(r.content)
['gb2312']



通过了解,可以这么用一个monkey patch解决这个问题:

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()

相关文章:

本文转载自:http://www.liguangming.com/python-requests-ge-encoding-from-headers

共有 人打赏支持
Cnlouds
粉丝 13
博文 95
码字总数 56136
作品 0
海淀
程序员
私信 提问
python+requests实现接口测试 - get与post请求使用

简介:Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库。它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTTP 测试需求。Requests 的哲学是...

上官夏洛特
09/04
0
0
python的requests库和urllib包对比

python中有多种库可以用来处理http请求,比如python的原生库:urllib包、requests类库。urllib和urllib2是相互独立的模块,python3.0以上把urllib和urllib2合并成一个库了,requests库使用了...

yzy121403725
07/04
0
0
linux下使用vim打开文件乱码问题解决方案

方案一:修改.vimrc文件 添加下面一行代码 set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1 编码的前后顺序代表了vim在识别文件编码使用的优先次序,所以在不了解...

苗雨顺
2011/04/18
0
0
Gogs v0.8.10 发布,极易搭建的自助 Git 托管服务

Gogs v0.8.10 发布,该版本为 Bug 修复,可选升级。 Bug 修复 在 Windows 下无法识别 Git 版本 #2167 火狐下无法预览 Wiki #2176 使用 PostgreSQL 作为数据库时无法正常浏览仓库的关注者和称...

无闻
2015/12/18
1K
14
LibJPEG 9 发布,JPEG 图像压缩库

libjpeg 9 支持无损的 RGB 图像编码,显著的提升了压缩比例;该版本文件不兼容上一个版本,但兼容其他 JPEG 标准;允许文件包含无效的组件识别;修复了一些 bug。 LibJPEG 是一个广泛使用的 ...

oschina
2013/01/27
5.1K
0

没有更多内容

加载失败,请刷新页面

加载更多

PHP生成CSV之内部换行

当我们使用PHP将采集到的文件内容保存到csv文件时,往往需要将采集内容进行二次过滤处理才能得到需要的内容。比如网页中的换行符,空格符等等。 对于空格等处理起来都比较简单,这里我们单独...

豆花饭烧土豆
今天
1
0
使用 mjml 生成 thymeleaf 邮件框架模板

发邮件算是系统开发的一个基本需求了,不过搞邮件模板实在是件恶心事,估计搞过的同仁都有体会。 得支持多种客户端 支持响应式 疼彻心扉的 outlook 多数客户端只支持 inline 形式的 css 布局...

郁也风
今天
4
0
让哲学照亮我们的人生——读《医务工作者需要学点哲学》有感2600字

让哲学照亮我们的人生——读《医务工作者需要学点哲学》有感2600字: 作者:孙冬梅;以前读韩国前总统朴槿惠的著作《绝望锻炼了我》时,里面有一句话令我印象深刻,她说“在我最困难的时期,...

原创小博客
今天
3
0
JAVA-四元数类

public class Quaternion { private final double x0, x1, x2, x3; // 四元数构造函数 public Quaternion(double x0, double x1, double x2, double x3) { this.x0 = ......

Pulsar-V
今天
17
0
Xshell利用Xftp传输文件,使用pure-ftpd搭建ftp服务

Xftp传输文件 如果已经通过Xshell登录到服务器,此时可以使用快捷键ctrl+alt+f 打开Xftp并展示Xshell当前的目录,之后直接拖拽传输文件即可。 pure-ftpd搭建ftp服务 pure-ftpd要比vsftp简单,...

野雪球
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部