본문 바로가기
API/MySQL API

Python으로 Mysql 접속, 영화추천 API

by 하니__ 2024. 5. 27.

 

 

 

이런 서비스를 만든다고 할때

 

 

API 설정

 

 

HTTP 메소드는

CRUD중 Read인

Get으로 설정

 

10개만 보여주기로 하니 count라는 변수를 10개로 설정

 

app.py 설정
api.add_resource(MovieRecommendResources, '/movie/recommend')

 

recommend.py 설정

 

class MovieRecommendResources(Resource) : 
    
    @jwt_required()
    def get(self):
        
        count = request.args.get('count')
        count = int(count)
        user_id = get_jwt_identity()

 

새로운 클래스를 만들고

 

인증토큰이 필요하니 jwt_required를 작성

get 함수를 사용

 

request로 경로에 있는 count를 가져와서

사용해야 하는데 쿼리 파라미터로 넘어온 데이터는 문자열이므로
숫자로 사용하기 위해 캐스팅 한다

 

그리고 인증토큰에서 userid를 추출한다

 

try :
    connection = get_connection()
    query = '''select m.title, r.userId, r.rating
                from movie m
                left join review r
                    on m.id = r.movieId;'''
    cursor = connection.cursor(dictionary=True)
    cursor.execute(query)
    result_list = cursor.fetchall()

    df = pd.DataFrame(data = result_list)
    df = df.pivot_table(index= 'userId',columns='title', values='rating')
    print(df)
    movie_corr = df.corr(min_periods= 50)

 

그리고 우선은 DB와 연결후

무비 테이블과 리뷰테이블을 레프트조인하여

무비테이블의 영화타이틀과

리뷰테이블의 유저아이디, 별점을 가져온다

 

그리고 그것을 데이터프레임으로 변환,

피봇테이블을 이용하여

인덱스를 유저아이디,

컬럼을 각 타이틀,

밸류를 별점으로 변환후에

상관계수를 구한다

이때 신뢰도 향상을 위해 최소값을 50으로 설정한다

 

    query = '''select m.title, r.rating
                from review r
                join movie m
                    on r.movieId = m.id
                where userId = %s;'''
    record = (user_id, )
    cursor = connection.cursor(dictionary=True)
    cursor.execute(query, record)
    result_list = cursor.fetchall()

    cursor.close()
    connection.close()

except Error as e :
    if cursor is not None:
        cursor.close()
    if connection is not None:
        connection.close()
    return{"result": "fail", "error": str(e)}, 500

 

그리고 다시 리뷰테이블과 영화테이블을 조인하여

로그인한 유저의

리뷰 남긴 영화와 별점을 얼마 줬는지를 가져온다

 

내 별점 기반으로 추천영화목록 만들기
my_review = pd.DataFrame(data= result_list)
movie_list = pd.DataFrame()

for i in np.arange( my_review.shape[0] ) :
    title = my_review['title'][i]
    recom_movie = movie_corr[title].dropna().sort_values(ascending=False).to_frame()
    recom_movie.columns = ['correlation']
    recom_movie['weight'] = recom_movie['correlation'] * my_review['rating'][i]
    movie_list = pd.concat([movie_list, recom_movie])

 

그리고 사용자의 리뷰를 기반으로

위에서 구한 상관계수가 높은 리스트를 뽑는다

 

중복 추천된 영화, 내가 이미 본 영화 제거

 

for title in my_review['title']:
    if title in movie_list.index:
        movie_list.drop(title, axis = 0, inplace= True)

movie_list = movie_list.groupby('title')['weight'].max().sort_values(ascending=False)

if movie_list.shape[0] < int(count) :
    return{"result" :"fail", 'error' : '추천영화 갯수가 count 보다 적습니다.'}, 400

 

그리고 거기서 리뷰가 여러개 였으니

서로 중첩되는 목록들은 제거하고,

내가 이미 본 영화도 제거하고,

다시 정렬을 한 뒤에

 

추천영화갯수가 설정한 count 값보다 적다면 나오지 않는 문구를 적어준다

 

판다스 데이터프레임을 JSON으로 변환
movie_list = movie_list.to_frame()
movie_list.reset_index(inplace=True)
movie_list = movie_list.to_dict('records')

return {"result":"success",
       "items" : movie_list,
       "count": len(movie_list) }, 200

 

그리고 그 추천영화 리스트를 데이터프레임으로 변환,

인덱스가 이상해졌으니 지워주고,

그리고 json형태인 딕셔너리형태로 변환 시켜준 뒤에

 

결과를 리턴해준다

 

 

 

 

로컬에선 잘 돌아가는것을 확인 할 수 있다

 

그럼 이제 서버에서 돌아가는 것을 테스트 해보자

 

 

 

 

이런 오류가 나는데

 

 

아무런 오류가 찍히지 않는다

이때 이 오류는

 

 

numpy 와 pandas를 추가 설치 하였는데

용량이 커서 서버로 올라가지 않아서 생긴 오류로

 

이때 해결법은 docker 가 있다

 

 

 

해결법은

 

AWS - Docker 개념, 설치, 설정

 

AWS - Docker 개념, 설치, 설정

우선 docker 도커란 무엇인가  도커의 CI즉, 도커를 상징하는 이미지 를 보면 고래로 보이는 형상물이컨테이너를 싣고있는 모습을 하고 있는것을 알 수 있다 말 그대로 Docker는 소프트웨어를 "

hani08.tistory.com