파이썬(Python)/웹스크롤링

[Python] 공공데이터포털에서 미세먼지 데이터 가져오기(크롤링, fine dust, API, 파이썬)

끄적끄적아무거나 2022. 5. 24. 09:07
반응형

 

목차

     

    이번 시간에는 파이썬을 사용해서 공공데이터 포탈의 API에 접속해서 미세먼지 정보를 가져오는 방법에 대해 알아보겠습니다.

     

    API(Application Programming Interface) 란?

     

    API란 데이터회사나 웹서버(Web server) 회사에서 제공하는 리모콘과 같은 것입니다. 사용자는 리모콘의 동작 방법을 이해하지는 못하지만 리모콘을 통해서 웹 서버 회사가 제공하는 데이터를 손쉽게 접근할 수 있게 되는 것입니다. 

     

    여기서 공공데이터 포탈은 API를 통해 미세 먼지 정보를 손쉽게 제공 합니다.

     

     

     

    공공데이터포탈에서 API 요청하기

     

    우선 구글에서 공공데이터포털로 검색하거나 https://www.data.go.kr/ 에 접속합니다. 정부기관 홈페이지므로 go.kr로 끝나는지 꼭 확인하시길 바랍니다. 

     

    우선 회원 하이디가 없으시면 가입을 하셔야 합니다. 네이버, 카카오톡 연계로 쉽게 가입할 수 있으니 참조하시길 바랍니다. 

     

    1. 검색창에 아래와 같이 대기오염을 검색합니다.

     

     

     

    2. 오픈 API 항목에서 "한국환경공간_에어코리아_대기오염정보"에서 "활용신청" 버튼을 클릭합니다.

     

     

     

     

    3. 아래와 같이 활용목적을 선택하고 이유를 간단하게 작성해줍니다. 그리고 아래에 활용신청 버튼을 클릭합니다.

     

     

     

     

     

    4. 신청 완료 후 아래와 같이 인증키를 확인할 수 있습니다. 아래 인증키로 API를 사용할 수 있게 된 것입니다.

     

     

     

    5. 아래와 같이 "시도별 실시간 측정정보 조회" 를 클릭 후 미리보기 버튼을 클릭 합니다.

     

     

     

    6. 아래와 같이 XML 문서형식으로 데이터를 불러 올 수 있습니다. 앞으로 크롤링에서 데이터를 이용할 때 아래 웹 주소값을 이용할 수 있습니다.

     

     

     

     

     

     

     

     

     

    공공데이터포탈의 미세먼지 데이터 파이썬 크롤링(Crawling) 하기

     

    이번에는 앞서 받아온 주소를 사용해서 파이썬 크롤링을 해보겠습니다. 이번 내용은 단순히 파일을 읽는 것만 진행하고 구체적인 크롤링 사용 법은 다음 장에서 알아보겠습니다. 

     

     

    예제 코드>>

    import requests
    dust = requests.get("API주소값")
    
    dust.raise_for_status()
    print("reponse : ", dust.status_code) 
    
    with open("dust_info.html", "w", encoding="utf8") as f:
        f.write(dust.text)
    
    print(dust.text)

     

    2번 라인: API주소값은 앞서 미세먼지 API에서 알아낸 주소값을 입력 합니다.

    4번 라인: HTTP 문서를 2번 라인에서 GET으로 요청 했기 때문에 정상 응답이 오면 200 을 response 로 보냅니다.만일 200이 아니면 웹상에서 문제가 발생했음을 알 수 있습니다.

    7~8번 라인: API 주소를 통해 읽은 값을 dust_info.html 이라는 파일명으로 파이썬 코드를 작성하고 있는 폴더에 저장해줍니다.

    10번 라인: 전체 문서를 출력 합니다.

     

     

    결과>>

    위쪽 상단에 dust_info.html 파일이 생성되었습니다.

     

     

     

    출력 결과>>

    reponse :  200
    <?xml version="1.0" encoding="UTF-8"?>
    <response>
      <header>
        <resultCode>00</resultCode>
        <resultMsg>NORMAL_CODE</resultMsg>
      </header>
      <body>
        <items>
          <item>
            <so2Grade>1</so2Grade>
            <coFlag/>
            <khaiValue>74</khaiValue>
            <so2Value>0.003</so2Value>
            <coValue>0.4</coValue>
            <pm25Flag/>
            <pm10Flag/>
            <o3Grade>1</o3Grade>
            <pm10Value>26</pm10Value>
            <khaiGrade>2</khaiGrade>
            <pm25Value>21</pm25Value>
            <sidoName>서울</sidoName>
            <no2Flag/>
            <no2Grade>1</no2Grade>
            <o3Flag/>
            <pm25Grade>2</pm25Grade>
            <so2Flag/>
            <dataTime>2022-05-24 08:00</dataTime>
            <coGrade>1</coGrade>
            <no2Value>0.028</no2Value>
            <stationName>중구</stationName>
            <pm10Grade>2</pm10Grade>
            <o3Value>0.027</o3Value>
          </item>
          
     ///////생략////////
          
          <item>
            <so2Grade>1</so2Grade>
            <coFlag/>
            <khaiValue>74</khaiValue>
            <so2Value>0.003</so2Value>
            <coValue>0.4</coValue>
            <pm25Flag/>
            <pm10Flag/>
            <o3Grade>1</o3Grade>
            <pm10Value>38</pm10Value>
            <khaiGrade>2</khaiGrade>
            <pm25Value>24</pm25Value>
            <sidoName>서울</sidoName>
            <no2Flag/>
            <no2Grade>1</no2Grade>
            <o3Flag/>
            <pm25Grade>2</pm25Grade>
            <so2Flag/>
            <dataTime>2022-05-24 08:00</dataTime>
            <coGrade>1</coGrade>
            <no2Value>0.027</no2Value>
            <stationName>강서구</stationName>
            <pm10Grade>2</pm10Grade>
            <o3Value>0.022</o3Value>

     

     

     

     

    공공데이터포탈의 미세먼지 데이터 파이썬 크롤링(Crawling) 주의 사항

     

    앞서 미세먼지 데이터는 HTTPS 로 전달하기 때문에 암호화가 걸려 있습니다. 그러므로 HTTPS 주소를 사용하시게 되면 아래와 같이 에러 메세지가 발생합니다. 

     

    에러메세지>>

    Traceback (most recent call last):
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\connectionpool.py", line 703, in urlopen        
        httplib_response = self._make_request(
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\connectionpool.py", line 386, in _make_request  
        self._validate_conn(conn)
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\connectionpool.py", line 1040, in _validate_conn
        conn.connect()
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\connection.py", line 414, in connect
        self.sock = ssl_wrap_socket(
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\util\ssl_.py", line 449, in ssl_wrap_socket
        ssl_sock = _ssl_wrap_socket_impl(
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\util\ssl_.py", line 493, in _ssl_wrap_socket_impl
        return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\ssl.py", line 512, in wrap_socket
        return self.sslsocket_class._create(
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\ssl.py", line 1070, in _create
        self.do_handshake()
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\ssl.py", line 1341, in do_handshake
        self._sslobj.do_handshake()
    ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\adapters.py", line 440, in send
        resp = conn.urlopen(
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\connectionpool.py", line 785, in urlopen
        retries = retries.increment(
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\urllib3\util\retry.py", line 592, in increment
        raise MaxRetryError(_pool, url, error or ResponseError(cause))
    urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='apis.data.go.kr', port=443): Max retries exceeded with url: /B552584/ArpltnInforInqireSvc/getCtprvnRltmMesureDnsty?serviceKey=OwMVmW1NKr%2Bopg21trL%2B2g2yaT7%2BlepKYMBMz8CboLoNnpftyGVGkSZLJM9415bEJhih4tZEMuqLMq6Wr5HCMg%3D%3D&returnType=xml&numOfRows=100&pageNo=1&sidoName=%EC%84%9C%EC%9A%B8&ver=1.0 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)')))
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "d:\Python\test03\test05.py", line 2, in <module>
        dust = requests.get("https://apis.data.go.kr/B552584/ArpltnInforInqireSvc/getCtprvnRltmMesureDnsty?serviceKey=OwMVmW1NKr%2Bopg21trL%2B2g2yaT7%2BlepKYMBMz8CboLoNnpftyGVGkSZLJM9415bEJhih4tZEMuqLMq6Wr5HCMg%3D%3D&returnType=x  File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\api.py", line 75, in get
        return request('get', url, params=params, **kwargs)
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\api.py", line 61, in request
        return session.request(method=method, url=url, **kwargs)
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\sessions.py", line 529, in request
        resp = self.send(prep, **send_kwargs)
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\sessions.py", line 645, in send
        r = adapter.send(request, **kwargs)
      File "C:\Users\forgo\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\adapters.py", line 517, in send
        raise SSLError(e, request=request)
    requests.exceptions.SSLError: HTTPSConnectionPool(host='apis.data.go.kr', port=443): Max retries exceeded with url: /B552584/ArpltnInforInqireSvc/getCtprvnRltmMesureDnsty?serviceKey=OwMVmW1NKr%2Bopg21trL%2B2g2yaT7%2BlepKYMBMz8CboLoNnpftyGVGkSZLJM9415bEJhih4tZEMuqLMq6Wr5HCMg%3D%3D&returnType=xml&numOfRows=100&pageNo=1&sidoName=%EC%84%9C%EC%9A%B8&ver=1.0 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)')))

     

     

    다행히 공공데이터 웹에서는 HTTP 주소로도 값을 전달하므로 앞서 주소값에서 HTTPS를 HTTP로 수정 해주시면 됩니다.

     

    반응형