You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

问题分析与修复方案

核心错误原因

  1. 变量覆盖函数:fetch_poster= recommend_movie_poster.append(fetch_poster(index))这行代码把全局的fetch_poster函数名当成局部变量赋值,导致后续调用fetch_poster(index)时,Python认为它是未赋值的局部变量,抛出UnboundLocalError。而且list.append()方法返回None,不能用来赋值。
  2. 代码缩进错误:推荐逻辑的循环和UI渲染代码都不在recommend函数内部,导致函数无法执行完整逻辑。
  3. API请求参数错误:URL中的&&应该改为&,否则会导致请求失败。
  4. 数据处理错误:title_from_index是单个电影标题字符串,title_from_index[0]会取标题的第一个字符,而不是第一个推荐电影;需要先收集前5个推荐的标题和海报地址,再批量渲染。
  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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 14:15:59