텍스트 삭제(text redaction)

정규표현식 활용

정규표현식(regular expression)을 사용해서 민감정보를 삭제해보자.

  1. 민감정보가 담긴 텍스트를 문자열로 준비한다.
  2. 전화번호 패턴을 탐지하기 위해서 휴대폰 전화번호와 유선 전화번호 패턴을 정규표현식으로 준비한다.
  3. re.sub 메쏘드를 사용해서 전화번호 패턴을 제거한다.
  4. 전자우편 패턴을 정규표현식으로 준비한다.
  5. re.sub 메쏘드를 사용해서 전자우편 패턴을 제거한다.
In [1]:
import re

pledge_message = '''
경찰의 내사를 받고 있는 성호군은 한OO 일보와 조0일보를 잠시 착각한 것으로 밝혀졌으며 \
이 와중에 전화번호 010-2345-2212 가 외부로 유출되어 핸드폰 번호를 바꾸었으나 이 과정에서 \
집전화번호 031-222-3234 도 유출되어 더이상 전화를 사용할 수 없는 자연인으로 돌아갔습니다. \
이제 본인 전자우편 sungho@gmail.com도 당연히 외부에 절대 유출되지 않도록 국민신문고에 민원을 넣었습니다."
'''

## 전화번호 민감정보 삭제
mobile_phone = "\d{3}-\d{3,4}-\d{4}"
regular_phone = "\d{2,3}-\d{3,4}-\d{4}"

phone_pattern = re.compile(mobile_phone + "|" + regular_phone)

phone_message = re.sub(phone_pattern, "XXX-XXXX-XXXX", pledge_message)  

print(phone_message)
경찰의 내사를 받고 있는 성호군은 한OO 일보와 조0일보를 잠시 착각한 것으로 밝혀졌으며 이 와중에 전화번호 XXX-XXXX-XXXX 가 외부로 유출되어 핸드폰 번호를 바꾸었으나 이 과정에서 집전화번호 XXX-XXXX-XXXX 도 유출되어 더이상 전화를 사용할 수 없는 자연인으로 돌아갔습니다. 이제 본인 전자우편 sungho@gmail.com도 당연히 외부에 절대 유출되지 않도록 국민신문고에 민원을 넣었습니다."

In [2]:
## 전자우편 민감정보 삭제

email_pattern = "(\w+\.)*\w+@(\w+\.)+[A-Za-z]+"

redacted_message = re.sub(email_pattern, "xxx@yyy.zzz", phone_message)  

print(redacted_message)
경찰의 내사를 받고 있는 성호군은 한OO 일보와 조0일보를 잠시 착각한 것으로 밝혀졌으며 이 와중에 전화번호 XXX-XXXX-XXXX 가 외부로 유출되어 핸드폰 번호를 바꾸었으나 이 과정에서 집전화번호 XXX-XXXX-XXXX 도 유출되어 더이상 전화를 사용할 수 없는 자연인으로 돌아갔습니다. 이제 본인 전자우편 xxx@yyy.zzz도 당연히 외부에 절대 유출되지 않도록 국민신문고에 민원을 넣었습니다."

spaCy 개체명 인식

문서에 포함된 민감정보를 제거하는 것이 필요한 경우가 많다. 이런 요구를 충족시키기 위해서 개인정보와 관련된 경우에 따라서 다른 연관된 정보를 식별하고 이를 제거하는 방법을 spaCy NER(named entity recognition) 기법을 활용하여 적용해 보자.

텍스트 민감정보 제거

개체명 추출

spacy를 활용하여 영문을 대상으로 개체명을 추출해본다.

In [3]:
import spacy

nlp = spacy.load('en')

ex_text = '''European authorities fined Google a record $5.1 billion on Wednesday \
for abusing its power in the mobile phone market and ordered the company to alter its practices'''

ex_text_doc = nlp(ex_text)

for ent in ex_text_doc.ents:
    print(f'텍스트: {ent.text}, \t 개체 그룹: {ent.label_}')
텍스트: European, 	 개체 그룹: NORP
텍스트: Google, 	 개체 그룹: ORG
텍스트: $5.1 billion, 	 개체 그룹: MONEY
텍스트: Wednesday, 	 개체 그룹: DATE

spacy.explain() 메쏘드를 사용하게 되면 개체 그룹인지를 확인도 할 수 있다. 예를 들어, spacy.explain('NORP')을 통해 'Nationalities or religious or political groups'임을 확인할 수 있다.

In [4]:
spacy.explain('NORP')
Out[4]:
'Nationalities or religious or political groups'

민감정보 삭제 함수

앞서 추출된 정보를 바탕으로 특정된 개체 유형(NORP, ORG, MONEY, DATE 등)에 따라 민감정보를 삭제하는 함수를 제작하여 적용시켜본다.

In [5]:
def redact_text(text, ent_type):
    
    docx = nlp(text)
    
    redacted_sentences = []

    for token in docx:
        if token.ent_type_ == ent_type:
            redacted_sentences.append("[REDACTED]")
        else:
            redacted_sentences.append(token.string)
    
    return "".join(redacted_sentences)

redact_text(ex_text, 'ORG')
Out[5]:
'European authorities fined [REDACTED]a record $5.1 billion on Wednesday for abusing its power in the mobile phone market and ordered the company to alter its practices'

시각화

다른 것들 다 떠나서 이를 시각화하여 제대로 민감정보가 삭제되었는지 확인해보자. 시각적으로 문장에서 어떤 단어가 어떠한 개체유형인지를 확인할 수 있다.

In [6]:
from spacy import displacy

displacy.render(nlp(ex_text), style='ent', jupyter=True)
European NORP authorities fined Google ORG a record $5.1 billion MONEY on Wednesday DATE for abusing its power in the mobile phone market and ordered the company to alter its practices
In [7]:
redacted_text = redact_text(ex_text, 'NORP')
displacy.render(nlp(redacted_text), style='ent', jupyter=True)
[REDACTED]authorities fined Google ORG a record $5.1 billion MONEY on Wednesday DATE for abusing its power in the mobile phone market and ordered the company to alter its practices