☎️

Python 正規表現で個人情報マスキング

2023/03/25に公開

個人情報をマスキングする

ダッシュボードでデータを掲載したいものの、個人情報は情報セキュリティ的に載せられない。
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