2. 공공데이터 API를 이용한 크롤링(22.05.23)
1. 전체 작업 설계
| 작업설계 | 사용할 코드 |
| --- | --- |
| 1. 데이터를 수집할 국가코드와 연도 입력하기 | national_code, nStartYear, nEndYear |
| 2. 데이터 수집 요청하기 | getTourismStatsService() |
| 2.1 url 구성하여 데이터 요청하기 | getTourismStatsItem() |
| 2.2 url 접속하고 요청하기 | getRequestUrl() |
| 2.3 응답 데이터를 리스트로 구성하기 | jsonResult, result |
| 3. 데이터를 JSON 파일과 CSV 파일로 저장하기 | json.dumps(), to_csv() |
2. 프로그램 구성 설계
def main()
1. 수집할 국가 코드와 연도 입력
2. 데이터 수집 요청
3. 파일 저장
3. 함수 설계
[main함수]
def main():
jsonResult=[]# 수집한 데이터를 저장할 리스트 객체로 json파일 저장용
result=[]
print("<<국내 입국한 외국인의 통계 데이터를 수집합니다. >>")
nat_cd=input("국가 코드를 입력하세여(중국: 112 / 일본: 130 / 미국: 275 ) : ")
nStartYear=int(input("데이터를 몇 년부터 수집할까요? : "))
nEndYear=int(input("데이터를 몇 년까지 수집할까요? : "))
ed_cd="E"#E: 방한 외래 관광객, D: 해외출국
jsonResult,result,natName,ed,dataEND=getTourismStatsService(nat_cd,ed_cd,nStartYear,nEndYear)
with open("./%s_%s_%d_%s.json" %(natName,ed,nStartYear,dataEND),'w',encoding='utf8') as outfile:
jsonFile=json.dumps(jsonResult,indent=4,sort_keys=True,ensure_ascii=False)
outfile.write(jsonFile)
columns=["입국자국가","국가코드","입국연월","입국자 수"]
result_df=pd.DatatFrame(result,columns=columns)
result_df.to_csv('./%s_%s_%d_%s.csv'%(natName,ed,nStartYear,dataEND),index=False,encoding='cp949')
[11행]
getTourismStatsService() 함수를 호출하여 반환받은 수집 데이터를 jsonResult, result, natName, dataEND에 저장
[14~16행]
수집 데이터를 딕셔너리의 리스트로 저장한 jsonResult를 json.dumps()를 통해 json 객체로 변환한 후 JSON 파일에 저장
[getRequestUrl 함수]
def getRequestUrl(url):
req=urllib.request.Request(url)
try:
response=urllib.request.urlopen(req)
if response.getcode()==200:
print("[%s] Url Request Success" % datetime.datetime.now())
return response.read().decode('utf-8')
except Exception as e:
print(e)
print("[%s] Error for URL: %s"%(datetime.datetime.now(),url))
return None
[02행]
url에 대한 요청을 보낼 객체 req를 생성
[04행]
요청 객체를 보내서 받은 응답 데이터를 response 객체에 저장
[05~07행]
- response 객체에 저장된 코드를 확인
- 코드가 200이면 요청을 정상 처리한 것이므로, 성공 메세지와 현재 시간을 파이썬 셸 창에 출력
- 응답을 utf-8 형식으로 디코딩하여 반환
[08~11행]
예외사항이 발생하면 에러 메세지를 파이썬 셸 창에 출력
[getTourismStatsItem 함수]
def getTourismStatsItem(yyyymm, national_code, ed_cd):
service_url = "http://openapi.tour.go.kr/openapi/service/EdrcntTourismStatsService/getEdrcntTourismStatsList"
parameters = "?_type=json&serviceKey=" + ServiceKey# 인증키
parameters += "&YM=" + yyyymm
parameters += "&NAT_CD=" + national_code
parameters += "&ED_CD=" + ed_cd
url = service_url + parameters# 완성 url
print(url)# 액세스 거부 여부 확인용 출력
responseDecode = getRequestUrl(url)# 반환받은 응답 객체if(responseDecode == None):
return None
else:return json.loads(responseDecode)
[10행]
구성한 url로 getRequestUrl() 함수를 호출해서 받은 응답을 responseDecode에 저장한다.
[15행]
서버에서 받은 json형태의 응답 객체를 파이썬 객체로 로드하여 반환하다.
[getTourismStatsService 함수]
def getTourismStatsService(nat_cd, ed_cd, nStartYear, nEndYear):
jsonResult = []
result = []# 수집한 데이터를 CSV저장용으로 구성할 리스트 객체
natName = ''# 수집한 국가 이름 데이터
dataEND = "{0}{1:0>2}".format(str(nEndYear), str(12))# 마지막 데이터의 연월
isDataEnd = 0# 데이터 끝 확인용 플래그for year in range(nStartYear, nEndYear+1):
for month in range(1, 13):
if(isDataEnd == 1): break
yyyymm = "{0}{1:0>2}".format(str(year), str(month))
jsonData = getTourismStatsItem(yyyymm, nat_cd, ed_cd)
if(jsonData['response']['header']['resultMsg'] == 'OK'):
if jsonData['response']['body']['items'] == '':
isDataEnd = 1
dataEND = "{0}{1:0>2}".format(str(year), str(month-1))
print("데이터 없음.... \n 제공되는 통계 데이터는 %s년 %s월까지입니다." %(str(year), str(month-1)))
break
print(json.dumps(jsonData, indent = 4, sort_keys = True, ensure_ascii = False))
natName = jsonData['response']['body']['items']['item']['natKorNm']
natName = natName.replace(' ', '')
num = jsonData['response']['body']['items']['item']['num']
ed = jsonData['response']['body']['items']['item']['ed']
print(' [%s_%s : %s ]' %(natName, yyyymm, num))
print('---------------------------------------------')
jsonResult.append({'nat_name':natName, 'nat_cd':nat_cd, 'yyyymm':yyyymm, 'visit_cnt':num})
result.append([natName, nat_cd, yyyymm, num])
return (jsonResult, result, natName, ed, dataEND)
[05행]
수집한 데이터의 끝 날짜인 dataEND를 nEndYear의 12월로 설정한다
[06행]
수집한 데이터의 끝인지 확인하기 위한 플래그인 isDataEnd를 0으로 설정한다.
[09행]
데이터의 끝 플래그인 isDataEnd를 확인하여 플래그가 설정되어 있으면 작업을 중단한다.
[10행]
수집할 연도와 월을 여섯 자리로 맞추어 yyyymm에 저장한다.
[11행]
getTourismStataItem()을 호출해 받은 월 데이터를 jsonData에 저장
[12행]
응답 데이터가 정상인지 확인
[13~17행]
['items'] 항목에 값이 없으면 출입국관광통계 데이터가 아직 안들어간것이므로, isDataEndfmf 1로 설정한다. 그리고 마짐가 데이터가 있는 날짜 month-1월을 dataEND에 저장하고 데이터 수집 종료
[18행]
수집한 월 데이터인 jsonData 내용을 확인할 수 있게 파이썬 셸 창에 출력
[27행]
수집하여 정리한 데이터를 반환한다.
[PublicDatacrawlingcode]*
import os
import sys
import urllib.request
import datetime
import time
import json
import pandas as pd
ServiceKey="###"
def getRequestUrl(url):
req = urllib.request.Request(url)
try:
response = urllib.request.urlopen(req)
if response.getcode() == 200:
print("[%s] Url Request Success" % datetime.datetime.now())
return response.read().decode('utf-8')
except Exception as e:
print(e)
print("[%s] Error for URL : %s" %(datetime.datetime.now(), url))
return None
def getTourismStatsItem(yyyymm, national_code, ed_cd):
service_url = "http://openapi.tour.go.kr/openapi/service/EdrcntTourismStatsService/getEdrcntTourismStatsList"
parameters = "?_type=json&serviceKey=" + ServiceKey # 인증키
parameters += "&YM=" + yyyymm
parameters += "&NAT_CD=" + national_code
parameters += "&ED_CD=" + ed_cd
url = service_url + parameters
print(url)# 액세스 거부 여부 확인용 출력
responseDecode = getRequestUrl(url)# [CODE 1]if(responseDecode == None):
return None
else:return json.loads(responseDecode)
def getTourismStatsService(nat_cd, ed_cd, nStartYear, nEndYear):
jsonResult = []
result = []
natName = ''
dataEND = "{0}{1:0>2}".format(str(nEndYear), str(12))
isDataEnd = 0
for year in range(nStartYear, nEndYear+1):
for month in range(1, 13):
if(isDataEnd == 1): break
yyyymm = "{0}{1:0>2}".format(str(year), str(month))
jsonData = getTourismStatsItem(yyyymm, nat_cd, ed_cd)#[CODE 2]if(jsonData['response']['header']['resultMsg'] == 'OK'):
if jsonData['response']['body']['items'] == '':
isDataEnd = 1
dataEND = "{0}{1:0>2}".format(str(year), str(month-1))
print("데이터 없음.... \n 제공되는 통계 데이터는 %s년 %s월까지입니다." %(str(year), str(month-1)))
break
print(json.dumps(jsonData, indent = 4, sort_keys = True, ensure_ascii = False))
natName = jsonData['response']['body']['items']['item']['natKorNm']
natName = natName.replace(' ', '')
num = jsonData['response']['body']['items']['item']['num']
ed = jsonData['response']['body']['items']['item']['ed']
print(' [%s_%s : %s ]' %(natName, yyyymm, num))
print('---------------------------------------------')
jsonResult.append({'nat_name':natName, 'nat_cd':nat_cd, 'yyyymm':yyyymm, 'visit_cnt':num})
result.append([natName, nat_cd, yyyymm, num])
return (jsonResult, result, natName, ed, dataEND)
#[CODE 0]def main():
jsonResult = []
result = []
print("<< 국내 입국한 외국인의 통계 데이터를 수집합니다. >>")
nat_cd = input('국가 코드를 입력하세요(중국: 112 / 일본: 130 / 미국: 275) : ')
nStartYear = int(input('데이터를 몇 년부터 수집할까요? : '))
nEndYear = int(input('데이터를 몇 년까지 수집할까요? : '))
ed_cd = "E"#E : 방한외래관광객, D : 해외 출국
jsonResult,result,natName,ed,dataEND = getTourismStatsService(nat_cd, ed_cd, nStartYear, nEndYear)
with open('./%s_%s_%d_%s.json' % (natName, ed, nStartYear, dataEND), 'w',
encoding='utf8') as outfile:
jsonFile = json.dumps(jsonResult, indent = 4, sort_keys = True, ensure_ascii = False)
outfile.write(jsonFile)
columns = ["입국자국가", "국가코드", "입국연월", "입국자 수"]
result_df = pd.DataFrame(result, columns = columns)
result_df.to_csv('./%s_%s_%d_%s.csv' % (natName, ed, nStartYear, dataEND),
index = False, encoding = 'cp949')
if __name__ == '__main__':
main()
코드를 실행하고 국가 코드를 112, 데이터 수집 시작연도를 2017, 마지막년도를 2021을 입력하면 셸창에 결과가 출력된다.
'데이터분석실습 > 데이터 과학 기반의 파이썬 빅데이터 분석' 카테고리의 다른 글
파이썬 빅데이터 분석 Day 5 (1) | 2023.10.26 |
---|---|
파이썬 빅데이터 분석 Day 4 (0) | 2023.10.26 |
파이썬 빅데이터 분석 Day 3 (0) | 2023.10.26 |
파이썬 빅데이터 분석 Day 1 (0) | 2023.10.26 |
파이썬 빅데이터 분석 Day 0 (0) | 2023.10.26 |