정규표현을 사용하려면 import를 해주어야 한다. 간혹 정규표현식앞에 r이 붙은 것을 볼 수 있는데 이전 버전에는 r을 붙여야 한다더라. 현재는 사용할 때 r을 안붙여도 잘 돌아간다.
import re
정규표현식을 이용해서 원하는 문자열을 추출하기 위한 몇가지 함수를 소개하겠다.
method |
search() |
match() |
findall() |
finditer() |
fullmatch() |
search()와 match는 매치 될때 객체를 반환하고, 없을 때 None를 반환한다. match객체란 정규식의 검색 결과로 돌려주는 객체를 말한다.
re.search(패턴, 문자열, flags)
문자열 전체를 검색해 패턴과 일치하는 지를 조사하는 함수이다. 문자열이 처음부터 있는 경우 뿐만아니라 중간부터 일치하더라도 찾아준다.
print(re.search('ab', 'abcd'))
print(re.search('ab', 'irabcd'))
<re.Match object; span=(0, 2), match='ab'>
<re.Match object; span=(2, 4), match='ab'>
패턴 ab로 시작하는 abcd에서 매치하는지 뿐만아니라 패턴 ab가 문자열의 첫번째부터 있지 않은 'irabvd'에서도 ab가 매치하는 지를 찾아 반환하여 준다. span은 매치된 패턴의 시작과 끝+1의 인덱스를 반환한다.
re.match(패턴, 문자열, flags)
search()와 다르게 문자열의 처음부터 시작해서 패턴과 일치하는 지를 조사한다.
print(re.match('ab', 'abcd'))
print(re.match('ab', 'irabcd'))
<re.Match object; span=(0, 2), match='ab'>
None
ab로 시작하는 문자열 abcd에서는 매치된 결과를 반환하지만 그렇지 않은 경우 None을 반환하는 것을 볼 수 있다.
re.findall(패턴, 문자열, flags)
문자열중 패턴과 일치되는 모든 부분을 리스트로 반환해주는 함수이다. 반환된 리스트는 서로 겹치지 않는다.
print(re.findall('a', 'abcd'))
print(re.findall('a', 'bbbbaca'))
print(re.findall('aaa','aaaa'))
['a']
['a', 'a']
['aaa']
마지막 예에서 aaa가 겹치지만 하나만 반환하므로 반환된 리스트는 겹치지 않는다는 것을 확인할 수 있다.
re.finditer(패턴, 문자열, flags)
findall과 비슷하지만 ㅇ리치된 문자열 리스트 대신 매치 객체리스트를 반환한다.
it = re.finditer('a', 'abcda')
for i in it:
print(i)
<re.Match object; span=(0, 1), match='a'>
<re.Match object; span=(4, 5), match='a'>
re.finditer(패턴, 문자열, flags)
패턴과 문자열이 완벽하게 일치하는 지를 조사하는 함수이다.
print(re.fullmatch('ab', 'ab'))
print(re.fullmatch('ab', 'abc'))
<re.Match object; span=(0, 2), match='ab'>
None
match Object 메서드
search(), match(), finditer()는 매치 객체를 반환한다고 했다. 반환된 매치 객체를 사용하기 위한 메서드를 소개하겠다.
method | 목적 |
group() | 매치된 문자열을 반환 |
start() | 매치된 문자열의 시작위치 반환 |
end() | 매치된 문자열의 끝 위치 반환 |
span() | 매치된 문자열의 (시작, 끝) 튜플 반환 |
a = re.match('ab', 'abcd')
print(a)
print(a.group())
print(a.start())
print(a.end())
print(a.span())
b = re.search('ab', 'abcd')
print(b)
print(b.group())
print(b.start())
print(b.end())
print(b.span())
<re.Match object; span=(0, 2), match='ab'>
ab
0
2
(0, 2)
<re.Match object; span=(0, 2), match='ab'>
ab
0
2
(0, 2)
결과를 보면 알듯 match의 start는 항상 0임을 알 수 있다.
주의할 점은 end와 span의 끝 인덱스가 문자열이 끝난 인덱스가 아닌 끝난 지점 +1이라는 점이다.
re.sub(패턴, 대체문자열, 문자열, count, flag)
정규표현식을 활용해서 replace를 하려면 sub함수를 사용해야한다.
print(re.sub('\d{4}', 'XXXX', '010-1234-5678'))
010-XXXX-XXXX
길이가 4인 숫자를 xxxx로 바꿔주려면 위와 같이 사용하면 된다.
동아뉴스 html에서 기사본문 추출
def donga_extract_article(html):
article = ""
rslt = re.search("<!-- 본문내용 -->(.|\n)*?<!-- //본문내용 -->",html).group()
rslt = re.sub(".*</span></div>",'',rslt)
rslt = re.sub("<script>(.|\n)*</script>",'',rslt)
rslt = re.sub("<.*?>|</.*?>",'',rslt)
rslt = re.sub("\n",'',rslt)
article = re.sub("(\S+@\S+)",'',rslt)
return article.strip()
기사 본문은 <!-- 본문내용 -->사이에 있다는 사실을 이용해 읽어온다. search메서드에 패턴인 (.|\n)*? 은 문장이 ' . ' 또는 '\n'으로 끝나는 것을 이용해 문장별로 ()를 사용하여 그룹화하여 반복시켜 본문내용을 읽어온다. search는 객체를 반환하므로 뉴스기사의 본문을 읽어오기 위해 group를 사용한다. 문장사이에 있는 html서식을 없애주기 위해 sub함수를 사용한다.
한일뉴스 html에서 기사본문 추출
def hani_extract_article(html):
article = ""
rslt = re.sub("</div>\n|/P>\n",'',html)
rslt = re.search("<P align=justify></P>\n(.|\n)*?</a></div>",html).group()
article = re.sub("<.*>",'',rslt)
return article
동아뉴스 추출함수와 비슷한 구성이다. html서식이 다른 부분만 수정하고 문장이 ' . '과 '\n'으로 끝나는 점은 똑같이 이용했다.
참고
07-2 정규 표현식 시작하기
[TOC] ## 정규 표현식의 기초, 메타 문자 정규 표현식에서 사용하는 메타 문자(meta characters)에는 다음과 같은 것이 있다. > ※ 메타 문자란 원래 ...
wikidocs.net
Python, Machine & Deep Learning
Python, Machine Learning & Deep Learning
greeksharifa.github.io
Python, Machine & Deep Learning
Python, Machine Learning & Deep Learning
greeksharifa.github.io
'NLP > 기초' 카테고리의 다른 글
정규표현 유용한 표현 모음집 (0) | 2024.06.18 |
---|---|
[#1 이론] 정규표현식 (1) | 2021.12.01 |
[#0] 시작 (3) | 2021.12.01 |
댓글