使用chardet判断编码方式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用chardet判断编码方式相关的知识,希望对你有一定的参考价值。

 

1. chardet是什么

chardet是python中比较常用的一个编码方式检测库,需要注意的是它只检测并返回检测结果,并不负责对原数据做什么处理。

 

可以使用PIP命令安装:

pip install chardet

 

2. 如何使用

2.1 API简介

一般都是调用chardet.detect传入一个字节数组,返回一个字典,此字典中存放分析的结果,一个可能的分析结果字典:

{
  ‘encoding‘: ‘ISO-8859-1‘,
  ‘confidence‘: 0.44923076923076927,
  ‘language‘: ‘‘
}

encoding: 可能的编码方式

condidence: 识别的正确率是多少,这是一个区间[0, 1]上的值,值越大表示结果越可信

language: 我也不知道做啥的,等会儿看看源码这个值是如何得到的....

 

2.2 读取配置文件时自动识别编码方式

只要是一个灵活的软件都会提供配置文件来让用户根据自己需要进行定制,但是我们没法保证用户究竟是使用什么鬼东西来编辑这个配置文件的,vim?notepad?editplus?奇奇怪怪的文本编辑工具一大堆,如果强制配置文件只能使用UTF-8格式的甚至还可能会碰上notepad的bom,要了命了,所以一个比较好的方式是在读取配置文件的时候能够自动检测它的编码方式,这样就无需关心用户究竟是使用什么鬼东西编辑的。一个可能的例子如下:

#! /usr/bin/python

import chardet
import json


class EncodingUtil:
    """
    编码工具类
    """
    @staticmethod
    def decode(content):
        """
        将字节数组读取为UTF8格式
        :param content: a byte or byte array
        :return:
        """
        encoding = chardet.detect(content)[‘encoding‘]
        if encoding != ‘utf-8‘:
            return content.decode(encoding)
        else:
            return content.decode(‘UTF-8‘)


class ConfigurationLoader:
    """
    配置文件加载类
    """
    @staticmethod
    def load_config(config_path):
        with open(config_path, ‘rb‘) as config_file:
            config_content = EncodingUtil.decode(config_file.read())
            return json.loads(config_content)


if __name__ == ‘__main__‘:
    print(ConfigurationLoader.load_config(‘D:/config.json‘))

 

2.3 爬虫中用来判别网页的编码方式

呃,貌似现在python已经成为爬虫的代名词,正常的套路网站内容都是按照UTF-8编码返回的,但是总有一些非主流站,会以奇奇怪怪的编码返回(根据笔者的经验,国内的网站一般也就是UTF-8和GB2312的,GB2312估计是因为很多编写网页的开发工具默认是GB2312的,写网页的家伙没改然后就这样子了呗),如果是有针对性的爬虫(时髦的说法叫做垂直领域爬虫),大不了我们失败几次之后专门做下编码格式转换就可以了,毕竟写爬虫基本就是不断处理异常情况,但是如果写的是通用爬虫,我们甚至都不知道爬虫会去哪里抓取内容更别提内容的编码方式了,所以在这种情况下在处理内容之前要进行一个编码转换,将其转换为宇宙通用的UTF-8格式,一个简单的例子如下:

#! /usr/bin/python

import chardet
import urllib3


class Spider:
    """
    蜘蛛侠,爬爬爬
    """
    pool_manager = urllib3.PoolManager()

    @staticmethod
    def get(url):
        return Spider.pool_manager.urlopen(‘GET‘, url)


class EncodingUtil:
    """
    编码工具类
    """
    @staticmethod
    def decode(content):
        """
        读取字节数组为字符串
        :param content: a byte array
        :return:
        """
        encoding = chardet.detect(content)[‘encoding‘]
        if encoding != ‘utf-8‘:
            return content.decode(encoding)
        else:
            return content.decode(‘UTF-8‘)


if __name__ == ‘__main__‘:
    # UTF8格式编码的
    response = Spider.get(‘http://www.baidu.com/‘)
    html = EncodingUtil.decode(response.data)
    print(html)

    # GB2312格式编码的,找了好久才找到一个GB2312编码的...
    response = Spider.get(‘http://www.hzsjwjcj.gov.cn/‘)
    html = EncodingUtil.decode(response.data)
    print(html)










当正确读取到内容之后就可以传给bs处理啦,chardet在爬虫中的应用大致就是这样子。

 

2.4 检测大文件

检测编码方式是需要一定的数据量作为参考的,当要检测一个特别大的文件的时候,比如一个几个G大的文件,没必要全部输入太浪费了,但是究竟给它多少数据做检测比较合适呢,1M?10M?100M?这个还真不知道....

所以这个时候我们就可能需要它提供一种方式,我们一点一点的把数据喂给它,当能够确定编码方式的时候就立即返回。哈,它确实提供了这么一种方式:

 

 

所以我们也可以总结出来,检测的数据量越少结果就越可能产生偏差,输入的数据量越大结果就可能越正确,所以也明确了chardet的应用场景,当只有几个字节的时候就别指望chardet能给出多正确的结果了。

 

3. 需要注意的一些坑

如果看到检测的返回值是这个样子的:

{
  ‘encoding‘: ‘ascii‘,
  ‘confidence‘: 1.0,
  ‘language‘: ‘‘
}

不要急着感叹于chardet的牛叉竟然可以100%的确定是ASCII编码,这个八成就是没有检测出来,因为chardet.detect方法的默认返回值就是这个,贴源代码有图有真相:

# Default to ASCII if it is all we‘ve seen so far
elif self._input_state == InputState.PURE_ASCII:
    self.result = {‘encoding‘: ‘ascii‘,
                   ‘confidence‘: 1.0,
                   ‘language‘: ‘‘}

 

 

参考资料:

1. https://pypi.python.org/pypi/chardet/

2. https://github.com/chardet/chardet


 

.

以上是关于使用chardet判断编码方式的主要内容,如果未能解决你的问题,请参考以下文章

python 判断一个字符能否用gbk和utf8编码

chardet坑——比蜗牛还慢

使用chardet模块获取文件的编码格式,进而正确的读取文件内容

编码格式检测chardet模块

Python爬虫2-检测编码(使用chardet)

python 模块 chardet下载及介绍