python3.5 request 爬取中文网页乱码那些事

爬取某东的部分网站内容时,出现编码错误: 抓下来的内容显示乱码.

网页源码

网页源码如下:

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type"  content="text/html; charset=gb2312" />
  </head>
</html>

网页使用的是 gbk的编码形式,使用 utf-8 必然是乱码的:

resp = self.request.get(cart_url,cookies=self.cookies)
resp.encoding = 'utf-8'
print(resp.text[:500])

#print 内容:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>�ҵľ���--�ҵĶ���</title>

requests 编码源码:

 def content(self):
        if self._content is False:
            try:
                if self._content_consumed:
                    raise RuntimeError(
                        'The content for this response was already consumed')
                if self.status_code == 0:
                    self._content = None
                else:
                    self._content = bytes().join(self.iter_content(CONTENT_CHUNK_SIZE)) or bytes()
            except AttributeError:
                self._content = None
        self._content_consumed = True
        return self._content
######### 对比 ###########
def text(self):
        #  requests 会基于响应头获取字符集编码,可使用 r.encoding 指定编码方式. 
        content = None
        encoding = self.encoding
        if not self.content:
            return str('')
        # 没有编码方式,会使用 chardet 猜测编码方式.消耗资源
        if self.encoding is None:
            encoding = self.apparent_encoding
        try:
            content = str(self.content, encoding, errors='replace')
        except (LookupError, TypeError):
            content = str(self.content, errors='replace')
        return content

# apparent_encoding通过调用chardet.detect()来识别文本编码.
def apparent_encoding(self):
    """The apparent encoding, provided by the chardet library"""
    return chardet.detect(self.content)['encoding']

有几点说明的地方:

  • resp.text 返回的是Unicode型的数据;
  • resp.content 返回的是bytes型也就是二进制的数据;
  • 也就是说: 取文本,可以通过r.text; 取图片,文件用r.contexnt;

解决办法

弄明白编码之后, 开始修改代码,将编码方式修改为 gbk即可.

resp = self.request.get(cart_url,cookies=self.cookies)
resp.encoding = 'gbk'
print(resp.text[:500])

#print 内容:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>我的京东--我的订单</title>

小结

  1. 使用更简便的方式,先分析编码方式:
    >>> r=requests.get('http://jd.com')
    >>> r.encoding
    'utf-8'
    >>> r=requests.get('http://order.jd.com')
    >>> r.encoding
    'GBK'
    
  2. 明确编码的方式,可以指定 r.encoding=’gbk’的方式进行编码了.

  3. 站点请求一般都会在请求头中指定编码方式, 如果请求头没有,就从 meta中抽取即可:
#1.headers 一般会指定编码方式:
Content-Type application/json; charset=UTF-8
#2.从html的meta中抽取:
<meta charset="utf-8">

支持一下

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码支持一下

打开支付宝扫一扫,即可进行扫码打赏哦