이런 서비스를 만든다고 할때
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 가 있다
해결법은
'API > MySQL API' 카테고리의 다른 글
Python으로 Mysql접속, 사진 업로드&오토태깅&DB저장 API, 포스팅 수정&DB수정 API (4) | 2024.05.29 |
---|---|
Python으로 Mysql접속, 영화리스트 가져오는 API (0) | 2024.05.27 |
Python으로 Mysql 접속, 회원 정보 수정 API (0) | 2024.05.24 |
Python으로 Mysql 접속, 회원탈퇴 API (0) | 2024.05.24 |
Python으로 Mysql 접속, 로그아웃 API (0) | 2024.05.22 |