코딩걸음마

공공데이터 API를 활용한 데이터 크롤링 방법 (ex.경주마 성적정보) 본문

나만의 프로그램

공공데이터 API를 활용한 데이터 크롤링 방법 (ex.경주마 성적정보)

코딩걸음마 2022. 7. 10. 00:48
728x90

1) 출력 데이터 확인 및 결정 (출력 변수 확인)

공공데이터는 생각보다(?) 순순하게 정보를 주지 않더군요

크롤링 코드를 한줄씩 쓰면서 머리를 많이 굴렸습니다.

 

마이페이지 에 들어가서 승인받은 데이터를 클릭한 후 상세설명클릭합니다.

상세설명을 누르면 데이터 요청방법을 알 수 있다.

 

 

아래로 내리다 보면 나오는 리스트를 보면 다양한 정보에 대한 출력변수를 알 수 있습니다.

모든 데이터를 편하게 요청하기 위해 하나의 csv 또는 xlsx 파일을 하나 만들어서 출력변수를 한번에 요청하는 방법을 사용하겠습니다.

위 영역의 데이터를 긁어 엑셀을 열고, 하나의 엑셀파일에 붙여넣기 해주세요

 

 

요청변수 엑셀파일을 정리하여 요청리스트로 정리합니다.

 

(1) 소문자로 전처리

  출력변수 설명에는 Camel 표기법으로 되어있지만, 실제 입력 시에는 모두 소문자로 입력을 해야합니다.

(2) 필요한 요청변수만 골라내기

출력변수를 입력하고 데이터를 받더라도, 연도별로 제공하는 데이터가 다른 경우가 있어 유의가 필요합니다.

   심지어는 요청변수 설명에 없는 데이터도 제공하는 경우도 있습니다.

    저는 각 연도를 모두 확인하고, 중복되는  출력 데이터만을 사용했습니다.

df_info = pd.read_excel('Horse_Race(1985~2022).xlsx', header=0)
df_info['요청코드'] = df_info['요청코드'].str.lower()

# 요청변수 리스트 작성
req_ls = df_info['요청코드'].tolist()

 

 

2)  데이터의 크기 확인 및 요청변수 세팅 

그 다음 관문은 데이터가 얼마나 있는지 확인을 하는 단계입니다.

다시 마이페이지 로 돌아와(물론 뒤로가기를 눌러도 됩니다) 승인받은 데이터를 클릭한 후 

조금 내려서 활용신청 상세기능 정보의 확인을 클릭합니다.

 

 

확인을 클릭하면 다음과 같은 요청변수 입력란이 나옵니다. 여기에  요청갑을 입력하여 출력 결과를

미리 볼 수 있습니다.

요청 변수 설명은 필 또는 옵으로  나뉩니다.

필 = 필수 입력사항이라는 뜻입니다.

옵 = 입력을 안해도 되지만, 입력을 안했을 때 전체 데이터를 불러오는게 아니라는 점을 기억하세요.

 

 

요청변수에 대한 세부 설명이 필요하면 아래를 참조하세요

serviceKey 필   = 여러분의 인증키를 넣는 곳입니다.

numOfRows 필  = 한 결과창에서 볼 수 있는 최대 데이터의 양을 말합니다. 200 입력 시, 결과창에서 200개의 데이터를 볼 수 있습니다. 

PageNo 필  =결과창의 페이지 번호를 말합니다. 만약 numOfRows 가 200이고 PageNo가 2라면 201번째 데이터부터 400번째 데이터를 볼 수 있습니다. 

numOfRowsPageNo 를 반복문으로 돌리기 이전에 numOfRows 를 100,000으로 PageNo 를 1로 하여 요청을 해봤는데 numOfRows 가 2000을 넘어가면 서버에서 결과를 안주더라구요(아마도 시간초과?) 그래서 조금씩 쪼개서 요청했습니다.

그리고 데이터가 얼마나 있을지 몰라서 우선 특정 연도를 샘플로 뽑아 numOfRows 를 2000으로 PageNo 을 1000으로 하여 평균적인 데이터 총량을 확인하고 연간 평균 데이터 생산량이 어느정도인지 가늠을 해봤습니다.

그 후, 23~24천개 정도의 데이터가 평균적으로 나오는 것을 확인했고, 최대 30000개의 데이터를 받을 수 있도록 코드를 짰습니다. 

 

rc_year 옵  이 데이터에서는 미입력시 2020 ~ 2022년 데이터만 가져옵니다.. 그래서 반복문을 이용했습니다.

rc_month 옵  미입력시, 모든 월의 데이터를 가져옵니다.

rc_date 옵  미입력시, 모든 일의 데이터를 가져옵니다.

 

[크롤링 코드 전체]

import time
import pandas as pd
import requests
from bs4 import BeautifulSoup
import numpy as np
import re
from tqdm import tqdm
import requests

# %% 요청코드 리스트
df_info = pd.read_excel('Horse_Race(1985~2022).xlsx', header=0)
df_info['요청코드'] = df_info['요청코드'].str.lower()

# 요청변수 리스트 작성
req_ls = df_info['요청코드'].tolist()

# df 컬럼명 리스트 작성
col_ls = df_info['구분'].tolist()

# %% 공공데이터 가져오기
# 총 데이터 수를 모르므로, 최대 3만개를 가정하여 2000개 단위(호출되는 최대값)로 나누여 요청함
total_df = pd.DataFrame()
for j in tqdm(range(1985,2023)):  
    for i in tqdm(range(1, 15)):
        api_key = '당신의 공공데이터 인증키를 여기에 입력하세요'
        url = 'https://apis.data.go.kr/B551015/API214/RaceDetailResult?serviceKey=' + api_key + '&pageNo=' + str(i) + '&numOfRows=2000'+'&rc_year='+str(j)  
        # %% 전체 df 만들기
        response = requests.get(url, verify=False)
        soup = BeautifulSoup(response.content, features="lxml")

        subtotal_df = pd.DataFrame()


        try :
            for req in req_ls:
                temp_ls = soup.find_all(req)
                temp_df = pd.DataFrame(temp_ls)
                subtotal_df = pd.concat([subtotal_df, temp_df], axis=1)
            subtotal_df.columns = col_ls
            total_df = pd.concat([total_df, subtotal_df], axis=0)

        except :
            continue


total_df.columns = col_ls
total_df
total_df.to_csv("Horse_Race_all(1985,2023).csv, index=False)
728x90
Comments