Pandas - 영화 진흥원 API 상영 순위 분석
1. Site
http://www.kobis.or.kr/kobisopenapi/homepg/main/main.do
2. API 발급
3. Code
import datetime as dt
import requests
import json
import pandas
from pandas import DataFrame
from matplotlib import pyplot
from print_df import print_df
kobis_api_key = "API"
kobis_api_url = "http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=%s&targetDt=%s"
today = dt.datetime.now()
delta = dt.timedelta(days=-1)
yesterday = today + delta
yesterday_str = yesterday.strftime("%Y%m%d")
api_url = kobis_api_url % (kobis_api_key, yesterday_str)
print_df(api_url)
r = requests.get(api_url)
if r.status_code != 200:
print("[%d Error] %s" % (r.status_code, r.reason))
quit()
r.encoding = "utf-8"
result = json.loads(r.text)
df = DataFrame(result['boxOfficeResult']['dailyBoxOfficeList'])
df = df.filter(items=['movieNm', 'audiCnt'])
movie_list = list(df['movieNm'])
index_dict = {}
for i, v in enumerate(movie_list):
index_dict[i] = v
df.rename(index=index_dict, columns={'audiCnt': '관람객수'}, inplace=True)
df.drop('movieNm', axis=1, inplace=True)
df['관람객수'] = df['관람객수'].apply(pandas.to_numeric)
df.sort_values('관람객수', inplace=True, ascending=True)
df = df.dropna()
empty_sum = df.isnull().sum()
pyplot.rcParams["font.family"] = 'NanumGothic'
pyplot.rcParams["font.size"] = 14
pyplot.rcParams["figure.figsize"] = (16, 8)
df.plot.barh()
pyplot.grid()
pyplot.title("%s 박스오피스 순위" % yesterday_str)
pyplot.legend()
pyplot.savefig('boxoffice_daily.png', dpi=200)
pyplot.show()
pyplot.close()
4. Code 풀이
- Import Module
import datetime as dt
import requests
import json
import pandas
from pandas import DataFrame
from matplotlib import pyplot
from print_df import print_df
- 영화 진흥원 API
kobis_api_key = "API"
- request 주소
kobis_api_url = "http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=%s&targetDt=%s"
- 인터페이스 / 응답구조 확인
- 요청 인터페이스
- 응답 구조
- 연동 사전 작업 - 하루 전 날짜값 생성
today = dt.datetime.now()
delta = dt.timedelta(days=-1)
yesterday = today + delta
yesterday_str = yesterday.strftime("%Y%m%d")
- API와 날짜로 접속할 URL 생성
api_url = kobis_api_url % (kobis_api_key, yesterday_str)
print_df(api_url)
- URL에 접속해 결과 생성
r = requests.get(api_url)
- 가져온 데이터를 딕셔너리 형태로 변환
r.encoding = "utf-8"
result = json.loads(r.text)
{'boxOfficeResult': {'boxofficeType': '일별 박스오피스', 'showRange': '20190601~20190601', 'dailyBoxOfficeList': [{'rnum': '1', 'rank': '1', 'rankInten': '0', 'rankOldAndNew': 'OLD', 'movieCd': '20183782', 'movieNm': '기생충', 'openDt': '2019-05-30', 'salesAmt': '9907985973', 'salesShare': '68.8', 'salesInten': '4014544998', 'salesChange': '68.1', 'salesAcc': '20479182448', 'audiCnt': '1126561', 'audiInten': '458769', 'audiChange': '68.7', 'audiAcc': '2372310', 'scrnCnt': '1926', 'showCnt': '9902'}, {'rnum': '2', 'rank': '2', 'rankInten': '0', 'rankOldAndNew': 'OLD', 'movieCd': '20183867', 'movieNm': '알라딘', 'openDt': '2019-05-23', 'salesAmt': '2610974127', 'salesShare': '18.1', 'salesInten': '1526830402', 'salesChange': '140.8', 'salesAcc': '15416106172', 'audiCnt': '306058', 'audiInten': '182790', 'audiChange': '148.3', 'audiAcc': '1842303', 'scrnCnt': '965', 'showCnt': '3451'}, {'rnum': '3', 'rank': '3', 'rankInten': '1', 'rankOldAndNew': 'OLD', 'movieCd': '20184865', 'movieNm': '고질라: 킹 오브 몬스터', 'openDt': '2019-05-29', 'salesAmt': '738268373', 'salesShare': '5.1', 'salesInten': '377834088', 'salesChange': '104.8', 'salesAcc': '1994088788', 'audiCnt': '78282', 'audiInten': '40563', 'audiChange': '107.5', 'audiAcc': '236118', 'scrnCnt': '610', 'showCnt': '1615'}, {'rnum': '4', 'rank': '4', 'rankInten': '-1', 'rankOldAndNew': 'OLD', 'movieCd': '20188941', 'movieNm': '악인전', 'openDt': '2019-05-15', 'salesAmt': '567294200', 'salesShare': '3.9', 'salesInten': '158201730', 'salesChange': '38.7', 'salesAcc': '27995218090', 'audiCnt': '62886', 'audiInten': '16299', 'audiChange': '35', 'audiAcc': '3230927', 'scrnCnt': '569', 'showCnt': '1628'}, {'rnum': '5', 'rank': '5', 'rankInten': '0', 'rankOldAndNew': 'OLD', 'movieCd': '20188144', 'movieNm': '0.0MHz', 'openDt': '2019-05-29', 'salesAmt': '220796140', 'salesShare': '1.5', 'salesInten': '87998700', 'salesChange': '66.3', 'salesAcc': '658800680', 'audiCnt': '25945', 'audiInten': '11024', 'audiChange': '73.9', 'audiAcc': '85289', 'scrnCnt': '409', 'showCnt': '673'}, {'rnum': '6', 'rank': '6', 'rankInten': '0', 'rankOldAndNew': 'OLD', 'movieCd': '20184889', 'movieNm': '어벤져스: 엔드게임', 'openDt': '2019-04-24', 'salesAmt': '114133860', 'salesShare': '0.8', 'salesInten': '41070580', 'salesChange': '56.2', 'salesAcc': '121245236720', 'audiCnt': '13071', 'audiInten': '4875', 'audiChange': '59.5', 'audiAcc': '13832015', 'scrnCnt': '158', 'showCnt': '207'}, {'rnum': '7', 'rank': '7', 'rankInten': '12', 'rankOldAndNew': 'OLD', 'movieCd': '20192001', 'movieNm': '피터팬: 후크 선장과 결투의 날', 'openDt': '2019-05-30', 'salesAmt': '33691000', 'salesShare': '0.2', 'salesInten': '30547000', 'salesChange': '971.6', 'salesAcc': '39119000', 'audiCnt': '4394', 'audiInten': '4002', 'audiChange': '1020.9', 'audiAcc': '5094', 'scrnCnt': '129', 'showCnt': '157'}, {'rnum': '8', 'rank': '8', 'rankInten': '-1', 'rankOldAndNew': 'OLD', 'movieCd': '20184082', 'movieNm': '걸캅스', 'openDt': '2019-05-09', 'salesAmt': '36020220', 'salesShare': '0.3', 'salesInten': '4075210', 'salesChange': '12.8', 'salesAcc': '13711831634', 'audiCnt': '4258', 'audiInten': '413', 'audiChange': '10.7', 'audiAcc': '1614861', 'scrnCnt': '164', 'showCnt': '215'}, {'rnum': '9', 'rank': '9', 'rankInten': '0', 'rankOldAndNew': 'OLD', 'movieCd': '20199448', 'movieNm': '어린 의뢰인', 'openDt': '2019-05-22', 'salesAmt': '22468160', 'salesShare': '0.2', 'salesInten': '9399450', 'salesChange': '71.9', 'salesAcc': '1583056500', 'audiCnt': '2725', 'audiInten': '1055', 'audiChange': '63.2', 'audiAcc': '191510', 'scrnCnt': '144', 'showCnt': '189'}, {'rnum': '10', 'rank': '10', 'rankInten': '-2', 'rankOldAndNew': 'OLD', 'movieCd': '20198597', 'movieNm': '교회오빠', 'openDt': '2019-05-16', 'salesAmt': '20487930', 'salesShare': '0.1', 'salesInten': '6179030', 'salesChange': '43.2', 'salesAcc': '512607320', 'audiCnt': '2372', 'audiInten': '669', 'audiChange': '39.3', 'audiAcc': '61958', 'scrnCnt': '65', 'showCnt': '86'}]}}
df = DataFrame(result['boxOfficeResult']['dailyBoxOfficeList'])
- 영화 제목 / 관람객 수 필터링 작업
df = df.filter(items=['movieNm', 'audiCnt'])
+---+------------------------+---------+
| | movieNm | audiCnt |
+---+------------------------+---------+
| 0 | 기생충 | 1126561 |
| 1 | 알라딘 | 306058 |
| 2 | 고질라: 킹 오브 몬스터 | 78282 |
| 3 | 악인전 | 62886 |
| 4 | 0.0MHz | 25945 |
+---+------------------------+---------+
- 영화 이름 리스트 작업
movie_list = list(df['movieNm'])
index_dict = {}
for i, v in enumerate(movie_list):
index_dict[i] = v
- 컬럼이름 변경
df.rename(index=index_dict, columns={'audiCnt': '관람객수'}, inplace=True)
- 필요없는 열 삭제 후 결과 확인
df.drop('movieNm', axis=1, inplace=True)
+------------------------+----------+
| | 관람객수 |
+------------------------+----------+
| 기생충 | 1126561 |
| 알라딘 | 306058 |
| 고질라: 킹 오브 몬스터 | 78282 |
| 악인전 | 62886 |
| 0.0MHz | 25945 |
+------------------------+----------+
- 관람객 수 확인
print(df['관람객수'])
기생충 1126561
알라딘 306058
고질라: 킹 오브 몬스터 78282
악인전 62886
0.0MHz 25945
어벤져스: 엔드게임 13071
피터팬: 후크 선장과 결투의 날 4394
걸캅스 4258
어린 의뢰인 2725
교회오빠 2372
Name: 관람객수, dtype: object
- 관람객수 열의 타입 숫자로 변환 후 재 확인
df['관람객수'] = df['관람객수'].apply(pandas.to_numeric)
기생충 1126561
알라딘 306058
고질라: 킹 오브 몬스터 78282
악인전 62886
0.0MHz 25945
어벤져스: 엔드게임 13071
피터팬: 후크 선장과 결투의 날 4394
걸캅스 4258
어린 의뢰인 2725
교회오빠 2372
Name: 관람객수, dtype: int64
- 관람객수 기준으로 오름차순 정렬
df.sort_values('관람객수', inplace=True, ascending=True)
+-------------------------------+----------+
| | 관람객수 |
+-------------------------------+----------+
| 교회오빠 | 2372 |
| 어린 의뢰인 | 2725 |
| 걸캅스 | 4258 |
| 피터팬: 후크 선장과 결투의 날 | 4394 |
| 어벤져스: 엔드게임 | 13071 |
| 0.0MHz | 25945 |
| 악인전 | 62886 |
| 고질라: 킹 오브 몬스터 | 78282 |
| 알라딘 | 306058 |
| 기생충 | 1126557 |
+-------------------------------+----------+
- 결측치 확인 후 삭제
df = df.dropna()
empty_sum = df.isnull().sum()
<class 'pandas.core.series.Series'>
관람객수 0
dtype: int64
- 시각화 작업
pyplot.rcParams["font.family"] = 'NanumGothic'
pyplot.rcParams["font.size"] = 14
pyplot.rcParams["figure.figsize"] = (16, 8)
df.plot.barh()
pyplot.grid()
pyplot.title("%s 박스오피스 순위" % yesterday_str)
pyplot.legend()
pyplot.savefig('boxoffice_daily.png', dpi=200)
pyplot.show()
pyplot.close()