一座古蹟應該要修繕到什麼程度,有時候還真是個好問題。
話說本站的前一個版本(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)