정규표현식
regular expression
특정한 패턴과 일치하는 문자열를 '검색', '치환', '제거' 하는 기능을 지원
정규표현식의 도움없이 패턴을 찾는 작업(Rule 기반)은 불완전 하거나, 작업의 cost가 높음
e.g) 이메일 형식 판별, 전화번호 형식 판별, 숫자로만 이루어진 문자열 등
raw string
문자열 앞에 r이 붙으면 해당 문자열이 구성된 그대로 문자열로 변환
예시)
a = 'abcdef\n'
print(a)
b = r'abcdef\n'
print(b)
기본 패턴
import re
#abcdef 에서 abc가 존재하는지 찾는 경우
m = re.search(r'abc', 'abcdef')
#시작하는 곳
print(m.start())
#끝나는 곳 (파이썬 특성상 시작은 포함 끝은 미포함)
print(m.end())
#시작하는 곳
print(m.group())
결과
0
3
abc
# 없는 경우엔 None
m = re.search(r'\d\d\d', '112abcdef99')
m
결과
<re.Match object; span=(0, 3), match='112'>
예시)
m = re.search(r'[cbm]at', 'cat')
m
결과
<re.Match object; span=(0, 3), match='cat'>
m = re.search(r'[^abc]aron', 'aron')
m1 = re.search(r'[^abc]aron', 'garon')
m1
결과
<re.Match object; span=(0, 5), match='garon'>
\
다른 문자와 함께 사용되어 특수한 의미를 지님
\d : 숫자를 [0-9]와 동일
\D : 숫자가 아닌 문자 [^0-9]와 동일
\s : 공백 문자(띄어쓰기, 탭, 엔터 등)
\S : 공백이 아닌 문자
\w : 알파벳대소문자, 숫자 [0-9a-zA-Z]와 동일
\W : non alpha-numeric 문자 [^0-9a-zA-Z]와 동일
메타 캐릭터가 캐릭터 자체를 표현하도록 할 경우 사용
. , \
#띄어쓰기
re.search(r'\sand', 'apple and banana')
<re.Match object; span=(5, 9), match=' and'>
re.search(r'a[bcd]*b', 'abcdbccdb')
결과
ab도 만족을 하지만 가장 많은 abcdccb로
<re.Match object; span=(0, 9), match='abcdbccdb'>
re.search(r'b\w+a', 'banana')
결과
<re.Match object; span=(0, 6), match='banana'>
^, $
^ 문자열의 맨 앞부터 일치하는 경우 검색
$ 문자열의 맨 뒤부터 일치하는 경우 검색
grouping
()을 사용하여 그루핑
매칭 결과를 각 그룹별로 분리 가능
패턴 명시 할 때, 각 그룹을 괄호() 안에 넣어 분리하여 사용
#e-mail pattern
#id, domain 구분
m = re.search(r'(\w+)@(.+)', 'test@gmail.com')
print(m.group(1))
print(m.group(2))
결과
test
gmail.com
re.search('pi{3}g', 'piiig')
<re.Match object; span=(0, 5), match='piiig'>
#greedy 하게 검색하기 때문에 처음부터 끝까지 찾음
re.search('<.+>', '<html>haha</html>')
#최소한으로 매칭 되는 것을 검색
re.search('<.+?>', '<html>haha</html>')
결과
<re.Match object; span=(0, 6), match='<html>'>
#greedy 하게 검색하기 때문에 처음부터 끝까지 찾음
re.search('a{3,5}', 'aaaaa')
#최소한으로 매칭 되는 것을 검색
re.search('a{3,5}?', 'aaaaa')
결과
<re.Match object; span=(0, 3), match='aaa'>
re. 다른 패키지
#결과 안 나옴
re.match(r'\d\d\d', 'my number is 123')
#결과나옴 search에서 '^'와 유사
re.match(r'\d\d\d', '123 is my number')
re.findall(r'[\w-]+@[\w.]+', 'test@gmail.com haha test2@naver.com test test')
결과
['test@gmail.com', 'test2@naver.com']
re.sub(r'[\w-]+@[\w.]+', 'email', 'test@gmail.com haha test2@naver.com test test', count = 1)
결과
'email haha test2@naver.com test test'
email_reg = re.compile(r'[\w-]+@[\w.]+')
email_reg.search('test@gmail.com haha test2@naver.com test test')
결과
<re.Match object; span=(0, 14), match='test@gmail.com'>
연습문제
아래 뉴스에서 이메일 주소를 추출해 보세요
다음중 올바른 (http, https) 웹페이지만 찾으시오
import requests
from bs4 import BeautifulSoup
# 위의 두 모듈이 없는 경우에는 pip install requests bs4 실행
def get_news_content(url):
response = requests.get(url)
content = response.text
soup = BeautifulSoup(content, 'html5lib')
div = soup.find('div', attrs = {'id' : 'harmonyContainer'})
content = ''
for paragraph in div.find_all('p'):
content += paragraph.get_text()
return content
news1 = get_news_content('https://news.v.daum.net/v/20190617073049838')
print(news1)
(로스앤젤레스=연합뉴스) 옥철 특파원 = 팀 쿡 애플 최고경영자(CEO)가 16일(현지시간) 실리콘밸리 앞마당 격인 미국 서부 명문 스탠퍼드대학 학위수여식에서 테크기업들을 향해 쓴소리를 쏟아냈다.쿡은 이날 연설에서 실리콘밸리 테크기업들은 자신들이 만든 혼란에 대한 책임을 질 필요가 있다고 경고했다.근래 IT 업계의 가장 큰 이슈인 개인정보 침해, 사생활 보호 문제를 콕 집어 라이벌인 구글, 페이스북 등 IT 공룡을 겨냥한 발언이라는 해석이 나왔다.쿡은 "최근 실리콘밸리 산업은 고귀한 혁신과는 점점 더 거리가 멀어지는 것으로 알려져 있다. 책임을 받아들이지 않고도 신뢰를 얻을 수 있다는 그런 믿음 말이다"라고 꼬집었다.개인정보 유출 사건으로 미 의회 청문회에 줄줄이 불려 나간 경쟁사 CEO들을 향해 일침을 가한 것으로 보인다.그는 또 실리콘밸리에서 희대의 사기극을 연출한 바이오벤처 스타트업 테라노스(Theranos)를 직격했다.쿡은 "피 한 방울로 거짓된 기적을 만들 수 있다고 믿었느냐"면서 "이런 식으로 혼돈의 공장을 만든다면 그 책임에서 절대 벗어날 수 없다"라고 비난했다.테라노스는 손가락 끝을 찔러 극미량의 혈액 샘플만 있으면 각종 의학정보 분석은 물론 거의 모든 질병 진단이 가능한 바이오헬스 기술을 개발했다고 속여 월가 큰손들로부터 거액의 투자를 유치했다가 해당 기술이 사기인 것으로 드러나 청산한 기업이다.쿡은 애플의 경우 프라이버시(사생활) 보호에 초점을 맞춘 새로운 제품 기능들로 경쟁사들에 맞서고 있다며 자사의 데이터 보호 정책을 은근히 홍보하기도 했다.oakchul@yna.co.kr저작권자(c)연합뉴스. 무단전재-재배포금지
email_reg = re.compile(r'[\w-]+@[\w.]+[0-9a-zA-Z]+')
email_reg.search(news1)
webs = ['http://www.test.co.kr',
'https://www.test1.com',
'http://www.test.com',
'ftp://www.test.com',
'http:://www.test.com',
'htp://www.test.com',
'http://www.google.com',
'https://www.homepage.com.']
web_reg = re.compile(r'https?://[\w.]+\w+$')
list(map(lambda w: web_reg.search(w) != None, webs))
결과
[True, True, True, False, False, False, True, False]