ICU 의 경우에는 charset detect 가 포함된지 꽤 되었음에도 불구하고, php 5.3 부터 기본 포함되는 intl extension 에는 이 기능이 들어가지 않고 있습니다. 그 외에도 pecl 이나 pear 의 icu library 관련 패키지들에도 이상하게 이 부분만 들어가지 않고 있군요.
그리고 좀 더 안습인 것은, Mozilla 의 Universal Chardet 의 경우에는 C#, java, python, ruby (python chardet 을 porting 했음) 등등이 지원하고 있음에도 불구하고, PHP 나 별도의 c/c++ library 로는 제공되지 않고 있습니다.
Mozilla Universal Charset
Nchardet for C#
jchardet for Java
chardet for python
rchardet for ruby (python clone
Encode-Detect-1.01 > Encode::Detect::Detector for perl
mozilla code 에 c++ 로 지원하고 있으니 이걸 포팅하면 되겠지 하고 쉽게 생각을 했는데, xpcom 구조를 알기 전에는 쉽게 뗄 수 있을 놈이 아니더군요.
이렇듯 저렇듯.. 나오기만 2여년을 기다리다가.. 귀찮아서 mod_chardet 이라는 php extension 으로 하나 만들어 보고 말았습니다. 일단 mod_chardet 은 기본은 ICU library 의 Charset detect 기능을 이용하고, 옵션으로 python chardet 이 설치가 되어 있으면 Python C API를 이용하여 python chardet 을 사용할 수 있도록 설계를 했습니다. Mozilla Universal chardet 이 PHP 만 없다는 것도 좀 그렇다는 생각이 들었고..
일단, ICU 와 Universal Chardet 의 성능 비교도 해 볼겸해서 돌려 보았는데, 역시 ICU 보다는 Universal Chardet 이 detect 능력이 좋더군요. 그리고 ICU 에서 detect 할 수 있는 charset 보다 Universal chardet 이 좀 더 많이 지원하는 까닭도 있었고요.
일단, python chardet homepage 에 있는 자료가 오래된 까닭에 다음의 환경에서 해당 자료를 다시 분석해 보았습니다. 테스트 환경으로는 다음과 같습니다.
Python 2.5
Python Chardet 1.0.1
PHP 5.2.6
ICU library 4.0.1
Python Chardet result:
google.cn {'confidence': 0.98999999999999999, 'encoding': 'GB2312'}
yahoo.jp {'confidence': 0.98999999999999999, 'encoding': 'utf-8'}
amazon.co.jp {'confidence': 1, 'encoding': 'SHIFT_JIS'}
pravda.ru {'confidence': 0.93312187961594417, 'encoding': 'windows-1251'}
auction.co.kr {'confidence': 0.56471064895612277, 'encoding': 'ISO-8859-2'}
haaretz.co.il {'confidence': 0.98999999999999999, 'encoding': 'windows-1255'}
www.nectec.or.th {'confidence': 0.77645629965698426, 'encoding': 'TIS-620'}
feedparser.org {'confidence': 0.98999999999999999, 'encoding': 'utf-8'}
python-chardet 1.0.1 의 경우, 홈페이지 자료와는 약간 다른 결과가 나오더군요. 일단 python chardet homepage 의 정보가 변경이 되었을 수도 있고, chardet 이 업데이트 되면서 결과가 달라질 수도 있겠지만, 일단 이 결과에서 auction 이 예전에는 제대로 EUC-KR로 판단이 되었는데, 지금 환경에서는 다른 결과를 보여 주고 있습니다.
다음은 mod_chardet 의 결과 입니다.
PHP mod_chardet result:
google.cn (7121)
ICU : Encoding -> GB18030 Confidence -> 100
MOZ : Encoding -> GB2312 Confidence -> 98
yahoo.jp (30367)
ICU : Encoding -> UTF-8 Confidence -> 100
MOZ : Encoding -> utf-8 Confidence -> 98
amazon.co.jp (166082)
ICU : Encoding -> Shift_JIS Confidence -> 100
MOZ : Encoding -> SHIFT_JIS Confidence -> 100
pravda.ru (97826)
ICU : Encoding -> ISO-8859-1 Confidence -> 28
MOZ : Encoding -> windows-1251 Confidence -> 93
auction.co.kr (101330)
ICU : Encoding -> EUC-KR Confidence -> 100
MOZ : Encoding -> ISO-8859-2 Confidence -> 56
haaretz.co.il (174179)
ICU : Encoding -> ISO-8859-1 Confidence -> 32
MOZ : Encoding -> windows-1255 Confidence -> 98
www.nectec.or.th (41527)
ICU : Encoding -> ISO-8859-1 Confidence -> 37
MOZ : Encoding -> TIS-620 Confidence -> 77
feedparser.org (28443)
ICU : Encoding -> UTF-8 Confidence -> 100
MOZ : Encoding -> utf-8 Confidence -> 98
18.33 Sec
보시다 시피, CJK / UTF-8 / ASCII 를 제외한 다른 1byte 권의 언어들에 대해서는 Universal chardet 이 ICU chardet 보다 월등히 detecting 을 잘 하고 있습니다. 다만 안습인 것은, mod_charset 의 Universal chardet 이 Python C API 를 이용해서 python 을 호출하다 보니, ICU 보다 성능이 굉장히 많이 떨어집니다. 실제로 위의 결과를 Universal chadet 체크를 하지 않는다면, 대략 0.04초 정도에 결과가 나옵니디만, Universal chardet detecting 을 시키니 거의 20초 가까운 결과치가 나옵니다.
대략 테스트를 해 보니 문자열이 3K 정도가 넘어가면 Python C API 로 호출한 결과가 상당히 늦어지는 결과를 보이더군요. 대략 1K 이내의 경우에 어느정도 비슷한 속도가 나옵니다.
또한, 짧은 문자열에 대해서도 ICU 보다 Universal chardet 이 성능이 조금 더 좋더군요. 그래도 한글 기준으로 테스트를 했을 때, 한글 10글자 정도는 받아야지 왠만한 confidence 가 나오게 됩니다.
다음의 결과는 web page 에서 html code 를 삭제하고 나온 결과 입니다. 다음의 코드가 사용이 되었습니다.
$buf = preg_replace ('/<[^>]*>/', '', $buf);
보통 웹 페이지의 경우, <>로 쌓여져 있는 코드들은 대부분 ASCII 이기 때문에 확률적 판단을 하는 chardet 에 부정적인 영향을 줄것이라 생각을 하고 한번 시도를 해 보았습니다.
PHP mod_chardet result:
google.cn (2781)
ICU : Encoding -> GB18030 Confidence -> 100
MOZ : Encoding -> GB2312 Confidence -> 98
yahoo.jp (3561)
ICU : Encoding -> UTF-8 Confidence -> 100
MOZ : Encoding -> utf-8 Confidence -> 98
amazon.co.jp (30739)
ICU : Encoding -> Shift_JIS Confidence -> 100
MOZ : Encoding -> SHIFT_JIS Confidence -> 100
pravda.ru (15728)
ICU : Encoding -> windows-1251 Confidence -> 28
MOZ : Encoding -> windows-1251 Confidence -> 94
auction.co.kr (36084)
ICU : Encoding -> EUC-KR Confidence -> 100
MOZ : Encoding -> ISO-8859-2 Confidence -> 27
haaretz.co.il (44570)
ICU : Encoding -> ISO-8859-8-I Confidence -> 23
MOZ : Encoding -> windows-1255 Confidence -> 98
www.nectec.or.th (10425)
ICU : Encoding -> EUC-JP Confidence -> 64
MOZ : Encoding -> TIS-620 Confidence -> 76
feedparser.org (5854)
ICU : Encoding -> UTF-8 Confidence -> 100
MOZ : Encoding -> utf-8 Confidence -> 98
4.86 Sec
이렇게 detecting 을 하니 ICU의 결과가 조금 좋아졌으며 (하지만 오판하는 경우도 생겼군요), 텍스트 양이 줄면서 Python C API를 사용하는 Univiersal chardet 의 성능이 대략 5초 정도로 시간이 절약 되었습니다.
뭐 어쨌든 두가지 기능을 다 지원을 하고, PHP 에서도 Universal chardet 을 지원할 수 있다는 점에 일단은 만족을 하고, posting 과 함께 mod_chardet 을 공개합니다.
그리고 혹시나 단순히 euc-kr / utf-8 만 판단을 해야 한다면, chardet 은 overhead 일 경우가 많습니다. 이럴 경우에는 차라리 pear KSC5601에 있는 is_utf8 method 를 사용하시는 것이 훨씬 경제적/성능적 효과가 좋습니다. 물론 제가 만들어 놓은 것입니다 ^^;
코드는 http://cvs.oops.org/index.php?cvsroot=PHP-Module 에서 받으실 수 있으며, 소스 안의 test.php 를 참조 하시면 사용하시는데 별 무리는 없을 겁니다.
Comments List
정균님 안녕하세요.
요 모듈 아직도 서포트 받을 수 있는지 궁금하네요 ^^
libtool 버전이 2.2.6으로 올라가면서 CDPATH관련 에러두 나구요. --tag를 찾네요
그리고
/home/sangjins/mod_chardet/php_chardet.h:104: error: expected specifier-qualifier-list before 'UErrorCode'
/home/sangjins/mod_chardet/php_chardet.c: In function 'zif_chardet_detect':
/home/sangjins/mod_chardet/php_chardet.c:375: error: duplicate case value
/home/sangjins/mod_chardet/php_chardet.c:367: error: previously used here
/home/sangjins/mod_chardet/php_chardet.c:392: error: 'CharDetObj' has no member named 'status'
/home/sangjins/mod_chardet/php_chardet.c: In function 'chardet_obj_init':
/home/sangjins/mod_chardet/php_chardet.c:422: error: 'CharDetObj' has no member named 'status'
/home/sangjins/mod_chardet/php_chardet.c: In function 'moz_chardet':
/home/sangjins/mod_chardet/php_chardet.c:442: error: 'CharDetObj' has no member named 'status'
/home/sangjins/mod_chardet/php_chardet.c:448: error: 'CharDetObj' has no member named 'status'
의 에러도 나네요; 잘 사용하다가 재설치 하려니 이런 문제가 발생했습니다;
바쁘신데 이거 실례가 되지 않을런지.. ㅜㅜ
libtool 과는 상관이 없습니다. ICU library가 지원되지 않을 경우에 처리 버그가 존재하고 있었네요. 이 버그 수정해서 0.0.3으로 release해 놓았으니, 0.0.3으로 해 보시기 바랍니다.
Ubuntu 9.04 의 기본 패키지들과 libchardet 1.0.1 로 build할 때 문제없이 되었습니다. ^^;
그렇군요. 그럼 라이브러리로 빌드하지 말고 그냥 소스를 직접 기존 프로젝트에 넣어버려야겠네요.
이래저래 신경써주셔서 감사합니다.
제 짧은 소견으로는 배포가 문제라면 귀찮게 소스 관리를 하시느니, 정적으로 link 시키는 것이 더 편하지 않을까 싶습니다. MPL 은 GPL 이나 LGPL 처럼 과격하지 않으니, static link 하시거나 dynamic link 하신 후에, MPL 라이센스 파일 하나 넣어 주시는 것으로 끝이 납니다. 전반적으로 GPL/LGPL로 배포를 하고 싶으시다면, 특정 부분에 call 을 MPL call 을 사용하신다고 명기를 하시면 될 것 같습니다. MPL은 다른 라이센스와 결합하는데 크게 지장이 없는 라이센스이니까요.
아...그렇게해도 되는군요. GPL과 MPL이 호환이 안된다고 해서, 문제가 될줄 알았습니다. 감사합니다.
그런거였군요. 감사합니다.
방금 다운 받아서 확인해보았는데, 라이센스가 MPL이더군요.
본래 소스는 MPL/GPL/LGPL중에 선택가능하게 되있던거 같은데, GPL로도 이용가능하게 배포하실 생각은 없으신가요...?
제가 개발하는 코드들은 대부분 필요에 의해서 제작을 하는 것입니다. 그렇기 때문에 순수하게 제가 처음부터 설계/코딩을 하는 경우 보다는 비슷한 것을 찾아서 제가 사용하기 편하도록 수정/개발을 하는 경우가 많습니다.
그러다 보니, 항상 license가 문제가 골치거리가 되는데, 가장 좋은 방법은 원 코드의 license 를 유지하는 것이 가장 편한 방법이더군요. 그리고 libcharset 의 원형이 Mozilla Universal Charset Detector 이기는 하지만, 저는 이 코드를 Perl Moudle 에서 친절하게 잘 분리해 놓은 것을 C wrapper 를 만들어서 c/c++ library 로 둔갑을 시켜 놓은 것입니다. 그리고 해당 Perl Module 이 license를 MPL로 해 놓아서 저 역시 이를 승계한 것이고요.
다만, Universal Chardet code 를 보면 MPL/GPL2/LGPL2.1 중에 하나를 선택할 수 있도록 되어 있습니다. 그리고, 저와 Perl module 개발자가 추가한 코드에서 이 문구는 역시 포함이 되어 있기 때문에 재배포를 하시고 싶고, license 를 변경하고 싶다면 저작권에 위배되지 않도록 결정을 하시면 될 것 같습니다.
저도 나름 살짝 고민했다가 GPL보다 MPL이 더 자유롭지 않을까 생각해서 MPL로 그냥 고민없이 승계를 했습니다.
안녕하세요.
libchardet을 쓰고 싶어서 다운 받으려고 했더니 사용자 이름과 암호를 요구하네요... 특정 그룹에게만 공개된 자료인가요...?
browser 로 접속하지 마시고 ftp client 로 접속 하시면 됩니다.
감사합니다!! libchardet으로 하니 에러도없이 바로 작동하는군요~
잘 사용하겠습니다 (__) 감사합니다
mod_chardet 0.0.2 로 업데이트 했습니다. Python C API로 지원하던 mozilla universal charset detect mode 를 제거하고, libchardet 을 만들어서 C++로 지원하도록 변경했습니다. 속도가 캡빵 빨라졌습니다. :-) python-chardet 보다 정확도가 조금 더 좋습니다.
ftp://ftp.oops.org/pub/oops/php/extensions/mod_chardet 에서 받으실 수 있습니다.
http://cvs.oops.org/?cvsroot=PHP-Module&module=mod_chardet&file=README,v&rev=1.3 를 참조해서 빌드 하실 수 있습니다.
이 버전은 libchardet 이 기본 모드로 지원되며, CHARDET_ICU mode 로 ICU chardet mode 를 사용할 수 있으며, 개발시의 debug mode로 CHARDET_PY (default option 아님) 를 이용할 수 있습니다.
안녕하세요 ^^
개발해주신 모듈 설치에 성공하였습니다.
다만 온라인 용으로 사용시의 예제가 필요한데 혹시 제작해주실 수 있으신지요..
죄송합니다;
source 안에 있는 test.php 와 http://cvs.oops.org/?cvsroot=PHP-Module&module=mod_chardet&file=Reference,v&rev=1.1 를 참조하시면 될 것 같습니다. test.php 역시 제일 첫라인을 제외하면 web에서 그대로 사용하실 수 있습니다.
"mozilla code 에 c++ 로 지원하고 있으니 이걸 포팅하면 되겠지 하고 쉽게 생각을 했는데, xpcom 구조를 알기 전에는 쉽게 뗄 수 있을 놈이 아니더군요." 라고 적어 놓았는데, Perl 모듈을 보니 가져다 사용하고 있더군요. 그래도 libchardet 을 c/c++ 용 library 로 만들어 보았습니다. mod_chardet 의 python c api 를 굳이 이용할 필요가 없어 졌네요. :-)
조만간 업데이트를 하겠습니다.