訪問者数 2205 最終更新 2012-03-01 (木) 11:19:41
Unicodeは、 WikipediaのUnicode によると
世界中の多くのコンピュータ上の文字列を一貫した方法で符号化し、表現し、 扱うためのコンピュータ業界の標準
で、
NT系のMicrosoft Windows (Windows)、Mac OS X、LinuxやJavaなどで利用されて
おり、
元々16ビットの文字集合で全ての文字の網羅を目指して開発されたが、 符号位置が圧倒的に足りなくなり、Unicode 2.0以降では、 21ビットの文字集合として規定されることとなった。
である。
Unicodeの文字を表現する場合、"U+"にその文字の符号位置を表す16進数の値を続ける。
また、
日本の文字については当初より JIS X 0201、JIS X 0208 と JIS X 0212 を、 Unicode 3.1 では JIS X 0213 の内容を収録している。
具体的に我々が使いそうなのは、
U+0000-007F ラテン文字(ASCII文字) と U+3000-303F 漢字上の記号・句読点 U+3040-309F ひらがな U+30A0-30FF かたかな U+4E00-9FFF 漢字(正確にはCJK統合漢字、CJKは中国・日本・韓国)
と思われる。あと、CJK互換文字とかCJK統合漢字拡張B,C,Dとかあるが、無視してよいのか?
UTF-8は、上記のUnicodeを「符号化」する方法の1つである。WikipediaのUTF-8によると、
ASCII文字と互換性を持たせるために、ASCIIと同じ部分は1バイト、その他の部分 を2〜6バイトで符号化する。4バイトのシーケンスでは21bit(0x1FFFFF)まで 表現することができるが、(後略)
であり、符号化の規則は、
バイトの先頭が0 ⇒ 1バイトコード(ASCII対応のU+00-7Fの部分) バイトの先頭が10 ⇒ 2〜6バイト時の2〜6バイト目(非1バイト目)を表す バイトの先頭が110 ⇒ 2バイトコードの1バイト目 2バイトコードはU+0080-07FFを収容する。7FF=11ビットをyyyyxxxxxxxとすると 1バイト目 110yyyyx、 2バイト目 10xxxxxx として収める バイトの先頭が1110 ⇒ 3バイトコードの1バイト目 3バイトコードはU+08000-FFFFを収容する。FFFF=16ビットをyyyyyxxxxxxxxxxxとすると 1バイト目 1110yyyy、 2バイト目 10yxxxxx、 3バイト目 10xxxxxx として収める。
ここは、かなり微妙な話で、わかりにくかったが、このページを見て納得した。
要するに、Python上では
Unicode文字列 = 次項に述べるように、「シーケンス型」のうちの1つで、propertyとして「unicode」がついているもの。だから、
>>> u1 = u"これはユニコード型文字列です" >>> type(u1) <type 'unicode'>
UTF-8の文字列 = シーケンス型のうちの「str型」であり、バイト列と思えばよいらしく、その中に入っている文字のエンコードは(pythonとしては)関わらない。たまたまシステムがUTF-8を仮定しているのでUTF-8のバイトコードが入っているだけ。
>>> s1 = "これはふつうの文字列です" >>> type(s1) <type 'str'>
Pythonのシステムに対して、「扱う文字コードはUTF-8」としておけば(=プログラム上に書く文字列も、入出力もUTF-8としておけば)、str型の中に入っている文字列はUTF-8になっている。でも、ユニコード型とは、同じものではない。また、ユニコード型の文字列が内部的にUTF-8で表現されている保証もない(実際どうなのか知らない)。
目に見える違いとしては、たとえば
# EUC-JPなソースコードでは >>> len("あ") 〜〜〜 EUC-JPやShift-JISでは2バイトで保持される 2 # UTF-8なソースコードでは >>> len("あ") 〜〜〜 UTF-8では3バイトで保持される 3 # unicode型なら >>> len(u"あ") 〜〜〜 ユニコード文字としては1文字(内部表現のバイトではなくて) 1
ということになる。
で、基本は、プログラム内部ではなるべくunicode型で持つべし、ということになる。変換が必要になることがある。
import sys import codecs sys.stdin = codecs.getreader('utf_8')(sys.stdin) sys.stdout = codecs.getwriter('utf_8')(sys.stdout)を使う。同様にファイル入出力に対しては
import codecs fin = codecs.open('input.txt', 'r', 'utf_8') fout = codecs.open('output.txt', 'w', 'utf_8')のようにすることができる。なお、utf_8の代わりにshift_jisやeuc_jpを指定することもできる。
u1 = u"あいう" 〜〜〜 u1はunicode型 s1 = u1.encode('utf_8') 〜〜〜 s1はstr型や、逆に
s1 = "かきく" 〜〜〜 s1はstr型 u1 = s1.decode('utf_8') 〜〜〜 u1はunicode型ができる。また組込み関数unicodeはdecode('utf_8')と同じような働きをする
u1 = unicode(s1, 'utf_8')ができる。
まず、Pythonでのunicode文字列は、「シーケンス型」である。(5.6節 シーケンス型)
シーケンス型への操作は、この5.6節の表に載っている通りで、
x in s | s のある要素 x と等しい場合 True , そうでない場合 False |
x not in s | s のある要素が x と等しい場合 False, そうでない場合 True |
s + t | s および t の結合 |
s * n, n * s | s の浅いコピー n 個からなる結合 |
s[i] | s の 0 から数えて i 番目の要素 |
s[i:j] | s の i 番目から j 番目までのスライス |
s[i:j:k] | s の i 番目から j 番目まで、 k 毎のスライス |
len(s) | s の長さ |
min(s) | s の最小の要素 |
max(s) | s の最大の要素 |
s.index(i) | s 中で最初に i が現れる場所のインデクス |
s.count(i) | s 中に i が現れる数 |
だから、s[i]を使って文字列を先頭からスキャンして判定することになる。
Pythonでの、文字列がUnicodeであるかどうかの判定は、実は簡単で、 1文字ずつスキャンする必要はない。シーケンス型の変数xがUnicodeであるかどうかは、 isinstance(x, unicode) によって判定できる。
しかし、これは今の役には立たない。なぜなら、Twitter APIで得られたtext本文は、 すべて(ASCII文字も含めて)Unicodeで書かれているからである。たとえば、 u'abc' など。従って、ASCII文字であるか漢字(2バイトコード)であるかの区別は、 1文字ずつ判定をする必要がある。
実際に欲しいのは、文字列全体の中に漢字(2バイトコード)が含まれているか否か、であるから、1文字でも漢字が出てくればそこでTrueを返せばよい。全部の文字を確認する必要はない。つまり
Unicode文字列であることを確認したうえで、 先頭から1文字ずつ見て行って、 もしord(文字)が30xxや4Exx-9xxxならば、それは漢字なので「漢字入り文字列」。 もし最後のバイトまでそうでなければ、「ASCII文字列」
である。
# -*- coding: utf-8 -*- def hasKanji(s): #Returns True if string s contains a Kanji, False if not. kanji = False for c in s: if (((ord(c)&0xff00) == 0x3000) or (0x4e00 <= ((ord(c)&0xff00) <=0x9f00))): kanji = True break return kanji s = u"abc" とか u"abcあ" とか print hasKanji(s)
# -*- coding: utf-8 -*- import twitter def hasKanji(s): #Returns True if string s contains a Kanji, False if not. kanji = False for c in s: if (((ord(c)&0xff00) == 0x3000) or (0x4e00 <= ((ord(c)&0xff00) <=0x9f00))): kanji = True break return kanji api = twitter.Api() timeline = api.GetPublicTimeline() for s in timeline: t = s.text if hasKanji(t): print "Kanji> ", t else: print "Ascii> ", t
実際やってみると、Kanjiのツイートはそれ程多くないものだ。時間帯によるのか?
次のステップは、選び出した漢字のツイートを日本語形態素解析に掛けることになる ⇒ ノート/テキストマイニング/twitter-2