강의 내용 중에 등장했던 newspaper 라이브러리가 생각나서 사용해보았습니다.
from soynlp.normalizer import *
import re
def preprocess(text):
# HTML 태그 제거
text = re.sub(r"<[^>]+>\s+(?=<)|<[^>]+>", "", text).strip()
# 이메일 제거
text = re.sub(r"[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+", "", text).strip()
# 해쉬태그 제거
text = re.sub(r"#\S+", "", text).strip()
# 멘션 제거
text = re.sub(r"@\w+", "", text).strip()
# URL 제거
text = re.sub(r"(http|https)?:\/\/\S+\b|www\.(\w+\.)+\S*", "", text).strip()
text = re.sub(r"pic\.(\w+\.)+\S*", "", text).strip()
# 특수 문자 제거
text = re.sub(r"[^\w\s…]", "", text)
# 문제를 일으킬 수 있는 문자 제거
bad_chars = {"\u200b": "", "…": " ... ", "\ufeff": ""}
for bad_char in bad_chars:
text = text.replace(bad_char, bad_chars[bad_char])
text = re.sub(r"[\+á?\xc3\xa1]", "", text)
# 언론 정보 제거
re_patterns = [
r"\([^(]*?(뉴스|경제|일보|미디어|데일리|한겨례|타임즈|위키트리)\)",
r"[가-힣]{0,4} (기자|선임기자|수습기자|특파원|객원기자|논설고문|통신원|연구소장) ", # 이름 + 기자
r"[가-힣]{1,}(뉴스|경제|일보|미디어|데일리|한겨례|타임|위키트리)", # (... 연합뉴스) ..
r"\(\s+\)", # ( )
r"\(=\s+\)", # (= )
r"\(\s+=\)", # ( =)
]
for re_pattern in re_patterns:
text = re.sub(re_pattern, "", text).strip()
# 저작권 관련 텍스트 제거
re_patterns = [
r"\<저작권자(\(c\)|ⓒ|©|\(Copyright\)|(\(c\))|(\(C\))).+?\>",
r"저작권자\(c\)|ⓒ|©|(Copyright)|(\(c\))|(\(C\))"
]
for re_pattern in re_patterns:
text = re.sub(re_pattern, "", text).strip()
# 사진 라벨 제거
text = re.sub(r"\(출처 ?= ?.+\) |\(사진 ?= ?.+\) |\(자료 ?= ?.+\)| \(자료사진\) |사진=.+기자 ", "", text).strip()
# 쓸모없는 괄호 제거
bracket_pattern = re.compile(r"\((.*?)\)")
modi_text = ""
text = text.replace("()", "") # 수학() -> 수학
brackets = bracket_pattern.search(text)
if brackets:
replace_brackets = {}
# key: 원본 문장에서 고쳐야하는 index, value: 고쳐져야 하는 값
# e.g. {'2,8': '(數學)','34,37': ''}
while brackets:
index_key = str(brackets.start()) + "," + str(brackets.end())
bracket = text[brackets.start() + 1 : brackets.end() - 1]
infos = bracket.split(",")
modi_infos = []
for info in infos:
info = info.strip()
if len(info) > 0:
modi_infos.append(info)
if len(modi_infos) > 0:
replace_brackets[index_key] = "(" + ", ".join(modi_infos) + ")"
else:
replace_brackets[index_key] = ""
brackets = bracket_pattern.search(text, brackets.start() + 1)
end_index = 0
for index_key in replace_brackets.keys():
start_index = int(index_key.split(",")[0])
modi_text += text[end_index:start_index]
modi_text += replace_brackets[index_key]
end_index = int(index_key.split(",")[1])
modi_text += text[end_index:]
modi_text = modi_text.strip()
text = modi_text
# 반복 문자 개수 고정
text = repeat_normalize(text, num_repeats=2).strip()
# 기호 치환
punct_mapping = {"‘": "'", "₹": "e", "´": "'", "°": "", "€": "e", "™": "tm", "√": " sqrt ", "×": "x", "²": "2", "—": "-", "–": "-", "’": "'", "_": "-", "`": "'", '“': '"', '”': '"', '“': '"', "£": "e", '∞': 'infinity', 'θ': 'theta', '÷': '/', 'α': 'alpha', '•': '.', 'à': 'a', '−': '-', 'β': 'beta', '∅': '', '³': '3', 'π': 'pi', }
for p in punct_mapping:
text = text.replace(p, punct_mapping[p])
text = text.strip()
# 연속 공백 제거
text = re.sub(r"\s+", " ", text).strip()
return text
clean_texts = [preprocess(text) for text in texts]
추가적으로 공유할 내용이, 데이터셋에 엄청 자주 등장하는 '…'이 말줄임표가 베이스라인에서 제공되는 토크나이저에서는 unk 토큰으로 토큰화 되는 것을 확인했습니다. 그래서 지금은 ' ... '으로 놔둔 상태인데, 다시 '…'로 바꾸고 스페셜 토큰을 추가하는 방법이 좋을 지, 현재 방법이 좋을 지 실험 해봐야 할 것 같습니다.
아래는 결과 csv 파일입니다.