Unicodeには「ここからここは平仮名の領域」、「ここからここは漢字の領域」のように文字種に応じてブロックが決められている。
それらを利用すれば解析対象の文字列が「何語で書かれているか」をある程度判定できたり、エンコードがどれが一番確からしいか確認できたりする、かもしれない。
サンプルコードはJava1.6を使用。
JavaのUnicodeBlockを使用すると、対象の文字列が平仮名であるかなどが判定できます。実行する前にjava.text.Normalizer.normalize使ってNFKCで正規化しておくと紛れが減るかもしれません。
// 平仮名判定(UnicodeBlock.HIRAGAN)
System.out.println( UnicodeBlock.of( 'あ' ) == UnicodeBlock.HIRAGANA );
// => true
System.out.println( UnicodeBlock.of( 'ア' ) == UnicodeBlock.HIRAGANA );
// => false
// カタカナ判定(UnicodeBlock.KATAKANA)
System.out.println( UnicodeBlock.of( 'ア' ) == UnicodeBlock.KATAKANA );
// => true
System.out.println( UnicodeBlock.of( 'あ' ) == UnicodeBlock.KATAKANA );
// => false
// 漢字判定(UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS)
System.out.println( UnicodeBlock.of( '言' ) == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS );
// => true
System.out.println( UnicodeBlock.of( 'ω' ) == UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS );
// => false
Perlにも似た表現があったり、Rubyは1.9から可能だったりするので、多くの言語で使えるはず。
// 平仮名4つ
System.out.println( "ひらがな".matches( "\\p{InHiragana}{4}" ) );
// => true
// カタカナ4つ
System.out.println( "カタカナ".matches( "\\p{InKatakana}{4}" ) );
// => true
// 漢字2つ
System.out.println( "漢字".matches( "\\p{InCjkUnifiedIdeographs}{2}" ) );
// => true
それぞれのブロックの意味についてはunicode.orgを見てもらうか、Wikipediaのこのページあたりを見てもらうかするとして、ここでは日本語で関わりがありそうなブロックのみを探してみることにします。
とりあえず文書を解析して、どのブロックが何度出現したかを調べる簡易コード。
// 解析対象文字
String str = "[Java]でUnicodeのブロックを、云々するソース。";
// NFKC(互換部品とそれに続く正規合成)をかけておく
str = Normalizer.normalize( str, Normalizer.Form.NFKC );
// どのブロックが何回使われたかカウントしてみる
Map<UnicodeBlock, Integer> result = new HashMap<UnicodeBlock, Integer>();
for( int i = 0; i < str.length(); i++ ) {
UnicodeBlock block = UnicodeBlock.of( str.charAt( i ) );
if( !result.containsKey( block ) ) {
result.put( block, 0 );
}
result.put( block, result.get( block ) + 1 );
}
// 結果表示
for( Object key : result.keySet() ) {
System.out.println( key + " : " + result.get( key ) );
}
// 結果
// => KATAKANA : 7
// => CJK_SYMBOLS_AND_PUNCTUATION : 3
// => CJK_UNIFIED_IDEOGRAPHS : 1
// => BASIC_LATIN : 13
// => HIRAGANA : 5
結果を見ての通り、「平仮名」は「HIRAGANA」、「カタカナ」は「KATAKANA」に分類され、「英字や記号」は「BASIC_LATIN」に分類されます。
漢字は「CJK_UNIFIED_IDEOGRAPHS」、句読点や「々」はCJK_SYMBOLS_AND_PUNCTUATIONに分類されているようです。
WEB上のjpドメインのページを2571個ほど適当に読み込んで(複数のポータルサイトからスタートして、本当に適当にリンクを辿ってもらいました)、各文書に登場するUnicodeBlockの数をカウントしてみました。
集計した文字数は全部で1億2千万くらい。タグを外して(というかDOMのTEXTの部分だけ読んで)、半角スペースを排除していますが、ScriptとかStyleタグの中身はカウントされいます。ので、英字・記号の発生率は普通の文書より高めになっていると思います。
けして多い母数とは言えないのと、エンコード失敗してる場合もあると思うので(レスポンスヘッダ見て指定してなければmeta見て判定はしてます)、まぁ、参考までの数値として。
UnicodeBlock | 日本語表記 | 出現数 | 出現率 | 出現率合算 |
---|---|---|---|---|
BASIC_LATIN | 基本ラテン文字 | 63447564 | 50.95821% | 50.95821% |
CJK_UNIFIED_IDEOGRAPHS | CJK統合漢字 | 21302350 | 17.10908% | 68.06729% |
KATAKANA | 平仮名 | 18909067 | 15.18690% | 83.25419% |
HIRAGANA | カタカナ | 18088082 | 14.52753% | 97.78172% |
CJK_SYMBOLS_AND_PUNCTUATION | CJKの記号及び句読点 | 2363719 | 1.89843% | 99.68015% |
GEOMETRIC_SHAPES | 幾何学模様 | 82669 | 0.06640% | 99.74655% |
GENERAL_PUNCTUATION | 一般句読点 | 60769 | 0.04881% | 99.79535% |
SPECIALS | 特殊用途文字 | 58295 | 0.04682% | 99.84217% |
BOX_DRAWING | 罫線素片 | 56623 | 0.04548% | 99.88765% |
MISCELLANEOUS_SYMBOLS | その他の記号 | 53811 | 0.04322% | 99.93087% |
ARROWS | 矢印 | 28584 | 0.02296% | 99.95383% |
LATIN_1_SUPPLEMENT | ラテン1補助 | 20855 | 0.01675% | 99.97058% |
MATHEMATICAL_OPERATORS | 数学記号 (演算子) | 15035 | 0.01208% | 99.98265% |
GREEK | ギリシア文字及びコプト文字 | 5628 | 0.00452% | 99.98717% |
COMBINING_DIACRITICAL_MARKS | ダイアクリティカルマーク | 3526 | 0.00283% | 99.99000% |
LATIN_EXTENDED_B | ラテン文字拡張B | 3192 | 0.00256% | 99.99257% |
LATIN_EXTENDED_A | ラテン文字拡張A | 1181 | 0.00095% | 99.99352% |
CYRILLIC | キリル文字 | 1049 | 0.00084% | 99.99436% |
IPA_EXTENSIONS | IPA拡張 (国際音声記号) | 969 | 0.00078% | 99.99514% |
HEBREW | ヘブライ文字 | 846 | 0.00068% | 99.99582% |
ARABIC | アラビア文字 | 624 | 0.00050% | 99.99632% |
HIGH_SURROGATES | 上位代用符号位置 | 585 | 0.00047% | 99.99679% |
THAANA | ターナ文字 | 572 | 0.00046% | 99.99725% |
LOW_SURROGATES | 下位代用符号位置 | 533 | 0.00043% | 99.99767% |
SYRIAC | シリア文字 | 528 | 0.00042% | 99.99810% |
ARABIC_PRESENTATION_FORMS_B | アラビア表示形B | 384 | 0.00031% | 99.99841% |
null | 354 | 0.00028% | 99.99869% | |
HANGUL_SYLLABLES | ハングル音節文字 | 317 | 0.00025% | 99.99895% |
ARMENIAN | アルメニア文字 | 234 | 0.00019% | 99.99913% |
SPACING_MODIFIER_LETTERS | 前進を伴う修飾文字 | 224 | 0.00018% | 99.99931% |
CURRENCY_SYMBOLS | 通貨記号 | 193 | 0.00016% | 99.99947% |
THAI | タイ文字 | 152 | 0.00012% | 99.99959% |
CYRILLIC_SUPPLEMENTARY | キリール文字補助 | 137 | 0.00011% | 99.99970% |
PRIVATE_USE_AREA | 外字領域 | 110 | 0.00009% | 99.99979% |
CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A | CJK統合漢字拡張A | 90 | 0.00007% | 99.99986% |
MISCELLANEOUS_TECHNICAL | その他の技術用記号 | 75 | 0.00006% | 99.99992% |
YI_SYLLABLES | イ文字 | 31 | 0.00002% | 99.99995% |
MONGOLIAN | モンゴル文字 | 25 | 0.00002% | 99.99997% |
DINGBATS | 装飾記号 | 16 | 0.00001% | 99.99998% |
TAI_LE | タイ・ロ文字 | 10 | 0.00001% | 99.99999% |
CHEROKEE | チェロキー文字 | 8 | 0.00001% | 99.99999% |
DEVANAGARI | デーヴァーナーガリー文字 | 7 | 0.00001% | 100.00000% |
見ての通り、BASIC_LATIN(基本ラテン文字)、CJK_UNIFIED_IDEOGRAPHS(漢字)、HIRAGANA(平仮名)、KATAKANA(カタカナ)の4種類だけで全体の97.78%をカバー出来ています。
次に数の多いCJK_SYMBOLS_AND_PUNCTUATION(句読点とか)を加えると、99.68%。たいていの日本語の文はこの5種類で構成されていると思って良さそうです。
ちなみにこの結果は直前でNFKCで正規化しています。正規化しない場合は、HALFWIDTH_AND_FULLWIDTH_FORMS(全角記号とか半角カナなど)が1%程度発生していました。