TEAMLAB

Human knowledge belongs to the world . -AntiTrust

Web scraping with Regular expression

우리는 데이터를 분석하고자 할 때 여러 사이트 및 공공기관, 기업데이터를 사용할 수 있지만 그들은 분석자가 원하는 데이터를 모두 가지고 있지 못한다. 또한 웹사이트나 소셜미디어 사용자의 댓글이나 글을 분석하는 오피니언 마이닝을 하고자 할 때 웹스크래핑 능력은 필수사항이다. 이번 포스트에서 다룰 정규표현식은 웹스크래핑이 사용될 뿐만 아니라 텍스터마이닝 전처리 때에도 사용되므로 매우 중요한 학습 중 하나이다.

정규표현식이란?

특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어를 말하는 것으로 . ^ * + ? { } [ ] \ | ( ) 와 같은 기호로 표현된다. 특정한 규칙을 가진 문자열의 집합을 추출하는 것이다. 이를테면 정규식 $ a. $ 에서 a는 말그대로 ‘a’와 일치하는 문자이며 . 이 의미하는 것은 새로운 줄의 문자가 아닌 모든 문자와 일치시키는 문자이다. 그러므로 이 정규식은 ‘a’, ‘ax’, ‘a0’, ‘and’ 모두와 일치시킬 수 있다. 이제부터 각 기호와 함께 어떻게 쓰이는지와 이를 이용한 웹스크래핑을 배워보도록 하겠다. 참고로 이러한 정규표현식을 예제를 통해 연습하고자 한다면 pythex 사이트를 이용하는 것을 권장한다.

Regular expression - Meta symbol([], -, ^, ., *, +, {}, ?)

  • Hyphen(-)

먼저 가장 기초인 - 에 대해 알아볼건데 이 기호는 From - to 로 이해하면 편할 것이다. 참고로 [] 는 안에 속한 문자들은 or 의 형식으로 문자를 매치시킨다. 예를 들어 [abc] 이면 a, be, abc, cr 등 [] 안의 문자가 하나라도 속해져있다면 속한다면 모두 추출해준다. 다시 돌아와 - 기호 에 대한 설명을 계속하면 [a-zA-Z] 는 알파벳 모두를 불러오는 것으로 매우 자주 사용하게 되며 꼭 기억해야할 문구 중 하나다. 마찬가지로 [0-9] 는 숫자 모두를 표현하는 것이다. 알파벳과 숫자 모두를 표현하고 싶다면 \w 를 사용하도록 하자. 이는 [a-zA-Z0-9] 와 같은 표현이다. 참고로 정규표현식은 대소문자를 구분하여 매치시켜주니 꼭 구분하여주자.

- ex 1) x 와 y 중 하나를 찾고자 할 때
    answer: '[xy]'

- ex 2) 모든 텍스트를 불러오고 싶을 때 
    answer: '[a-zA-Z0-9]'
  • Caret(^)

다음으로 알아야 할 것은 ^ 이다. 이는 not 이라는 의미를 가지고 있으며 예를 들어 [^0-9] 로 사용하게 된다면 숫자를 제외한 모든 텍스트를 표현한다. 참고로 숫자를 제외한 모든 텍스트는 \D 와 같다. 꼭 대문자로 사용해야하며 소문자인 d 로 사용할 경우 숫자만 표현한다. 대표적인 예로 IP 를 추출하고자 할 때 \d 를 많이 사용하게 된다. 예는 5번의 반복문을 설명할 때 제시한다.

  • Dot(.)

다음은 처음에 한번 언급한 $ . $ 이다. 모든 문자를 표현하며 예를 들어 a.z 라고 한다면 (a + 모든문자 + z) 를 일컫는다. 하지만 Dot(.) 이 붙은 만큼 하나의 문자라도 필히 있어야한다. aze 라는 문자가 있다면 이는 당연히 표현되지 않는다. 그럼 정말 a.z 라는 단어만 표현하고싶다면? 그럼 a[.]z 혹은 a.z 라고 표현하면 된다.

- ex) a 와 j 사이에 세개의 문자가 있는 텍스트만 매치시키고 싶을 때
    answer: 'a...j'
  • asterisk(*) and Plus(+)

$ * $ 는 바로 앞의 문자가 0번에서 무한에 이르기까지 반복 인식하여 문자를 표현해준다. 예를 들어 $ ac*g $ 를 한다면 acg, accg, acccg 그리고 c가 나오지않는 ag 또한 매치시켜준다. 반대로 + 를 한번 보도록하자. + 는 최소 1번은 앞의 문자가 있어야만 매치시켜준다. 즉 앞의 예로 들자면 ac+g 이면 ag 는 인식이 되지않는다. 참고로 (.+) 구문은 매우 자주 사용하게 될 것이다.

  • Bracket({}) and Question mark(?)

다음으로 알아볼 메타기호는 {} 와 ? 이다. 먼저 {} 는 반복을 의미한다. 예를 들어 코드 ab{2}c 가 있다면 이는 abbc 만 인식한다 {2} 앞의 문자인 b 가 무조건 2번 나와야한다고 생각하면 된다. $ ? $ 는 or 의 개념으로 앞의 문자가 있어도 되고 없어도 된다. 예를 들어 ab?c 가 있다면 abc, ac 둘다 인식될 것이다.

- ex 1) 203.252.101.58  (IP)
    answer: '\d{3}\.\d{3}\.\d{3}\.\d{2}' 

- ex 2) 010-7705-4105  (Phone Number)
    answer: '\d{3}\-\d{4}\-\d{4}'
  • back slash()

백슬래시는 상당히 정규표현식을 복잡하게 만든다. 그러므로 제대로 짚고넘어가야한다. 예를 들어 우리는 \daddy 라는 단어를 찾고자한다. 하지만 \d 는 앞에 언급했다시피 숫자와 매치되는 구문이다. 이럴 때는 백슬래시를 하나 더 붙여줘 \\daddy 라고 표현해야한다. 하지만 또 하나 문제가 있었으니 바로 파이썬 문자열 형식은 \\ 를 \ 로 바꿔버린다. 때문에 \\\\daddy 로 표현해야하는 일이 생겨난다. 이럴떄는 앞에 r 를 붙여주도록하자. Raw string 규칙으로 바꿔주는 의미로 생각하면된다.

- ex) \daddy 
    answer: r'\\daddy'

Web Scraping with python

자 이제 그동안 배운 정규표현식으로 데이터를 가져와보자. 필자는 현재 자동차에 관심이 많으므로 네이버의 인기조회순 5위까지의 자동차를 가져오고싶다. 먼저 우리는 정규표현식을 지원하는 re 모듈을 import 해야한다.

>>> import re
>>> r = re.compile('ab?c')

정규표현식 모듈을 import 시키고 $ r $ 에 ‘ab?c’ 라는 정규표현식을 컴파일 시켰다. 이제 찾고자하는 데이터를 위의 컴파일된 r 과 연결해 찾고자하는 정보를 추출해 볼수도 있지만 이번 포스트에서는 compile 의 옵션까지는 다루지 않을 것이므로 re.findall 만을 통해 데이터를 가져오겠다. 이제 해당 사이트의 url 을 가지고와야한다.

>>> import urllib.request as ur
>>> url = "https://auto.naver.com/index.nhn"
>>> html = ur.urlopen(url)
>>> html_contents = str(html.read().decode("utf8"))

urllib.request 모듈을 import 해주고 다음으로 네이버 자동차 주소를 $ url $ 에 넣어줬다. $ ur.urlopen() $ 명령어를 통해 html 형식으로 저장시켜준 뒤 마지막으로 문자형식으로 바꿔주었다. 자 이제 이 긴 문자열데이터를 정규표현식으로 매치되는 값을 찾고 리스트 형식으로 바꿔주면 끝난다!

>>> rank_results = re.findall("(\<span class=\"cont\"\>)([\s\S]+?)(\<\/span\>)", html_contents)
>>> result = []
>>> for i in range(5):
        a.append(rank_results[i][1])
>>> print(result)  

자 첫줄만 알면 끝이다. re.findall 구문은 첫번쨰 값은 정규표현식이고 두번째 들어갈 값은 해당 문자열데이터이다. 우리는 첫번쨰 값에 (\<span class=\“cont\”\>)([\s\S]+?)(\<\/span\>) 를 넣어주었는데 총 세개의 괄호로 이루어져있다. 해석하자면 <span class=”cont”> 와 </span> 를 포함한 둘 사이의 모든 텍스트를 불러오는 것이다. 중간에 ([\s\S]+?) 에서 \s 는 공백에 매치되는 구문인데 한국어이므로 이렇게 표현해준 것이다. for문을 통해 각각의 튜플에서 자동차 값이 있는 두번째 값을 뽑아냈다. 결국 이런 답이 나올 것이다.

['2018 싼타페', '2018 K9', '2018 그랜저', '2018 K3', '2017 G70'] 

이렇게 기본 정규표현식과 간단한 웹스크래핑을 다루어보았다. 다음 포스트에서는 정규표현식 심화과정인 컴파일 옵션과 좀 더 간단하고 쉽게 웹크롤링을 할 수 있는 Beautifulsoup 에 대해서 다뤄보겠다.