記事タイトルの通りマニアックな内容ですが、誰かの役に立つかもしれないので、やり方を公開します。
1.問題意識
私は、司法試験短答過去問ウェブアプリを作成しておりまして、事前に条文のhtmlファイルを準備し、参考条文をクリックするとその条文が画面右に表示されるようにしています。
(詳しくは司法試験短答式過去問演習サイトの解説を作り始めましたをご覧ください)
ページ内リンクを活用してこれを実現しています。
一年ほど前にe-Gov 法令検索から条文のhtmlファイルを取得したときは、例えば第百九十九条なら、「id=”Mp-At_199″」のようなidがhtml内に付されていました。
最近久しぶりにe-Gov 法令検索から条文のhtmlファイルを取得したところ、形式が変わっていました。
これまでは現に表示しているページをhtmlとして保存していましたが、現在はいろいろな形式でダウンロードできるように用意されていて、その中にはHTML形式もありました。
それをダウンロードするときれいなhtmlファイルで、これはありがたいと思いました。
しかし一つ問題がありまして、条文ごとに「id=”Mp-At_199″」のようなidが付されておらず、軒並み「id=””」となっていたのです。
これが私の問題意識です。
2.やり方
結論を最初に示します。
import re
def convert_kansuuji_to_arabic_number(kansuuji):
# 結果として返すアラビア数字の文字列を初期化
arabic_number = ''
# 一〜九の変換表
convert_table = str.maketrans("一二三四五六七八九", "123456789")
# 単位の処理
unit_under_thousand = {"十": 1, "百": 2, "千": 3}
unit_over_thousand = {"万": 4, "億": 8, "兆": 12, "京": 16}
# 基準となる単位の初期化
base_unit = 0
# 一の位から処理していくために逆順にする
reversed_kansuuji = list(reversed(kansuuji))
for i, character in enumerate(reversed_kansuuji):
# 十、百、千の場合
if character in unit_under_thousand.keys():
# unit_under_thousandの値に基準となる単位を加えた桁数でゼロパディング
arabic_number = arabic_number.zfill(unit_under_thousand[character] + base_unit)
# ループの最後(先頭の文字)か、次のループ(一つ前の文字)が単位を表す文字ならば、1を前に付け加える
if i == len(reversed_kansuuji) - 1 or reversed_kansuuji[i+1] in unit_under_thousand or reversed_kansuuji[i+1] in unit_over_thousand:
arabic_number = '1' + arabic_number
# 万、億、兆、京の場合
elif character in unit_over_thousand.keys():
# unit_over_thousandの値の桁数でゼロパディング
arabic_number = arabic_number.zfill(unit_over_thousand[character])
# 基準となる単位を更新
base_unit = unit_over_thousand[character]
# 一〜九の場合
else:
# 一〜九の変換表を用いて変換した数字を前に付け加える
arabic_number = character.translate(convert_table) + arabic_number
return arabic_number
# 第○○条の部分にマッチさせ、○○という漢数字をキャプチャするパターン
pattern = re.compile(r'第(.*)条')
# e-Govからダウンロードした条文htmlファイルの読み込み
with open('./140AC0000000045_20230713_505AC0000000066.html') as reader:
# 読み込んだhtmlファイルを一行ずつ保存するリストの初期化
output_line_list = []
for i, line in enumerate(reader):
# 読み込んだ行をリストに追加
output_line_list.append(line)
# 「第○○条」の部分にマッチさせる
result = pattern.search(line)
# 第○○条の部分にマッチした場合
if result:
# ○○という漢数字をアラビア数字に変換
arabic_joubun_number = convert_kansuuji_to_arabic_number(result.group(1))
# マッチした行の一つ前の行の「id=""」を「id="Mp-At_199"」のように変換
output_line_list[i-1] = output_line_list[i-1].replace('id=""', f'id="Mp-At_{arabic_joubun_number}"')
# 保存したリストの書き出し
with open('kei.html', 'w') as writer:
for output_line in output_line_list:
writer.write(output_line)
print('done')
細かくコメントを書き入れていますから、読めばある程度わかると思います。
前半は漢数字をアラビア数字に変換するための関数です。
pythonで漢数字をアラビア数字に変換するスクリプトで詳しく説明しました。
条文で万を超えることはないでしょうから、ここまで厳密な変換スクリプトは不要ですが、せっかくなので作ってみました。
後半がメインの処理です。
e-Govからダウンロードした条文htmlファイルを一行ずつ読み込み、「第○○条」という部分にマッチしたら、その一つ前の行に「id=”Mp-At_199″」のような形でその数字のidを付与するという処理です。
これでやりたいことができました。