ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 데이터 크롤링(with Mechanize)
    CS/Data Science 2024. 3. 31. 19:03

    데이터를 수집하는 방법에는 여러가지가 있는데, 오늘은 크롤링 도구를 이용한 웹스크랩핑 방법에 대해 알아보고자 한다.

     

    많은 데이터를 제공하는 기상청 사이트에서 기상 정보를 수집해보자!

    아래 페이지에서 데이터를 수집할것이다.

     

    https://www.weather.go.kr/w/obs-climate/land/past-obs/obs-by day.do?stn=108&yy=2012&mm=4&obs=1

     

    과거관측 - 일별자료 - 기상청 날씨누리

    개편된 날씨누리 홈페이지 첫 화면에서 지도를 통한 실시간 기상정보와 레이더영상, 전국 특보 현황을 조회할 수 있으며, 내 지역의 현재 기상상황과 대기질 상태, 일출/일몰 시각을 확인할 수

    www.weather.go.kr

     

     

    데이터 크롤링의 큰 구조는 아래와 같다.

     

    'Mechanize'라는 생소한 단어가 나오는데, 이는 하나의 크롤링 도구이다.

    Mechanize는 파이썬의 외부 라이브러리로 구현되어있어 이를 이용하면 쉽게 데이터를 크롤링 할 수 있다!

     

    Mechanize :
    A tool for stateful programmatic web browsing in Python. Browse pages programmatically with easy HTML form filling and clicking of links

     

    간단하게 설명하면, 정적 웹사이트를 파이썬에서 브라우징하는데 도움을 주는 라이브러리이다.

    주요 클래스인 Browser를 이용하면, 브라우저에서 조작할 수 있는 모든 부분을 파이썬에서 조작할 수 있다.

     

    !pip install mechanize

     

    pip를 이용하여 mechanize를 다운받을 수 있다.

    import mechanize
    import http.cookiejar

    cj = http.cookiejar.CookieJar()
    br = mechanize.Browser()
    br.set_cookiejar(cj)


    data = br.response().read().decode('utf-8')

     

    위 코드를 실행시키면, data에 URL의 데이터가 html 형식으로 저장된다.

     

    하지만 위 방법으로는 한 페이지밖에 수집할 수 없고, 이는 한 달간의 자료이기 때문에 30여일정도의 데이터가 수집된다.

    for문을 이용하면 더 많은 데이터를 크롤링할 수 있다.

     

    아래 for문의 코드는 2021년도부터 2023년도까지 1월부터 12월까지의 데이터를 크롤링 하기 위한 코드이다.

     

    import time
    import mechanize
    import http.cookiejar
    import re

    cj = http.cookiejar.CookieJar()
    br = mechanize.Browser()
    br.set_cookiejar(cj)

    months= []
    for j in range(1,4):
        for i in range(1, 13):
           
            br.open(url)
            data = br.response().read().decode("utf-8")

            # 정규표현식 패턴
            pattern = '(최고기온):([-+]?\d*\.?\d+)(?:℃)?|(최저기온):([-+]?\d*\.?\d+)(?:℃)?'

            # 정규표현식을 사용하여 추출
            matches = re.findall(pattern, data)

            max = []
            min = []

            for match in matches:
                # match[0]은 최고기온 매치, match[2]는 최저기온 매치
                if match[0] != '':
                    max.append(float(match[1]))
                if match[2] != '':
                    min.append(float(match[3]))
           
            result = list(zip(min,max))
           
            months.append(result)

            time.sleep(1)

     

     

    최저기온과 최고기온 데이터를 크롤링하고자 한다.

    위 데이터만 가져오기 위해서 정규표현식을 사용해주었다.

     

     pattern = '(최고기온):([-+]?\d*\.?\d+)|(최저기온):([-+]?\d*\.?\d+)'

     

    해당 정규표현식을 살펴보자.

     

    일단 '|'를 기준으로 크게 두 부분으로 나뉜다.

    그리고 ()는 캡쳐 그룹으로, 해당 부분에 일치하는 문자열이 나중에 앞에서부터 순서대로 그룹화되어 저장된다.

    즉 여기서는, (최고기온) / (숫자) / (최고기온) / (숫자) 이렇게 네 개의 그룹으로 나뉘게 될 것이다.

     

    (최고기온):([-+]?\d*\.?\d+) 이 부분을 보면,

     

    (최고기온): -> '최고기온:' 으로 시작하고,

    [-+]? -> -나 + 두 부호중에 하나가 올 수도 있고 안올수도 있고,

    \d* -> 숫자가 0개 이상 나오고,

    \. -> 소수점이 있을 수도 있고,

    \d+ -> 숫자가 하나 이상 나온다.

     

    이런 뜻이다.

     

    (최저기온):([-+]?\d*\.?\d+)도 동일하게 해석하면 된다.

     

    이제 이 패턴을 기반으로 

    matches = re.findall(pattern, data)

     

    matches라는 배열에 '데이터'에서 찾은 패턴이 저장된다.

     

    여기서 캡처 그룹을 4개 (최고기온)(온도)(최저기온)(온도)로 설정했기 때문에 배열 한칸당 4개의 칼럼을 가지게 될 것이다.

     

Designed by Tistory.