基于Streamlit的电影推荐系统海报获取UnboundLocalError问题排查
电影推荐系统海报获取功能报错修复
我正在开发一个基于机器学习的电影推荐项目,使用了**余弦相似度(cosine-similarity)**算法。目前已经得到推荐结果,但添加获取电影海报的函数后无法正常运行,以下是我的代码和报错信息:
原代码
import difflib import streamlit as st import pickle import pandas as pd import requests def fetch_poster(movie_id): response=requests.get('https://api.themoviedb.org/3/movie/{}?api_key=66862ec077a533abc19c22e85570925e&&language=en-US'.format(movie_id)) data=response.json() return 'https://image.tmdb.org/t/p/original'+data['poster_path'] mv_movie=pd.read_csv('movieList.csv') similarity=pickle.load(open('similarity.pkl','rb')) list_of_all_titles= mv_movie['title'].tolist() def recommend(movie): find_close_match = difflib.get_close_matches(movie, list_of_all_titles) close_match = find_close_match[0] index_of_the_movie = mv_movie[mv_movie.title == close_match]['index'].values[0] similarity_score = list(enumerate(similarity[index_of_the_movie])) sorted_similar_movies = sorted(similarity_score, key = lambda x:x[1], reverse = True) recommend_movie_poster=[] print('Movies suggested for you : \n') i = 1 for movie in sorted_similar_movies: index = movie[0] title_from_index = mv_movie[mv_movie.index==index]['title'].values[0] fetch_poster= recommend_movie_poster.append(fetch_poster(index)) if (i<6): st.write(i, '.',title_from_index,fetch_poster) i+=1 col1, col2, col3,col4,col5 = st.columns(5) with col1: st.header(title_from_index[0]) st.image(fetch_poster[0]) with col2: st.header(title_from_index[1]) st.image(fetch_poster[1]) with col3: st.header(title_from_index[2]) st.image(fetch_poster[2]) with col4: st.header(title_from_index[3]) st.image(fetch_poster[3]) with col5: st.header(title_from_index[4]) st.image(fetch_poster[4]) st.title('Movie Recommender System') selected_movie_name = st.selectbox( 'Select Your Favourite Movie', list_of_all_titles) if st.button('Recommend'): recommend(selected_movie_name)
报错信息
fetch_poster= recommend_movie_poster.append(fetch_poster(index)) ^^^^^^^^^^^^ UnboundLocalError: cannot access local variable 'fetch_poster' where it is not associated with a value
问题分析与修复方案
核心错误原因
- 变量覆盖函数:
fetch_poster= recommend_movie_poster.append(fetch_poster(index))这行代码把全局的fetch_poster函数名当成局部变量赋值,导致后续调用fetch_poster(index)时,Python认为它是未赋值的局部变量,抛出UnboundLocalError。而且list.append()方法返回None,不能用来赋值。 - 代码缩进错误:推荐逻辑的循环和UI渲染代码都不在
recommend函数内部,导致函数无法执行完整逻辑。 - API请求参数错误:URL中的
&&应该改为&,否则会导致请求失败。 - 数据处理错误:
title_from_index是单个电影标题字符串,title_from_index[0]会取标题的第一个字符,而不是第一个推荐电影;需要先收集前5个推荐的标题和海报地址,再批量渲染。 - 空值处理缺失:如果电影没有
poster_path,会抛出KeyError,需要添加默认值。
修复后的完整代码
import difflib import streamlit as st import pickle import pandas as pd import requests def fetch_poster(movie_id): # 修正URL参数的&&为& response = requests.get(f'https://api.themoviedb.org/3/movie/{movie_id}?api_key=66862ec077a533abc19c22e85570925e&language=en-US') data = response.json() # 处理poster_path为空的情况,添加默认图片地址 poster_path = data.get('poster_path', '') if poster_path: return f'https://image.tmdb.org/t/p/original{poster_path}' # 返回默认海报地址(可替换为自定义图片链接) return 'https://via.placeholder.com/300x450?text=No+Poster' mv_movie = pd.read_csv('movieList.csv') similarity = pickle.load(open('similarity.pkl', 'rb')) list_of_all_titles = mv_movie['title'].tolist() def recommend(movie): find_close_match = difflib.get_close_matches(movie, list_of_all_titles) if not find_close_match: st.warning('没有找到匹配的电影,请重新选择') return [], [] close_match = find_close_match[0] # 兼容数据集是否有自定义index列 if 'index' in mv_movie.columns: index_of_the_movie = mv_movie[mv_movie.title == close_match]['index'].values[0] else: index_of_the_movie = mv_movie[mv_movie.title == close_match].index.values[0] similarity_score = list(enumerate(similarity[index_of_the_movie])) sorted_similar_movies = sorted(similarity_score, key=lambda x:x[1], reverse=True) recommend_movies = [] recommend_posters = [] # 取前5个相似电影(排除自身) for i, movie_item in enumerate(sorted_similar_movies[1:6], 1): index = movie_item[0] title = mv_movie.iloc[index]['title'] movie_id = mv_movie.iloc[index]['id'] # 确保movieList.csv包含TMDB电影ID的id列 poster_url = fetch_poster(movie_id) recommend_movies.append(title) recommend_posters.append(poster_url) return recommend_movies, recommend_posters # Streamlit UI st.title('电影推荐系统') selected_movie_name = st.selectbox( '选择你喜欢的电影', list_of_all_titles) if st.button('获取推荐'): with st.spinner('正在生成推荐...'): recommended_titles, recommended_posters = recommend(selected_movie_name) if recommended_titles: st.subheader('为你推荐的电影:') cols = st.columns(5) for col, title, poster in zip(cols, recommended_titles, recommended_posters): with col: st.image(poster, use_column_width=True) st.caption(title)
额外说明
- 确保
movieList.csv包含id列,对应TMDB平台的电影ID,否则无法调用API获取海报。 - 可替换默认海报地址为自定义图片链接,优化无海报时的显示效果。
- 添加了匹配不到电影的警告提示,提升用户体验。
内容的提问来源于stack exchange,提问作者1018_csds_Pranjal Sharma
相关产品推荐
相关产品推荐

