歴史的な文書を扱っていると、人名や地名に異体字が頻繁に登場します(齋、髙、濵など)。検索やデータ処理の場面ではかなり厄介です。この記事では、そうした異体字を自動で標準的な文字に変換するプログラムを紹介します。
なぜ作ったのか?
研究で歴史的なデータを扱っています。その際、人名が資料に含まれているか確認したり、地名から緯度経度を取得したり(APIを使う)する必要があります。しかし、異体字・旧字体が使われていると、検索や照合がうまくいきません。
旧字体を変換するツールはいくつか見つかりましたが、異体字に特化した変換ツールが見当たらなかったため、自分で作ることにしました。
旧字体っぽく見えるけど実は旧字体ではない異体字があります。私が実際に出会った例だと、「鉄」の異体字である「鐡」があります。これは、旧字体の「鐵」とも微妙に異なります。
そのため、旧字体変換サイトでは変換できませんでした。
※ 厳密には旧字体も異体字の一種とされていますが、この記事では両者を区別しています。あしからず...
実装の概要
方針
- 異体字と標準形の対応表を取得
- それをもとに変換辞書を作成
- 文字列中の異体字を一括で置換する関数を作成
使用ライブラリ
pip install requests beautifulsoup4
これらのライブラリは以下の用途で使用します。
-
requests
:対応表のHTMLをダウンロード -
BeautifulSoup
:HTMLから表のデータを抽出
対応表の取得
異体字の対応表は以下のものを使います。
史料編纂所データベース異体字同定一覧
まずはHTMLページをダウンロードし、表の内容を抽出します。
import requests
from bs4 import BeautifulSoup
# 史料編纂所データベース異体字同定一覧
url = "https://wwwap.hi.u-tokyo.ac.jp/ships/itaiji_list.jsp"
# HTMLをダウンロード
response = requests.get(url)
response.encoding = "utf-8"
html = response.text
# BeautifulSoupでパース
soup = BeautifulSoup(html, "lxml")
# <table>要素を探す
table = soup.find("table")
# 各行を抽出(ヘッダーをスキップ)
data = []
for row in table.find_all("tr")[1:]:
cols = row.find_all(["td", "th"])
cols = [col.get_text(strip=True) for col in cols]
if len(cols) >= 2:
standard = cols[1]
variants = cols[2].split() if len(cols) > 2 else []
data.append((standard, variants))
# 確認用に数件出力
for s, vs in data[:5]:
print(f"{s} ← {' '.join(vs)}")
# 出力例:
# 亜 ← 亞
# 唖 ← 啞 瘂
# 悪 ← 惡
# 芦 ← 蘆
# 鯵 ← 鰺
対応表から変換辞書を作成
異体字 → 標準形 の辞書を生成します。
# 変換辞書を作成
conversion_dict = {}
for standard, variants in data:
for variant in variants:
conversion_dict[variant] = standard
print(conversion_dict)
# 出力例:
# {'亞': '亜', '啞': '唖', '瘂': '唖', '惡': '悪', ...}
文字列の一括変換関数
異体字変換辞書を使って、文字列に含まれる異体字をまとめて標準文字に置き換える関数です。
def convert_text(text, conversion_dict):
# 変換辞書を使ってテキストを変換
for old, new in conversion_dict.items():
text = text.replace(old, new)
return text
# 使用例
converted_text = convert_text("鐡太郎 齋藤 髙橋 濵田", conversion_dict)
print(converted_text) # 出力例: 鉄太郎 斎藤 高橋 浜田
変換辞書の保存
最後に、毎回HTMLをダウンロードして変換する必要のないように変換辞書を保存しておきましょう。
# 変換辞書を保存
import json
with open('conversion_dict.json', 'w', encoding='utf-8') as f:
json.dump(conversion_dict, f, ensure_ascii=False, indent=4)
おわりに
異体字を標準的な文字に変換するプログラムを作成しました。これによって、歴史的な人名や地名を扱う作業がグッと楽になります。
ちなみに、旧字体の変換も同様の手法で可能です。上記の対応表でも旧字体はある程度変換できますが、変換できない旧字体もあります。そういうときは、旧字体に特化した変換表を見つけて来て、変換辞書を新たに作るだけでOKです。