Data Engineering/실습

fastapi + movie api

qqprty 2024. 8. 13. 21:51

기존 코드

from typing import Union

from fastapi import FastAPI, HTTPException
import pandas as pd

app = FastAPI()

df = pd.read_parquet('/home/oddsummer/code/ffapi/data')

@app.get("/sample")
def sample_data():
    df = pd.read_parquet('/home/diginori/code/ffapi/data')
    sample_df = df.sample(n=5)
    r = sample_df.to_dict(orient='records')
    return r
    
@app.get("/movie/{movie_cd}")
def movie_meta(movie_cd: str):

    # df에서 movieCd == movie_cd 인 row 조회 df[df['a']==b]
    meta_df = df[df['movieCd'] == movie_cd]

    if meta_df.empty:
        raise HTTPException(status_code=404, detail="영화를 찾을 수 없습니다.")

    # 조회된 데이터 .to_dict로 만들어서 return
    r = meta_df.iloc[0].to_dict()
    return r

 

해당경로의 parquet 형식의 파일을 읽어와서, request한 movieCd에 맞는 row를 조회한다.

만약 request한 영화코드가 존재하지 않으면 오류코드를 발생한다.

meta_df.iloc[0]을 하면 meta_df라는 데이터프레임에서 첫 번째 행(즉, 인덱스가 0인 행)을 선택한다.

그렇게되면 다음과 같은 데이터가 반환되고

{
    "movieCd": "20124079",
    "movieNm": "광해, 왕이 된 남자",
    "movieNmEn": "Masquerade",
    "movieNmOg": "",
    "showTm": "131",
    "prdtYear": "2012",
    "openDt": "20120913",
    "prdtStatNm": "개봉",
    "typeNm": "장편",
    "nations": [{"nationNm": "한국"}],
    "genres": [{"genreNm": "사극"}, {"genreNm": "드라마"}],
    "directors": [{"peopleNm": "추창민", "peopleNmEn": "CHOO Chang-min"}]
    ...
}

 

이를 딕셔너리로 변환하여, 각 열의 이름이 사전의 키(key)가 되고, 그 열에 해당하는 값들이 사전의 값(value)으로 변환되어 r에 저장된다. 

 

http://127.0.0.1:8000/movie/20100359

다음과 같이 호출하면 다음과 같이 repNationCd 값이 null로 뜬다 (데이터에 없기 때문)

{
  "movieCd": "20100359",
  "multiMovieYn": "Y",
  "repNationCd": null
}

 

이를 영화진흥위원회의 API 중 "영화 상세정보" API 를 호출하여, 해당 영화코드에 맞는 repNationCd값을 불러와서 null값을 채우는 코드로 수정해보자. 


1. 영화 상세정보 API를 호출하는 req 함수 생성

 

1) API 호출에 사용할 URL을 영화 코드(movie_cd)와 API 키(key)를 사용해 구성

2) URL로 HTTP GET 요청을 보내고, 응답받기

3) 받은 응답을 JSON 형태로 파싱하여 Python의 딕셔너리로 변환

4) JSON 데이터에서 'movieInfoResult'의 'movieInfo' 부분에 접근

- JSON 구조 내에서 'movieInfoResult'라는 키 아래에 있는 'movieInfo'에 접근

5) 'movieInfo' 부분에서 'nations' 리스트의 첫 번째 항목에서 국가 이름('nationNm')을 가져옴

- 'nations' 는 리스트이므로 인덱스 번호를 통해 특정 항목을 선택

6) 국가 이름이 '한국'이면 'K'를 반환하고, 그렇지 않으면 'F'를 반환

 

2. null값 대신 API 호출해서 repNationCd 값 넣기

 

딕셔너리 r에 'repNationCd'라는 키가 없거나 그 값이 없을 경우(None), 해당 값을 req(movie_cd)를 호출하여 채워주기

 

수정 된 코드

from typing import Union

from fastapi import FastAPI, HTTPException
import pandas as pd
import os
import requests
import json

app = FastAPI()

df = pd.read_parquet('/home/oddsummer/code/ffapi/data')

@app.get("/mov/{movie_cd}")
def req(movie_cd):
    key = os.getenv("MOVIE_API_KEY")
    base_url = "http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieInfo.json"
    url = f"{base_url}?key={key}&movieCd={movie_cd}"
    r = requests.get(url)
    data = r.json()

    l = data['movieInfoResult']['movieInfo']
    nation_Cd = l['nations'][0]['nationNm']
	#nation_Cd = data['movieInfoResult']['movieInfo']['nations'][0]['nationNm']
    
    if nation_Cd == '한국':
        return 'K'
    else:
        return 'F'

@app.get("/movie/{movie_cd}")
def movie_meta(movie_cd: str):

    # df에서 movieCd == movie_cd 인 row 조회 df[df['a']==b]
    meta_df = df[df['movieCd'] == movie_cd]

    if meta_df.empty:
        raise HTTPException(status_code=404, detail="영화를 찾을 수 없습니다.")

    # 조회된 데이터 .to_dict로 만들어서 return
    r = meta_df.iloc[0].to_dict()

    if r.get('repNationCd') is None:
        r['repNationCd'] = req(movie_cd)

    return r