移至主內容
DarkRanger's Secret Area

主導覽

  • 首頁
  • 關於本站
  • Linux
  • 程式開發
  • N900
  • 譯文
  • 資訊技術辭典

文章分類

  • 影劇
  • 遊戲
  • 筆記
  • 雜文
  • 資訊技術
  • 站務訊息

最新內容

  • How-To:Linux 安裝 DevilutionX
  • 於 2012 年建立的一份音樂播放清單
  • How-To:Linux 安裝 Medal of Honor: Allied Assault
  • Fallout 4 (2015)
  • How-To:Linux 安裝 Blood
  • 《終極動員令》系列早期作品原始碼釋出
  • How-To:Linux 安裝 Doom 3
  • Nausicaä of the Valley of the Wind (1984)
  • Intel 內顯與 Linux 桌面死當問題排解
  • 《哥吉拉 -1.0》心得補遺

大量文字檔編碼轉換

發表日期:星期六, 03/05/2016 - 20:25

一座古蹟應該要修繕到什麼程度,有時候還真是個好問題。

 

話說本站的前一個版本(v5)是由靜態的 HTML 網頁檔所組成,數了一下,總共有 249 支網頁檔位於舊網站的目錄中,而其中絕大多數是採用繁體中文的 Big5 編碼。然而日前 DR 看著看著,突然覺得這些編碼應該要統一成 UTF-8 才是,於是便開始構思應該要怎麼處理才好。

 

雖然一開始很自然而然就會想到 iconv 這支工具,但隨後很快就會意識到,這項需求實則需要更加精細的功能。它應該要能夠偵測檔案的編碼,而不是僅檢查 <meta> 標籤的 charset 屬性,然後根據偵測結果來決定是否需要執行編碼轉換。除此之外,它也要能夠在轉換後自動修改 charset 屬性。

 

於是 DR 撰寫了一支 Python 程式,並使用 chardet 模組來做字元編碼的偵測,在 Fedora 23 上可以利用以下指令來安裝該模組:

  • sudo dnf install python-chardet python3-chardet

 

以下程式碼(text_encoding_conversion.py)會讀取同目錄及子目錄下的所有 HTML 檔,若字元編碼為 Big5 就會轉換為 UTF-8,並變更 charset 屬性值:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import os, sys, re
import codecs
import chardet

EXTENSIONS = (".htm", ".html")
FROM_ENCODING = "big5"
TO_ENCODING = "utf-8"

def get_encoding(fn):
    raw_file = open(fn, "rb")
    encoding = chardet.detect(raw_file.read())["encoding"]
    raw_file.close()
    
    return encoding
    
def do_conversion(fn):
    input_file = codecs.open(fn, "r", FROM_ENCODING)
    content = input_file.read()
    input_file.close()
    
    if "<meta " not in content:
        content = content.replace("<head>",
        "<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\" />" % TO_ENCODING)
    else:
        from_charset = re.compile(re.escape("charset=%s" % FROM_ENCODING), re.I)
        to_charset = "charset=%s" % TO_ENCODING
        content = re.sub(from_charset, to_charset, content)
    
    output_file = codecs.open(fn, "w", TO_ENCODING)
    output_file.write(content)
    output_file.close()

def text_encoding_conversion(path):
    total = 0
    converted = 0
    
    for dirname, dirnames, filenames in os.walk(path):
        for fn in filenames:
            if fn.lower().endswith(EXTENSIONS):
                total = total + 1
                full_path = os.path.join(dirname, fn)
                encoding = get_encoding(full_path)
                print("%s - %s" % (encoding, full_path))
                
                if encoding and encoding.lower() == FROM_ENCODING:
                    do_conversion(full_path)
                    converted = converted + 1

    print("%d files checked, %d converted." % (total, converted))

if __name__ == "__main__":
    appdir = os.path.abspath(os.path.dirname(sys.argv[0]))
    text_encoding_conversion(appdir)
    

 

筆記