1. 程式人生 > >使用chardet判斷編碼方式

使用chardet判斷編碼方式

script 自動 __main__ 正常的 的確 字符 編碼工具 param api

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判斷編碼方式