파이썬 크롤링 (API 이용)
크롤링
- 빅데이터 분석에 필요한 데이터를 외부(websites on the Internet)에서 수집하는 작업
- 웹 통신 방법
> 클라이언트-서버 구조
> HTTP 통신(REQUEST, RESPONSE)
웹 API
- 웹 서버 또는 웹 브라우저를 위한 애플리케이션 프로그래밍 인터페이스
> 데이터 CRUD 인터페이스(CRUD: Create, Read, Update, Delete)
> 지도, 검색, 주가, 환율 등 다양한 정보를 가지고 있는 웹 사이트의 기능을 외부에서 쉽게 사용할 수 있도록 사용 절차와 규약을 정의
네이버 API를 이용한 크롤링
1. 네이버 개발자 센터 접속
2. 오픈 API 이용 신청하기
3. 어플리케이션 등록하기
4. 어플리케이션 정보 확인하기
5. 이용 안내 페이지 확인하기
REST란?
- Representational State Transfer
- 애플리케이션 개발 architecture 중 하나
- 개념
> 웹 애플리케이션에 존재하는 모든 자원에 대해 고유 URI(Uniform Resource Identifier)를 부여
> HTTP Method(GET, POST, PUT, DELETE)를 이용해 리소스에 대해 CRUD 명령을 적용
> 응답은 JSON이나 XML 등의 형식으로 받음
project1. 네이버 뉴스 크롤링
1. 전체 작업 설계
1) 검색어 지정: srcText
2) 네이버 뉴스 검색하기: getNaverSearch()
2-1) url 구성: url=base+node+srcText
2-2) url 접속, 검색 요청하기: urllib.request.urlopen()
2-3) 요청 결과를 응답 json으로 받기: json.load()
3) 응답 데이터를 정리하여 리스트에 저장: getPostData()
4) 리스트를 json 파일로 저장: json.dumps()
2. 프로그램 구성 설계
3. 함수 설계
CODE 00: main()
#[CODE 00]
def main():
node = 'news' #크롤링할 대상 #네이버 뉴스 검색을 위해 검색 API 대상을 'news'로 설정
srcText = input('검색어를 입력하세요: ') #파이썬 셀 창에서 검색어를 입력받아 srcText에 저장
cnt = 0
jsonResult = []
jsonResponse = getNaverSearch(node, srcText, 1, 100) #[CODE 02]
#getNaverSearch() 함수를 호출하여 start=1, display=100에 대한 검색 결과를 반환받아 jsonResponse에 저장
total = jsonResponse['total']
#검색 결과(jsonResponse)에 데이터가 있는 동안 for문으로 검색 결과를 한 개씩 처리하는 작업(getPostData())을 반복
#반복 작업이 끝나면 다음 검색 결과 100개를 가져오기 위해 start 위치를 변경
while ((jsonResponse != None) and (jsonResponse['display'] != 0)):
for post in jsonResponse['items']:
cnt += 1
getPostData(post, jsonResult, cnt) #[CODE 03]
start = jsonResponse['start'] + jsonResponse['display']
jsonResponse = getNaverSearch(node, srcText, start, 100) #[CODE 02]
#getNaverSearch() 함수를 호출하여 새로운 검색 결과를 jsonResponse에 저장하고 for문을 다시 반복
print('전체 검색 : %d 건' %total)
#파일 객체를 생성하여 정리된 데이터를 JSON 파일에 저장
with open('%s_naver_%s.json' % (srcText, node), 'w', encoding='utf8') as outfile:
jsonFile = json.dumps(jsonResult, indent=4, sort_keys=True, ensure_ascii=False)
outfile.write(jsonFile)
print("가져온 데이터 : %d 건" %(cnt))
print('%s_naver_%s.json SAVED' % (srcText, node))
CODE 01: getRequestUrl(url)
- url 접속을 요청하고 응답을 받아서 반환하는 부분
#[CODE 01]
def getRequestUrl(url):
req = urllib.request.Request(url) #매개변수로 받은 url에 대한 요청을 보낼 객체를 생성
#API를 사용하기 위한 Client ID와 Client Secret 코드를 요청 객체 헤드에 추가
req.add_header("X-Naver-Client-Id", client_id)
req.add_header("X-Naver-Client-Secret", client_secret)
try:
response = urllib.request.urlopen(req) #요청 객체를 보내고 그에 대한 응답을 받아 response 객체에 저장
#getcode()로 response 객체에 저장된 코드를 확인
#200이면 요청이 정상처리된 것이므로 성공 메시지를 파이썬 셸 창에 출력하고 응답을 utf-8 형식으로 디코딩하여 반환
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
CODE 02: getNaverSearch(node, srcText, page_start, display)
- url을 만들고 [CODE 01]의 getRequestUrl(url)을 호출하여 반환받은 응답 데이터를 파이썬 json 형식으로 반환하는 부분
#[CODE 02]
def getNaverSearch(node, srcText, start, display):
#네이버 검색 API 정보에 따라 요청 URL을 구성
base = "https://openapi.naver.com/v1/search"
node = "/%s.json" % node
parameters = "?query=%s&start=%s&display=%s" % (urllib.parse.quote(srcText), start, display)
url = base + node + parameters
#완성한 url을 이용하여 getRequestUrl() 함수를 호출하여 받은 utf-8 디코드 응답을 responseDecode에 저장
responseDecode = getRequestUrl(url) #[CODE 1]
if (responseDecode == None):
return None
else:
return json.loads(responseDecode) #서버에서 받은 JSON 형태의 응답 객체를 파이썬 객체로 로드하여 반환
CODE 03: getPostData(post, jsonResult, cnt)
- JSON 형식의 응답 데이터를 필요한 항목만 정리하여 딕셔너리 리스트인 jsonReesult를 반환
#[CODE 03]
def getPostData(post, jsonResult, cnt):
#검색 결과가 들어 있는 post 객체에서 필요한 데이터 항목을 추출하여 변수에 저장
title = post['title']
description = post['description']
org_link = post['originallink']
link = post['link']
#formating
#네이버에서 제공하는 시간인 pubDate는 문자열 형태이므로 날짜 객체로 변환
#pubDate는 그리니치 평균시 형식을 사용하는데 한국 표준시보다 9시간 느리므로 +0900을 사용해 한국 표준시로 맞춤
pDate = datetime.datetime.strptime(post['pubDate'], '%a, %d %b %Y %H:%M:%S +0900')
pDate = pDate.strftime('%Y-%m-%d %H:%M:%S') #수정된 날짜를 '연-월-일 시:분:초' 형식으로 나타냄
#저장한 데이터를 딕셔너리 형태인 {'키':값}으로 구성하여 리스트 객체인 jsonResult에 추가
jsonResult.append({'cnt':cnt, 'title':title, 'description':description, 'org_link':org_link, 'link':org_link, 'pDate':pDate})
return
4. 전체 코드
import os
import sys
import urllib.request
import datetime
import time
import json
client_id = "Pn5aM5DQcC9IKjSayftW"
client_secret = "0DXRO2f6T3"
#[CODE 01]
def getRequestUrl(url):
req = urllib.request.Request(url) #매개변수로 받은 url에 대한 요청을 보낼 객체를 생성
#API를 사용하기 위한 Client ID와 Client Secret 코드를 요청 객체 헤드에 추가
req.add_header("X-Naver-Client-Id", client_id)
req.add_header("X-Naver-Client-Secret", client_secret)
try:
response = urllib.request.urlopen(req) #요청 객체를 보내고 그에 대한 응답을 받아 response 객체에 저장
#getcode()로 response 객체에 저장된 코드를 확인
#200이면 요청이 정상처리된 것이므로 성공 메시지를 파이썬 셸 창에 출력하고 응답을 utf-8 형식으로 디코딩하여 반환
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
#[CODE 02]
def getNaverSearch(node, srcText, start, display):
#네이버 검색 API 정보에 따라 요청 URL을 구성
base = "https://openapi.naver.com/v1/search"
node = "/%s.json" % node
parameters = "?query=%s&start=%s&display=%s" % (urllib.parse.quote(srcText), start, display)
url = base + node + parameters
#완성한 url을 이용하여 getRequestUrl() 함수를 호출하여 받은 utf-8 디코드 응답을 responseDecode에 저장
responseDecode = getRequestUrl(url) #[CODE 1]
if (responseDecode == None):
return None
else:
return json.loads(responseDecode) #서버에서 받은 JSON 형태의 응답 객체를 파이썬 객체로 로드하여 반환
#[CODE 03]
def getPostData(post, jsonResult, cnt):
#검색 결과가 들어 있는 post 객체에서 필요한 데이터 항목을 추출하여 변수에 저장
title = post['title']
description = post['description']
org_link = post['originallink']
link = post['link']
#formating
#네이버에서 제공하는 시간인 pubDate는 문자열 형태이므로 날짜 객체로 변환
#pubDate는 그리니치 평균시 형식을 사용하는데 한국 표준시보다 9시간 느리므로 +0900을 사용해 한국 표준시로 맞춤
pDate = datetime.datetime.strptime(post['pubDate'], '%a, %d %b %Y %H:%M:%S +0900')
pDate = pDate.strftime('%Y-%m-%d %H:%M:%S') #수정된 날짜를 '연-월-일 시:분:초' 형식으로 나타냄
#저장한 데이터를 딕셔너리 형태인 {'키':값}으로 구성하여 리스트 객체인 jsonResult에 추가
jsonResult.append({'cnt':cnt, 'title':title, 'description':description, 'org_link':org_link, 'link':org_link, 'pDate':pDate})
return
#[CODE 00]
def main():
node = 'news' #크롤링할 대상 #네이버 뉴스 검색을 위해 검색 API 대상을 'news'로 설정
srcText = input('검색어를 입력하세요: ') #파이썬 셀 창에서 검색어를 입력받아 srcText에 저장
cnt = 0
jsonResult = []
jsonResponse = getNaverSearch(node, srcText, 1, 100) #[CODE 02]
#getNaverSearch() 함수를 호출하여 start=1, display=100에 대한 검색 결과를 반환받아 jsonResponse에 저장
total = jsonResponse['total']
#검색 결과(jsonResponse)에 데이터가 있는 동안 for문으로 검색 결과를 한 개씩 처리하는 작업(getPostData())을 반복
#반복 작업이 끝나면 다음 검색 결과 100개를 가져오기 위해 start 위치를 변경
while ((jsonResponse != None) and (jsonResponse['display'] != 0)):
for post in jsonResponse['items']:
cnt += 1
getPostData(post, jsonResult, cnt) #[CODE 03]
start = jsonResponse['start'] + jsonResponse['display']
jsonResponse = getNaverSearch(node, srcText, start, 100) #[CODE 02]
#getNaverSearch() 함수를 호출하여 새로운 검색 결과를 jsonResponse에 저장하고 for문을 다시 반복
print('전체 검색 : %d 건' %total)
#파일 객체를 생성하여 정리된 데이터를 JSON 파일에 저장
with open('%s_naver_%s.json' % (srcText, node), 'w', encoding='utf8') as outfile:
jsonFile = json.dumps(jsonResult, indent=4, sort_keys=True, ensure_ascii=False)
outfile.write(jsonFile)
print("가져온 데이터 : %d 건" %(cnt))
print('%s_naver_%s.json SAVED' % (srcText, node))
# 메인 함수의 선언, 시작을 의미
if __name__ == '__main__':
main()
공공데이터 API를 이용한 크롤링
- 정부 3.0의 핵심 정책: 공공데이터 정책 추진
> 공공기관에서 보유한 공공데이터를 국민과 공유하며 소통과 협력을 확대하기 위함
> 2013년 7월 공공데이터법 제정, 10월부터 시행
1. 공공데이터포털 접속하기
2. 회원가입 및 로그인
3. '출입국관광통계서비스' 검색
4. 오픈 API 탭 -> 출입국관광통계서비스
5. 활용신청 클릭
6. 오픈 API 계발계정 발급
7. 오픈 API 사용 방법 확인
project2. '출입국관광통계서비스' 입국 외국인 수 크롤링
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. 프로그램 구성 설계
3. 함수 설계
CODE 00: main()
#[CODE 0]
def main():
jsonResult1 = []
result1 = []
natname1 = ''
jsonResult2 = []
result2 = []
natname2 = ''
print("<< 국내 입국한 외국인의 통계 데이터 수집 >>")
#데이터를 수집할 국가 코드를 입력
nat_cd1 = input("첫번째 국가 코드를 입력하세요(중국: 112 / 일본: 130 / 미국: 275) : ")
nat_cd2 = input("두번째 국가 코드를 입력하세요(중국: 112 / 일본: 130 / 미국: 275) : ")
#데이터를 수집할 시작 연도를 입력
nStartYear = int(input('데이터를 몇 년부터 수집할까요? : '))
#데이터를 수집할 마지막 연도를 입력
nEndYear = int(input('데이터를 몇 년까지 수집할까요? : '))
ed_cd = "E" # E: 방한외래관광객, D: 해외 출국
#getTourismStatsService() 함수를 호출하여 반환받은 수집 데이터를 jsonResult, result, natName, dataEND에 저장
jsonResult1, result1, natName1, ed, dataEND = getTourismStatsService(nat_cd1, ed_cd, nStartYear, nEndYear) #[CODE3]
jsonResult2, result2, natName2, ed, dataEND = getTourismStatsService(nat_cd2, ed_cd, nStartYear, nEndYear) #[CODE3]
#데이터 받아오는지 추가
if(natName1==''):
print("데이터가 전달되지 않았습니다. 공공데이터포털의 서비스 상태를 확인하기 바랍니다.")
#파일 저장1 : json 파일
#수집 데이터를 딕셔너리의 리스트로 저장한 jsonResult를 json.dumps()를 통해 json 객체로 변환한 후 JSON 파일에 저장
with open('./%s_%s_%d_%s.json' % (natName1, ed, nStartYear, dataEND), 'w', encoding='utf8') as outfile:
jsonFile = json.dumps(jsonResult1, indent=4, sort_keys=True, ensure_ascii=False)
outfile.write(jsonFile)
with open('./%s_%s_%d_%s.json' % (natName2, ed, nStartYear, dataEND), 'w', encoding='utf8') as outfile:
jsonFile = json.dumps(jsonResult2, indent=4, sort_keys=True, ensure_ascii=False)
outfile.write(jsonFile)
#파일 저장2 : csv 파일
#데이터프레임에 만들 컬럼명을 리스트로 만듦
columns = ["입국자국가", "국가코드", "입국연월", "입국자 수"]
#수집 데이터를 리스트로 저장한 result를 데이터프레임으로 변환
result_df1 = pd.DataFrame(result1, columns=columns)
#데이터프레임 객체인 result_df를 CSV 파일로 저장
result_df1.to_csv('./%s_%s_%d_%s.csv' %(natName1, ed, nStartYear, dataEND), index=False, encoding='cp949')
result_df2 = pd.DataFrame(result2, columns=columns)
result_df2.to_csv('./%s_%s_%d_%s.csv' %(natName2, ed, nStartYear, dataEND), index=False, encoding='cp949')
# #꺽은선 그래프 그리기
# x_label = []
# for i in range(len(result)):
# x_label.append(result[i][2])
#
# y_label = []
# for i in range(len(result)):
# y_label.append(result[i][3])
#
# plt.plot(x_label, y_label)
# plt.show()
yyyymmList = result_df1["입국연월"].values.tolist()
visitNumList1 = result_df1["입국자 수"].values.tolist()
visitNumList2 = result_df2["입국자 수"].values.tolist()
xlabel = numpy.arange(len(yyyymmList))
plt.bar(xlabel, visitNumList1, label=natName1, color='r', width=0.2)
plt.bar(xlabel+0.2, visitNumList2, label=natName2, color='b', width=0.2)
plt.xticks(xlabel, yyyymmList)
plt.legend(loc="upper right")
plt.title("{0}~{1} 입국자 수".format(str(yyyymmList[0]),str(yyyymmList[-1])))
plt.xlabel("입국연월")
plt.ylabel("입국자 수")
plt.show()
CODE 01: getRequestUrl(url)
- url 접속을 요청하고 응답을 받아서 반환하는 부분
#[CODE 1]
def getRequestUrl(url):
#매개변수로 받은 url에 대한 요청을 보낼 객체를 생성
req = urllib.request.Request(url)
try:
response = urllib.request.urlopen(req) # 요청 객체를 보내서 받은 응답 데이터를 response 객체에 저장
#response 객체에 저장된 코드를 확인
#코드가 200이면 요청을 정상 처리한 것이므로 성공
#메시지와 현재 시간을 파이썬 셸 창에 출력하고 응답을 utf-8 형식으로 디코딩하여 반환
if response.getcode() == 200: # 코드가 200이면 요청을 정상 처리
print("[%s] Url Request Success" % datetime.datetime.now())
return response.read().decode('utf-8') # 메시지와 현재 시간을 파이썬 셀 창에 출력하고 응답을 utf-8 형식으로 디코딩하여 반환
#요청이 처리되지 않은 예외 사황이 발생하면 에러 메시지를 파이썬 셸 창에 출력
except Exception as e:
print(e)
print("[%s] Error for URL : %s" % (datetime.datetime.now(), url))
return None
CODE 02: getTourismStatsItem(yyyymm, nat_cd, ed_cd)
- 출입국관광통계서비스의 오픈 API를 사용하여 데이터 요청 url을 만들고 [CODE 01]의 getRequestUrl(url)을 호출해서 받은 응답 데이터를 반환
#[CODE 2]
def getTourismStatsItem(yyyymm, national_code, ed_cd):
#출입국관광통계서비스의 오픈 API 상세정보 페이지에서 찾은 서비스 URL, 요청매개변수 정보, 발급받은 인증키를 사용하여 데이터 요청 URL을 구성
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) #액세스 거부 여부 확인용 출력
#구성한 url로 getRequestUrl() 함수를 호출해서 받은 응답(utf-8로 디코드됨)을 responseDecode에 저장
responseDecode = getRequestUrl(url) #[CODE1]
if (responseDecode == None):
# print("responseDecode is None")
return None
else:
# print("responseDecode is OK")
#서버에서 받은 JSON 형태의 응답 객체를 파이썬 객체로 로드하여 반환
return json.loads(responseDecode)
CODE 03: getTourismStatsService(nat_cd, ed_cd, nStartYear, nEndYear)
- 수집 기간 동안 월 단위로 [CODE 02]의 getTourismStatsItem()을 호출해 받은 데이터를 리스트로 묶어 반환
#[CODE 3]
def getTourismStatsService(nat_cd, ed_cd, nStartYear, nEndYear):
jsonResult = []
result = []
natName = ''
dataEND = "{0}{1:0>2}".format(str(nEndYear), str(12)) #데이터 끝 초기화
isDataEnd = 0 #데이터 끝 확인용 flag 초기화
ed = ''
for year in range(nStartYear, nEndYear+1):
for month in range(1, 13):
if(isDataEnd == 1): break #데이터 끝 flag 설정되어있으면 작업 중지
#수집할 연도와 월을 여섯 자리로 맞추어 yyyymm에 저장
yyyymm = "{0}{1:0>2}".format(str(year), str(month))
#getTourismStatsItem()을 호출해 받은 월 데이터를 jsonData에 저장
jsonData = getTourismStatsItem(yyyymm, nat_cd, ed_cd) #[CODE 2]
#응답 데이터가 정상인지 확인
if (jsonData['response']['header']['resultMsg'] == 'OK'):
#데이터가 없는 마지막 항목일 경우 --
#['items'] 항목에 값이 없으면 출입국관광통계 데이터가 아직 들어가지 않은 마지막 월이므로 날짜를 dataEND에 저장하고 데이터 수집 작업을 중단
if jsonData['response']['body']['items'] == '':
isDataEnd = 1 #데이터 끝 flag 설정
dataEND = "{0}{1:0>2}".format(str(year),str(month-1))
print("데이터 없음.... \n 제공되는 통계 데이터는 %s년 %s월까지 입니다." %(str(year), str(month-1)))
break
#jsonData를 출력하여 획인 --
#수집한 월 데이터인 jsonData 내용을 확인할 수 있게 파이썬 셸 창에 출력
print(json.dumps(jsonData, indent=4, sort_keys=True, ensure_ascii=False))
#수집한 국가 이름인 ['natKorNm'] 항목의 값에서 띄어쓰기를 제거하고 natNama에 저장
natName = jsonData['response']['body']['items']['item']['natKorNm']
natName = natName.replace(' ','')
#수집한 월의 데이터 수인 ['num'] 항목의 값을 num에 저장
num = jsonData['response']['body']['items']['item']['num']
#수집한 출입국 구분 데이터인 ['ed'] 항목의 값을 ed에 저
ed = jsonData['response']['body']['items']['item']['ed']
print(' [%s_%s : %s]' %(natName, yyyymm, num))
print('------------------------------')
#수집한 국가 이름(natName), 국가 코드(nat_cd), 날짜(yyyymm), 데이터 수(num)를 딕셔너리 자료형으로 구성하여 jsonResult 리스트에 원소로 추가
jsonResult.append({'nat_name': natName, 'nat_cd장: nat_cd, 'yyyymm': yyyymm, 'visit_cnt': num})
#수집한 국가 이름(natName), 국가 코드(nat_cd), 날짜(yyyymm), 데이터 수(num)를 result 리스트에 원소로 추가
result.append([natName, nat_cd, yyyymm, num])
# else:
# print("non-OK")
#수집하여 정리한 데이터를 반환
return (jsonResult, result, natName, ed, dataEND)
4. 전체 코드
import os
import sys
import urllib.request
import datetime
import time
import json
import pandas as pd
from matplotlib import pyplot as plt
import numpy
from matplotlib import rc
rc('font', family='AppleGothic')
plt.rcParams['axes.unicode_minus'] = False
ServiceKey = '발급받은 서비스 키 값 입력'
#[CODE 1]
def getRequestUrl(url):
#매개변수로 받은 url에 대한 요청을 보낼 객체를 생성
req = urllib.request.Request(url)
try:
response = urllib.request.urlopen(req) # 요청 객체를 보내서 받은 응답 데이터를 response 객체에 저장
#response 객체에 저장된 코드를 확인
#코드가 200이면 요청을 정상 처리한 것이므로 성공
#메시지와 현재 시간을 파이썬 셸 창에 출력하고 응답을 utf-8 형식으로 디코딩하여 반환
if response.getcode() == 200: # 코드가 200이면 요청을 정상 처리
print("[%s] Url Request Success" % datetime.datetime.now())
return response.read().decode('utf-8') # 메시지와 현재 시간을 파이썬 셀 창에 출력하고 응답을 utf-8 형식으로 디코딩하여 반환
#요청이 처리되지 않은 예외 사황이 발생하면 에러 메시지를 파이썬 셸 창에 출력
except Exception as e:
print(e)
print("[%s] Error for URL : %s" % (datetime.datetime.now(), url))
return None
#[CODE 2]
def getTourismStatsItem(yyyymm, national_code, ed_cd):
#출입국관광통계서비스의 오픈 API 상세정보 페이지에서 찾은 서비스 URL, 요청매개변수 정보, 발급받은 인증키를 사용하여 데이터 요청 URL을 구성
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) #액세스 거부 여부 확인용 출력
#구성한 url로 getRequestUrl() 함수를 호출해서 받은 응답(utf-8로 디코드됨)을 responseDecode에 저장
responseDecode = getRequestUrl(url) #[CODE1]
if (responseDecode == None):
# print("responseDecode is None")
return None
else:
# print("responseDecode is OK")
#서버에서 받은 JSON 형태의 응답 객체를 파이썬 객체로 로드하여 반환
return json.loads(responseDecode)
#[CODE 3]
def getTourismStatsService(nat_cd, ed_cd, nStartYear, nEndYear):
jsonResult = []
result = []
natName = ''
dataEND = "{0}{1:0>2}".format(str(nEndYear), str(12)) #데이터 끝 초기화
isDataEnd = 0 #데이터 끝 확인용 flag 초기화
ed = ''
for year in range(nStartYear, nEndYear+1):
for month in range(1, 13):
if(isDataEnd == 1): break #데이터 끝 flag 설정되어있으면 작업 중지
#수집할 연도와 월을 여섯 자리로 맞추어 yyyymm에 저장
yyyymm = "{0}{1:0>2}".format(str(year), str(month))
#getTourismStatsItem()을 호출해 받은 월 데이터를 jsonData에 저장
jsonData = getTourismStatsItem(yyyymm, nat_cd, ed_cd) #[CODE 2]
#응답 데이터가 정상인지 확인
if (jsonData['response']['header']['resultMsg'] == 'OK'):
#데이터가 없는 마지막 항목일 경우 --
#['items'] 항목에 값이 없으면 출입국관광통계 데이터가 아직 들어가지 않은 마지막 월이므로 날짜를 dataEND에 저장하고 데이터 수집 작업을 중단
if jsonData['response']['body']['items'] == '':
isDataEnd = 1 #데이터 끝 flag 설정
dataEND = "{0}{1:0>2}".format(str(year),str(month-1))
print("데이터 없음.... \n 제공되는 통계 데이터는 %s년 %s월까지 입니다." %(str(year), str(month-1)))
break
#jsonData를 출력하여 획인 --
#수집한 월 데이터인 jsonData 내용을 확인할 수 있게 파이썬 셸 창에 출력
print(json.dumps(jsonData, indent=4, sort_keys=True, ensure_ascii=False))
#수집한 국가 이름인 ['natKorNm'] 항목의 값에서 띄어쓰기를 제거하고 natNama에 저장
natName = jsonData['response']['body']['items']['item']['natKorNm']
natName = natName.replace(' ','')
#수집한 월의 데이터 수인 ['num'] 항목의 값을 num에 저장
num = jsonData['response']['body']['items']['item']['num']
#수집한 출입국 구분 데이터인 ['ed'] 항목의 값을 ed에 저
ed = jsonData['response']['body']['items']['item']['ed']
print(' [%s_%s : %s]' %(natName, yyyymm, num))
print('------------------------------')
#수집한 국가 이름(natName), 국가 코드(nat_cd), 날짜(yyyymm), 데이터 수(num)를 딕셔너리 자료형으로 구성하여 jsonResult 리스트에 원소로 추가
jsonResult.append({'nat_name': natName, 'nat_cd장: nat_cd, 'yyyymm': yyyymm, 'visit_cnt': num})
#수집한 국가 이름(natName), 국가 코드(nat_cd), 날짜(yyyymm), 데이터 수(num)를 result 리스트에 원소로 추가
result.append([natName, nat_cd, yyyymm, num])
# else:
# print("non-OK")
#수집하여 정리한 데이터를 반환
return (jsonResult, result, natName, ed, dataEND)
#[CODE 0]
def main():
jsonResult1 = []
result1 = []
natname1 = ''
jsonResult2 = []
result2 = []
natname2 = ''
print("<< 국내 입국한 외국인의 통계 데이터 수집 >>")
#데이터를 수집할 국가 코드를 입력
nat_cd1 = input("첫번째 국가 코드를 입력하세요(중국: 112 / 일본: 130 / 미국: 275) : ")
nat_cd2 = input("두번째 국가 코드를 입력하세요(중국: 112 / 일본: 130 / 미국: 275) : ")
#데이터를 수집할 시작 연도를 입력
nStartYear = int(input('데이터를 몇 년부터 수집할까요? : '))
#데이터를 수집할 마지막 연도를 입력
nEndYear = int(input('데이터를 몇 년까지 수집할까요? : '))
ed_cd = "E" # E: 방한외래관광객, D: 해외 출국
#getTourismStatsService() 함수를 호출하여 반환받은 수집 데이터를 jsonResult, result, natName, dataEND에 저장
jsonResult1, result1, natName1, ed, dataEND = getTourismStatsService(nat_cd1, ed_cd, nStartYear, nEndYear) #[CODE3]
jsonResult2, result2, natName2, ed, dataEND = getTourismStatsService(nat_cd2, ed_cd, nStartYear, nEndYear) #[CODE3]
#데이터 받아오는지 추가
if(natName1==''):
print("데이터가 전달되지 않았습니다. 공공데이터포털의 서비스 상태를 확인하기 바랍니다.")
#파일 저장1 : json 파일
#수집 데이터를 딕셔너리의 리스트로 저장한 jsonResult를 json.dumps()를 통해 json 객체로 변환한 후 JSON 파일에 저장
with open('./%s_%s_%d_%s.json' % (natName1, ed, nStartYear, dataEND), 'w', encoding='utf8') as outfile:
jsonFile = json.dumps(jsonResult1, indent=4, sort_keys=True, ensure_ascii=False)
outfile.write(jsonFile)
with open('./%s_%s_%d_%s.json' % (natName2, ed, nStartYear, dataEND), 'w', encoding='utf8') as outfile:
jsonFile = json.dumps(jsonResult2, indent=4, sort_keys=True, ensure_ascii=False)
outfile.write(jsonFile)
#파일 저장2 : csv 파일
#데이터프레임에 만들 컬럼명을 리스트로 만듦
columns = ["입국자국가", "국가코드", "입국연월", "입국자 수"]
#수집 데이터를 리스트로 저장한 result를 데이터프레임으로 변환
result_df1 = pd.DataFrame(result1, columns=columns)
#데이터프레임 객체인 result_df를 CSV 파일로 저장
result_df1.to_csv('./%s_%s_%d_%s.csv' %(natName1, ed, nStartYear, dataEND), index=False, encoding='cp949')
result_df2 = pd.DataFrame(result2, columns=columns)
result_df2.to_csv('./%s_%s_%d_%s.csv' %(natName2, ed, nStartYear, dataEND), index=False, encoding='cp949')
# #꺽은선 그래프 그리기
# x_label = []
# for i in range(len(result)):
# x_label.append(result[i][2])
#
# y_label = []
# for i in range(len(result)):
# y_label.append(result[i][3])
#
# plt.plot(x_label, y_label)
# plt.show()
yyyymmList = result_df1["입국연월"].values.tolist()
visitNumList1 = result_df1["입국자 수"].values.tolist()
visitNumList2 = result_df2["입국자 수"].values.tolist()
xlabel = numpy.arange(len(yyyymmList))
plt.bar(xlabel, visitNumList1, label=natName1, color='r', width=0.2)
plt.bar(xlabel+0.2, visitNumList2, label=natName2, color='b', width=0.2)
plt.xticks(xlabel, yyyymmList)
plt.legend(loc="upper right")
plt.title("{0}~{1} 입국자 수".format(str(yyyymmList[0]),str(yyyymmList[-1])))
plt.xlabel("입국연월")
plt.ylabel("입국자 수")
plt.show()
if __name__=='__main__':
main()
FIN.
[빅데이터 분석] 07. 텍스트 빈도 분석 (0) | 2023.07.25 |
---|---|
[빅데이터 분석] 06. 통계 분석II (0) | 2023.07.25 |
[빅데이터 분석] 05. 통계 분석 (0) | 2023.07.24 |
[빅데이터 분석] 03 - 04. 웹 페이지 크롤링 (0) | 2023.07.19 |
[빅데이터 분석] 00. 4차 산업혁명 기술과 데이터 과학 기반의 빅데이터 분석 (0) | 2023.05.03 |
댓글 영역