curlなどで取得したテキストを自動的にターミナルの文字コード(たとえばUTF-8)に変換したい場合がある。 このような場合には、Pythonのchardetモジュールが使える。 chardetは、Mozilla Firefoxで使われている文字コード判定アルゴリズムをPythonモジュールとして移植したものである。
chardetのインストール
DebianやUbuntuでは最初からインストールされている。
$ sudo apt-get install python-chardet Reading package lists... Done Building dependency tree Reading state information... Done python-chardet is already the newest version. 0 upgraded, 0 newly installed, 0 to remove and 35 not upgraded.
文字コードを自動判定し、デコードする
次のようなPythonコードを書き、test.pyとして保存する。
import sys import chardet text = sys.stdin.read() result = chardet.detect(text) print result print text.decode(result["encoding"])
iconvコマンドでShift_JISに変換したテキストをスクリプトに与えると、次のようになる。
$ echo -n 日本語 | iconv -f utf-8 -t shift_jis | python test.py
{'confidence': 0.99, 'encoding': 'SHIFT_JIS'}
日本語
Shift_JISと判定され、デコードに成功している。
シェル関数にしてみる
次のような関数を.bashrcなどに書くことで、シェル関数として使うことができる。
cats() {
local CODE
read -r -d '' CODE <<"__EOF__"
import sys, locale, chardet
text = sys.stdin.read()
locale = locale.getdefaultlocale() or 'UTF-8'
result = chardet.detect(text)
sys.stdout.write(text.decode(result['encoding'], 'replace').encode(locale[1]))
__EOF__
cat "$@" | python -c "$CODE"
}
ためしに、GB2312で書かれている騰訊QQのHTMLテキストを取得してみる。
$ echo $LANG
en_US.UTF-8
$ curl -s http://www.qq.com/ | head
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta content="text/html; charset=gb2312" http-equiv="Content-Type">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>��Ѷ��ҳ</title>
<script type="text/javascript">
if(window.location.toString().indexOf('pref=padindex') != -1){
}else{
if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(navigator.userAgent))){
HTMLテキストがGB2312で書かれているのに対し、ターミナルの文字コードがUTF-8であるため、title要素の中身が文字化けしていることがわかる。
ここで、定義したシェル関数にパイプで繋いでみる。
$ curl -s http://www.qq.com/ | head | cats
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta content="text/html; charset=gb2312" http-equiv="Content-Type">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>腾讯首页</title>
<script type="text/javascript">
if(window.location.toString().indexOf('pref=padindex') != -1){
}else{
if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(navigator.userAgent))){