Python 正規表現で個人情報マスキング
個人情報をマスキングする
ダッシュボードでデータを掲載したいものの、個人情報は情報セキュリティ的に載せられない。
CRM(顧客情報管理システム)などで手入力されるデータは表記が揺れるため、
SQLやPowerQueryには限界を感じ、自分の扱う個人情報で特に多い電話番号のマスキングに
正規表現を使用してみた。
SQLでもある程度できるが、使用しているDBで一般的なreplace関数の引数が使えず、
何度も電話番号が出現した場合は対応できないため、諦めた。
テストデータを用意する
携帯電話と固定電話を含んだリストを作成する。
メモなどに入力され、電話番号以外にも情報があり、それは残したい想定。
data = {'ID':[1, 2, 3, 4, 5],
'Memo':['2021/12/12_テスト000-0123-4567テスト',
'2021/12/12_テスト(000)0123-4567テスト',
'2021/12/12_テスト00001234567テスト',
'2021/12/12_テスト(00)0123-4567テスト',
'2021/12/12_テスト(000-123-4567テスト']
}
df = pd.DataFrame(data)
どの正規表現がいいか試す
ハイフンや()を取り除いて10桁の数字を指定してみる
ハイフンや()を取り除くために、英数字以外を空白に置き換えて、
10桁の数字の場合、「 *** 」に置き換えしてみた。
英数字以外は \W や [^a-zA-Z0-9] で表現されるらしい。
結果は以下で、電話番号自体はマスクされた。
df['masked'] = df['Memo'].map(lambda _: re.sub(r'\d{10}', r'***', re.sub(r'\W', r'', str(_))))
#out put
# ID Memo masked
#0 1 2021/12/12_テスト000-0123-4567テスト 20211212_テスト***7テスト
#1 2 2021/12/12_テスト(000)0123-4567テスト 20211212_テスト***7テスト
#2 3 2021/12/12_テスト00001234567テスト 20211212_テスト***7テスト
#3 4 2021/12/12_テスト(00)0123-4567テスト 20211212_テスト***テスト
#4 5 2021/12/12_テスト(000-123-4567テスト 20211212_テスト***テスト
しかし、日付の記号も消えるという、やや残念な様子である。
3桁-4桁-3桁の正規表現を指定してみる
正確には、以下の数字を指定してみた。
『0-1文字の数字以外+2-3桁の数字+0-1文字の数字以外
+3-4桁の数字+0-1文字の数字以外+4桁』
0~9の数字は \d か [0-9] で表現される。
{}は、直前のものの繰り返し回数を指定できる。
\d{3}は3桁、\d{2,3}は2~3桁の、0~9の数字のどれがということになる。
? は0-1回という意味で、 [^0-9] か \D は数字以外ということで、
^ を付けるとそれ以外という意味になる。(^だけは、文字列の先頭)
[^0-9]? とすることで、0-1回の数字以外が入るという意味になる。
結果は以下で、日付は残り、電話番号だけがマスクされた。
df['masked'] = df['Memo'].map(lambda _: re.sub(r'\D?\d{2,3}\D?\d{3,4}\D?\d{4}', r'***', str(_)))
#out put
# ID Memo masked
#0 1 2021/12/12_テスト000-0123-4567テスト 2021/12/12_テスト***テスト
#1 2 2021/12/12_テスト(000)0123-4567テスト 2021/12/12_テスト***テスト
#2 3 2021/12/12_テスト00001234567テスト 2021/12/12_テスト***テスト
#3 4 2021/12/12_テスト(00)0123-4567テスト 2021/12/12_テスト***テスト
#4 5 2021/12/12_テスト(000-123-4567テスト 2021/12/12_テスト***テスト
結果
この正規表現に当てはまる電話番号以外データがない限り、
基本的には上記でカバーできそうだった。
正規表現は情報を流し読みするだけでは理解できず、
実際にいろいろ試してみて勉強になった。
正規表現について詳しくは、書籍や他記事を参照してほしい。
Discussion