星期一, 8月 08, 2011

完美簡繁轉換

因為之前一直用ConvertZ轉影片字幕檔,但是我在家用Mac居多,加上聽完HITCON 2011後在公司也不太想用Windows了(大誤),而且ConvertZ必須自己指定檔案的編碼,對於多檔轉換時很麻煩(找的字幕檔編碼不一定是某種編碼),希望能有更方便的解決方案。原本想要用開放中文轉換opencc,但是在WIndows編譯上遇到困難,後來又看到convert2utf8,本以為它會自動轉換編碼,用了才發現不會,再找了Universal Encoding Detector,自己加上自動編碼偵測,並在轉換檔加上BOM

至此發現用Python做簡繁轉換其實非常好寫,而且convert2utf8要自訂詞組並不方便,於是就找 python-jianfan 來做為簡繁字轉換,至於詞呢?

Python简繁转换 有提到維基百科所使用的『詞』轉換技術,再配合他的【最大正向匹配算法】,可以有效得到我想要的結果。。至於文中提到的『人體內存在很多微生物,計算機內存很大』這樣的句子要怎麼辦呢?我的做法仿ConvertZ,加上一組無用的贅詞放在前面,即可避免錯誤的匹配。

轉換字幕有個特點:每個翻譯的用語或名字可能不一致,所以加上可針對每個影片自訂詞庫,例如說最近的韓劇城市獵人裏主角叫 李潤城 或 李潤成 呢?(男主角是 李民浩 或 李敏镐 ?)總是要統一看起來才方便。

由於我只需要UTF-8檔,整理這支小程式的流程如下:
  1. 利用Universal Encoding Detector偵測編碼轉成UTF-8
  2. 使用python-jianfan 將字轉成繁體並加上BOM
  3. 內建詞轉換
  4. 使用者自訂詞轉換
這裏內建詞庫來源是 ConvertZ裏的B5fix.dat 和 ZhConversion.php 加上自己的修改。在整理詞庫時發現幾個ZhConversion.php的錯誤,一些有爭議的字/片語是依照(臺灣)教育部重編國語辭典。同時也發現小時候學的字"裏"居然是異體字,現在要用"裡";同樣還有"污"要改用"汙"等等。

最後要感謝以上提到各Open Source專案,讓在下可以很方便的在各平台看影片。所有程式碼放在 chinese-autoconvert ,希望有本領的朋友能夠加以改進。

後記: 雖然我只有稍微看一些簡單的Python教學,但是也能夠很快上手寫出簡單的工具,漸漸能夠瞭解為何Google要採用Python。

Update: 剛剛發現有人做了OSX的GUI,有需要的朋友可以試試。

17 則留言:

s 提到...

不好意思,問一下,有沒有 mac or linux 的版本,純 command line 的?

我下載了您的 source ,然後試圖要在 mac 上執行,但是他說有些 import 的 module 找不到

因為我對 python 不熟,不知道是不是 一些 lib 是 windows 專用的,裝了python 就會有的,所以 mac or linux 上是沒有的。

s 提到...

不好意思,剛剛狀況沒講清楚,現在補上錯誤訊息

Traceback (most recent call last):
File "./g2butf8.py", line 9, in
from jianfan import jtof
ImportError: No module named jianfan

然後我連到您註解裡面提到的
http://code.google.com/p/python-jianfan/

裡面提供下載的內容,我不知道要怎麼使用
一個是 .egg
另一個是 一包 py
不知道那一個能夠讓我在 command 執行 python 的時候,他能找到您需要 import 的 jtof
如果您能告訴我的話,我想在 mac 上就能夠使用了

謝謝。

鳥毅 提到...

s: 不好意思,我偷懶了:P 今天會抽空把Linux和Mac的安裝方式寫上去。

因為我和Python也不太熟,所以花了點時間,不過可以放心,除了要產生windows執行檔的模組之外,另外兩個庫都是跨平台(Universal Encoding Detector和python-jianfan )。

文件請至 http://code.google.com/p/chinese-autoconvert/w/list 看

s 提到...

謝謝您的回覆

原來 python module 先 build 在 install
這樣我裝好了,但是還是有狀況

Traceback (most recent call last):
File "g2butf8.py", line 148, in
convertFile(afile);
File "g2butf8.py", line 96, in convertFile
print u"正在轉換", target_file, u" 編碼為: ", f_encoding
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)


然後我查了一下,翻到這個

http://blog.wahahajk.com/2008/08/app-engine.html

不知道對您 debug 有沒有幫助。

我是用 mac osx 10.6
python 是2.6 ,謝謝您。

鳥毅 提到...

我用Lion 10.7裏頭的Python 2.7.1並無此錯誤,我猜你的Terminal(終端機)編碼不是UTF-8.
請下 env指令,若不是,建議修改 ~/.profile
在最後加上
export LANG=zh_TW.UTF-8
export LC_CTYPE=UTF-8

s 提到...

謝謝哦,

我用 iterm ,然後我平常在用的 server 也都是 utf8 ,所以 terminal 確定沒問題。
我沒注意到 locale 的問題,locale 改完就正常了
謝謝您的熱心,寫了這個好用的 script,也謝謝您幫我解決問題。

匿名 提到...

因為有類似的問題所以寫了一個 Cocoa 程式來做轉換,參考了大大的筆記獲益良多。

http://the-moment.tk/conv-project/

鳥毅 提到...

rickwuman, 能夠幫到你的忙實在太好了。
可惜沒有open source,不然我很想幫你加上用語轉換:P

Ytsejam 提到...

1. Line 113, 114及130, 131的 for loop:
for line in lines:
line = convertVocabulary(line, dic_tw());

應改為

idx=0
for line in lines:
lines[idx] = convertVocabulary(line, dic_tw());
idx += 1

否則 lines 的內容還是一樣

2. Line 134

line = convertVocabulary(line, user_dic);

是多餘的,應可刪除

Tseng Teng-Yi 提到...

Ytsejam ,感謝。

Ytsejam 提到...

Tseng Sir,

Line 20:

for j in range(len(string_in) - i, 0, -1):

應改為

for j in range(len(string_in) - 1, 0, -1):

否則在第一次 match 後,字串結尾的位置會減去 i,
後續會造成匹配不到的問題

TEN 提到...

不好意思,請問有特殊字一樣可以轉換嗎? 例如:妰

Tseng Teng-Yi 提到...

Ytsejam: 那個function是抄來的,剛看了一下應該沒錯喲,雖然叫最大正向匹配,但看來是從最後開始切割,第24列 i += len(t) - 1 ,所以每次匹配完就從後面向前 len(t) 的長度是對的。

Tseng Teng-Yi 提到...

Ten:
妰 或 嬑 這種 UTF-8 字元也是可以轉換的,只是來源必須是UTF-8檔案,否則Python會丟出Exception。 您不妨自己試試 ^_^

Ytsejam 提到...

Tseng Sir,

抱歉,是我誤會了,原本的 function 是用 string_in[i:][:j]
我改成了 string_in[i:j],所以 j loop 也要跟著改

TEN 提到...

你好,最近查了很多有關中文編碼的文章,如果中文文檔不是unicode 可以使用cjk 的規格,python 內置的不是最新的,在這裡可找到最新的(它也很多年前了)CJKPython;另外正體中文還有CNS11643 的支援問題,大概只知道這些,不知道怎麼解決;CJK 也不知道怎麼用。

Tseng Teng-Yi 提到...

TEN: 你說的都不是我考慮的問題耶...這麼複雜的東西請找李果正先生。對我來說,只有UTF-8的國際標準,其他的東西不是每套電腦作業系統都一樣,根本不管:P 我做的這種小程式,就是滿足簡單需求就好。