안녕하세요 jay입니다.
지난 시간에는 urllib.request를 활용하여 웹크롤링을 해봤습니다.
이번 시간에는 크롤링한 정보를 가지고 스크레이핑을 하기 위해
정규표현식에 대해서 알아보도록 하겠습니다.
1. 정규표현식(regular expression : regex)이란?
정규 표현식은 특정한 규칙을 가진 문자열의 패턴을 표현하는 데 사용하는 표현식(Expression)으로 텍스트에서 특정 문자열을 검색하거나 치환할 때 흔히 사용됩니다.
HTML을 단순한 문자열로 취급하고, 필요한 부분을 추출해야합니다. 정규표현식에선 ₩(\)가 자주 나옵니다. 이때 r""을 사용합니다.
print('\n is an escape code') # \n을 명령기호(이스케이프문자)로 인식하여 줄바꾸기가 됨 is an escape code print(r'\n is an escape code') # \n을 문자열로 취급함 \n is an excape code
2. re모듈을 사용해서 스크레이핑하기
형식 : re.함수명(정규표현식, 스크레이핑할 데이터가 들어있는 HTML 또는 RSS)
import re #search()함수 문자열 전체를 검색하여 정규식과 매치되는지 조사하여 매치가 되면 Match 객체를 돌려줌 print(re.search(r"a.*c", 'abc123DEF')) # <re.Match object; span=(0, 3), match='abc'> print(re.search(r"a.*d", 'abc123DEF')) # None
3. 문자 클래스 []
문자 클래스로 만들어진 정규식은 "[]"사이의 문자들과 매치라는 것을 의미
문자 클래스 "[]" 안에는 어떤 문자 또는 메타 문자라도 사용할 수 있습니다.
메타 문자 : 문자가 가진 원래의 의미가 아닌 특별한 용도로 사용되는 문자를 말합니다.
문자 클래스 안에 ^ 메타 문자를 사용할 경우에는 반대(not)라는 의미
예시 :
[a-zA-Z] : 알파벳 모두
[0-9] : 숫자
* 자주 사용하는 문자 클래스
-\d - 숫자와 매치, [0-9]와 동일한 표현식
-\D = 숫자가 아닌 것과 매치, [^0-9]와 동일한 표현식
-\s - whitespace 문자와 매치, [\t\n\r\f\v]와 동일한 표현식
-\S -whitespace 문자가 아닌 것과 매치, [^ \t\n\r\f\v]와 동일한 표현식
-\w - 문자 + 숫자와 매치, [a-zA-Z0-9_]와 동일한 표현식
-\W - 문자 + 숫자와 매치, [^a-zA-Z0-9_]와 동일한 표현식
import re # \d - 숫자와 매치, [0-9]와 동일한 표현식 print(re.search(r"\d", 'abc123DEF')) # <re.Match object; span=(3, 4), match='1'> print(re.search("[\d]", 'abc123DEF')) # <re.Match object; span=(3, 4), match='1'> print(re.search("[0-9]", 'abc123DEF')) # <re.Match object; span=(3, 4), match='1'> # \D - 숫자가 아닌 것과 매치, [^0-9]와 동일한 표현식 print(re.search(r"\D" , "abcd(342)")) # <re.Match object; span=(0, 1), match='a'> print(re.search("\D" , "(abcd(342)")) # <re.Match object; span=(0, 1), match='('> print(re.search("[^0-9]", 'abc123*DEF')) # <re.Match object; span=(0, 1), match='a'> # \s - whitespace 문자와 매치, [\t\n\r\f\v]와 동일한 표현식 print(re.search(r"\s", ' abc123DEF')) # <re.Match object; span=(0, 1), match=' '> print(re.search("[\t]", '\tabc123DEF')) # <re.Match object; span=(0, 1), match='\t'> # \S - whitespace 문자가 아닌 것과 매치, [^ \t\n\r\f\v]와 동일한 표현식 print(re.search(r"\S", ' abc123DEF')) # <re.Match object; span=(3, 4), match='a'> # \w - 문자+숫자(alphanumeric)와 매치, [a-zA-Z0-9_]와 동일한 표현식 print(re.search(r"\w", 'abc123DEF')) # <re.Match object; span=(0, 1), match='a'> print(re.search("[\w]", ")!@#(!@)12342")) # <re.Match object; span=(8, 9), match='1'> # \W - 문자+숫자(alphanumeric)가 아닌 문자와 매치, [^a-zA-Z0-9_]와 동일한 표현식 print(re.search(r"\W",'abc123D()!@$EF')) # <re.Match object; span=(7, 8), match='('>
4. 정규표현식 패턴
패턴 | 설명 | 예제 |
---|---|---|
^ | 이 패턴으로 시작해야 함 | ^abc : abc로 시작해야 함 (abcd, abc12 등) |
$ | 이 패턴으로 종료되어야 함 | xyz$ : xyz로 종료되어야 함 (123xyz, strxyz 등) |
[문자들] | 문자들 중에 하나이어야 함. 가능한 문자들의 집합을 정의함. | [Pp]ython : "Python" 혹은 "python" |
[^문자들] | [문자들]의 반대로 피해야할 문자들의 집합을 정의함. | [^aeiou] : 소문자 모음이 아닌 문자들 |
| | 두 패턴 중 하나이어야 함 (OR 기능) | a | b : a 또는 b 이어야 함 |
? | 앞 패턴이 없거나 하나이어야 함 (Optional 패턴을 정의할 때 사용) | \d? : 숫자가 하나 있거나 없어야 함 |
+ | 앞 패턴이 하나 이상이어야 함 | \d+ : 숫자가 하나 이상이어야 함 |
* | 앞 패턴이 0개 이상이어야 함 | \d* : 숫자가 없거나 하나 이상이어야 함 |
패턴{n} | 앞 패턴이 n번 반복해서 나타나는 경우 | \d{3} : 숫자가 3개 있어야 함 |
패턴{n, m} | 앞 패턴이 최소 n번, 최대 m 번 반복해서 나타나는 경우 (n 또는 m 은 생략 가능) | \d{3,5} : 숫자가 3, 4개 혹은 5개 있어야 함 |
예시 :
import re # Dot(.) : 줄바꿈문자인 \n을 제외한 모든문자와 매치됨을 의미 # 정규식을 작성할 때 re.DOTALL 옵션을 주면 \n 문자와도 매치됨 print(re.search("\w.\d", 'abc123DEF')) # <re.Match object; span=(1, 4), match='bc1'> print(re.search(r"a.c", 'a\nc123DEF')) # None print(re.search(r"a.c", 'a\nc123DEF', re.DOTALL)) # <re.Match object; span=(0, 3), match='a\nc'> # 반복(*) : * 앞에 나온 문자가 0부터 무한대로 반복될 수 있다는 의미 print(re.search(r"a.*d", "abc123d")) # <re.Match object; span=(0, 7), match='abc123d'> print(re.search(r"a*d", "abc123d")) # <re.Match object; span=(6, 7), match='d'> print(re.search("[^\d].*[\d]" , "wsasdaska3jsklda")) # <re.Match object; span=(0, 10), match='wsasdaska3'> # 반복(+) : + 바로 앞에 있는 문자가 최소 1번이상 반복될 수 있다는 의미 print(re.search(r"ca+t", 'abcat')) # <re.Match object; span=(2, 5), match='cat'> print(re.search(r"ca+t", 'abcaaaaaaat')) # <re.Match object; span=(2, 11), match='caaaaaaat'> print(re.search("[^\d]+a" , "wsasdaska3jsklda")) # <re.Match object; span=(0, 9), match='wsasdaska'> # 반복({m,n}) {m,n} : {m,n} 표현식 앞에 있는 문자가 m부터 n까지 반복될 수 있다는 의미 # {m,}이나{,n}과 같이 사용할 수 있음 print(re.search(r"\D{3,5}", "4832avcd42ds")) # <re.Match object; span=(4, 8), match='avcd'> print(re.search("\d{3,4}-\d{4,}-\d{,4}", "010-1234-5678")) # <re.Match object; span=(0, 13), match='010-1234-5678'> # ^ : 이 패턴으로 시작해야 함, $ : 이 패턴으로 끝내야함 print(re.search("(^[\D])","BASDASD124@ASF")) # <re.Match object; span=(0, 1), match='B'> print(re.search("(\d{4}$)","010-1234-5688")) # <re.Match object; span=(9, 13), match='5688'> # group : ()를 사용, 그룹핑을 활용하여 text = "내가 찾을 양식은 031-123-1234입니다." regex = re.compile(r'(\d{3})-(\d{3}-\d{4})') # 정규 표현식 matchobj = regex.search(text) areaCode = matchobj.group(1) num = matchobj.group(2) print("지역번호는 : ",areaCode," 뒷번호는 : ", num)
다음 시간에는 re 모듈에 대해 알아보도록 하겠습니다.
댓글
댓글 쓰기