yusiff commited on
Commit
6c56633
ยท
verified ยท
1 Parent(s): 151f63c

Update app4.py

Browse files
Files changed (1) hide show
  1. app4.py +207 -176
app4.py CHANGED
@@ -1,176 +1,207 @@
1
- import pickle
2
- import streamlit as st
3
- import requests
4
- from datetime import datetime
5
- st.set_page_config(page_title="๐ŸŽฌ Movie Recommender", page_icon="๐ŸŽž๏ธ", layout="wide")
6
-
7
- st.markdown("""
8
- <style>
9
- .movie-title {
10
- text-align: center;
11
- font-weight: bold;
12
- font-size: 22px;
13
- }
14
- .footer {
15
- text-align: center;
16
- font-size: 12px;
17
- color: grey;
18
- margin-top: 50px;
19
- }
20
- </style>
21
- """, unsafe_allow_html=True)
22
-
23
- # -------------------- Load Data --------------------
24
- try:
25
- movies = pickle.load(open('movie_list.pkl', 'rb'))
26
- similarity = pickle.load(open('similarity.pkl', 'rb'))
27
- except FileNotFoundError:
28
- st.error("โŒ Required data files (movie_list.pkl and similarity.pkl) not found.")
29
- st.stop()
30
-
31
- # -------------------- Helper Functions --------------------
32
- def fetch_poster(movie_id):
33
- try:
34
- url = f"https://api.themoviedb.org/3/movie/{movie_id}?api_key=8265bd1679663a7ea12ac168da84d2e8&language=en-US"
35
- response = requests.get(url)
36
- data = response.json()
37
- poster_path = data.get('poster_path')
38
- return f"https://image.tmdb.org/t/p/w500/{poster_path}" if poster_path else "https://via.placeholder.com/500x750?text=No+Image"
39
- except:
40
- return "https://via.placeholder.com/500x750?text=Error"
41
-
42
- def fetch_movie_details(movie_id):
43
- try:
44
- url = f"https://api.themoviedb.org/3/movie/{movie_id}?api_key=8265bd1679663a7ea12ac168da84d2e8&language=en-US"
45
- response = requests.get(url)
46
- data = response.json()
47
- overview = data.get('overview', 'No overview available.')
48
- rating = data.get('vote_average', 'No rating')
49
- release_date = data.get('release_date', 'No release date')
50
- genres = ', '.join([genre['name'] for genre in data.get('genres', [])])
51
- return overview, rating, release_date, genres
52
- except:
53
- return "No details available.", "No rating", "No release date", "No genres"
54
-
55
- def recommend(movie):
56
- if movie not in movies['title'].values:
57
- return [], [], []
58
- index = movies[movies['title'] == movie].index[0]
59
- distances = sorted(list(enumerate(similarity[index])), reverse=True, key=lambda x: x[1])
60
- recommended_names = []
61
- recommended_posters = []
62
- recommended_ids = []
63
- for i in distances[1:6]:
64
- movie_id = movies.iloc[i[0]].movie_id
65
- recommended_names.append(movies.iloc[i[0]].title)
66
- recommended_posters.append(fetch_poster(movie_id))
67
- recommended_ids.append(movie_id) # ุญูุธ ุงู„ู€ movie_id ู„ุชูุงุตูŠู„ ุงู„ููŠู„ู…
68
- return recommended_names, recommended_posters, recommended_ids
69
-
70
- # -------------------- Page 1: Welcome --------------------
71
- def page_1():
72
- st.markdown("<h1 style='text-align: center;'>๐ŸŽฌ Movie Recommender</h1>", unsafe_allow_html=True)
73
- st.markdown("<hr>", unsafe_allow_html=True)
74
-
75
- hour = datetime.now().hour
76
- greeting_time = "Good Morning โ˜€๏ธ" if hour < 12 else "Good Evening ๐ŸŒ™" if hour >= 18 else "Good Afternoon ๐ŸŒค๏ธ"
77
- st.markdown(f"### {greeting_time}")
78
-
79
- user_name = st.text_input("๐Ÿ‘ค Enter your name:")
80
- if st.button("Continue to Movie Selection"):
81
- if user_name:
82
- st.session_state.name = user_name
83
- st.session_state.page = "select_movie"
84
- else:
85
- st.warning("Please enter your name first ๐Ÿ˜Š")
86
-
87
- # -------------------- Page 2: All-In-One (Select, Rate, Recommend, Details) --------------------
88
- def page_2():
89
- st.markdown(f"### Hello, {st.session_state.name} ๐Ÿ‘‹", unsafe_allow_html=True)
90
-
91
- movie_list = movies['title'].values
92
- selected_movie = st.selectbox("๐ŸŽฅ Select a Movie", movie_list)
93
-
94
- rating = st.slider("โญ Your Rating", 1, 10, 1)
95
- st.write(f"โœ… Your rating: {rating} stars")
96
-
97
- # ุชู‡ูŠุฆุฉ ุงู„ู…ุชุบูŠุฑุงุช ููŠ ุงู„ุฌู„ุณุฉ
98
- if "show_recommendations" not in st.session_state:
99
- st.session_state.show_recommendations = False
100
- if "show_details" not in st.session_state:
101
- st.session_state.show_details = {}
102
-
103
- # ุฃุฒุฑุงุฑ ุงู„ุชุจุฏูŠู„
104
- if st.button("๐ŸŽฏ Recommendations"):
105
- st.session_state.show_recommendations = not st.session_state.show_recommendations
106
-
107
- # ุนุฑุถ ุงู„ุชูˆุตูŠุงุช ุฅุฐุง ุชู… ุงู„ุชูุนูŠู„
108
- if st.session_state.show_recommendations:
109
- with st.spinner("โณ Fetching recommendations..."):
110
- names, posters, ids = recommend(selected_movie)
111
- if names:
112
- st.markdown(f"### โœ… Recommended Movies Similar to {selected_movie}:")
113
- cols = st.columns(5)
114
- for i in range(5):
115
- with cols[i]:
116
- details_key = f"details_{i}"
117
- if details_key not in st.session_state.show_details:
118
- st.session_state.show_details[details_key] = False
119
-
120
- if st.button(f"Show {names[i]} Details", key=details_key):
121
- st.session_state.show_details[details_key] = not st.session_state.show_details[details_key]
122
-
123
- if st.session_state.show_details.get(details_key, False):
124
- movie_id = ids[i]
125
- overview, vote_avg, release_date, genres = fetch_movie_details(movie_id)
126
- st.markdown(f"### ๐Ÿ“– Movie Details, {names[i]}:")
127
- st.markdown(f"**Overview**: {overview}")
128
- st.markdown(f"**Rating**: {vote_avg}/10")
129
- st.markdown(f"**Release Date**: {release_date}")
130
- st.markdown(f"**Genres**: {genres}")
131
-
132
- st.image(posters[i], use_container_width=True)
133
- st.markdown(f"<div class='movie-title'>{names[i]}</div>", unsafe_allow_html=True)
134
-
135
- else:
136
- st.warning("โš ๏ธ No recommendations found.")
137
-
138
- # ุชู‡ูŠุฆุฉ ุญุงู„ุฉ ุฅุธู‡ุงุฑ ุงู„ุชูุงุตูŠู„ ุฅู† ู„ู… ุชูƒู† ู…ูˆุฌูˆุฏุฉ
139
- if "show_selected_details" not in st.session_state:
140
- st.session_state.show_selected_details = False
141
-
142
- # ุฒุฑ ุงู„ุชุจุฏูŠู„ ุจูŠู† ุนุฑุถ/ุฅุฎูุงุก ุงู„ุชูุงุตูŠู„
143
- if st.button(f"๐Ÿ“– Show Details of {selected_movie}"):
144
- st.session_state.show_selected_details = not st.session_state.show_selected_details
145
-
146
- # ุนุฑุถ ุงู„ุชูุงุตูŠู„ ุฅุฐุง ูƒุงู†ุช ุงู„ุญุงู„ุฉ ู…ูุนู‘ู„ุฉ
147
- if st.session_state.show_selected_details:
148
- movie_id = movies[movies['title'] == selected_movie].movie_id.iloc[0]
149
- overview, vote_avg, release_date, genres = fetch_movie_details(movie_id)
150
- st.markdown(f"### ๐Ÿ“– Movie Details, {selected_movie}:")
151
- st.markdown(f"**Overview**: {overview}")
152
- st.markdown(f"**Rating**: {vote_avg}/10")
153
- st.markdown(f"**Release Date**: {release_date}")
154
- st.markdown(f"**Genres**: {genres}")
155
-
156
-
157
-
158
- if st.button("๐Ÿ”™ Back"):
159
- st.session_state.page = "welcome"
160
-
161
- # -------------------- Page Navigation --------------------
162
- if 'page' not in st.session_state:
163
- st.session_state.page = "welcome"
164
-
165
- if st.session_state.page == "welcome":
166
- page_1()
167
- elif st.session_state.page == "select_movie":
168
- page_2()
169
-
170
- # -------------------- Footer --------------------
171
- st.markdown("<hr>", unsafe_allow_html=True)
172
- st.markdown("<div class='footer'>ยฉ 2025 โ€ข by Youssef โ€ข Powered by TMDB API</div>", unsafe_allow_html=True)
173
-
174
-
175
-
176
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pickle
2
+ import streamlit as st
3
+ import requests
4
+ from datetime import datetime
5
+
6
+ # ุฅุนุฏุงุฏ ุงู„ุตูุญุฉ
7
+ st.set_page_config(page_title="๐ŸŽฌ Movie Recommender", page_icon="๐ŸŽž๏ธ", layout="wide")
8
+
9
+ # -------------------- ุตูุญุฉ ุฅุฏุฎุงู„ ุงุณู… ุงู„ู…ุณุชุฎุฏู… --------------------
10
+ if 'name' not in st.session_state:
11
+ st.session_state.name = None
12
+
13
+ # ุงู„ุชุญู‚ู‚ ุฅุฐุง ูƒุงู† ุงู„ู…ุณุชุฎุฏู… ู‚ุฏ ุฃุฏุฎู„ ุงุณู…ู‡ ุจุงู„ูุนู„
14
+ if st.session_state.name is None:
15
+ # ุตูุญุฉ ุฅุฏุฎุงู„ ุงู„ุงุณู…
16
+ st.title("๐ŸŽฌ Welcome to the Movie Recommender!")
17
+ st.markdown("Please enter your name to continue.")
18
+
19
+ name = st.text_input("Enter your name", "")
20
+
21
+ if st.button("Submit"):
22
+ if name:
23
+ st.session_state.name = name # ุชุฎุฒูŠู† ุงู„ุงุณู… ููŠ session_state
24
+ st.success(f"Hello, {name}! Welcome to the Movie Recommender ๐ŸŽฌ")
25
+ # ุฅุนุงุฏุฉ ุชุญู…ูŠู„ ุงู„ุตูุญุฉ ุจุงุณุชุฎุฏุงู… st.empty()
26
+ st.empty() # ูŠู…ูƒู† ุฅุนุงุฏุฉ ุชุญู…ูŠู„ ุงู„ู…ุญุชูˆู‰ ู‡ู†ุง ุฃูˆ ู…ู† ุฎู„ุงู„ ุงุณุชุจุฏุงู„ ู‡ุฐุง ุจู€ rerun ุจุณูŠุท
27
+ else:
28
+ st.error("Please enter a valid name.") # ุฅุฐุง ู„ู… ูŠุชู… ุฅุฏุฎุงู„ ุงุณู…
29
+
30
+ else:
31
+ # -------------------- ุชุญุณูŠู† ุชู†ุณูŠู‚ ุงู„ุดุฑูŠุท ุงู„ุฌุงู†ุจูŠ ุจุงุณุชุฎุฏุงู… CSS --------------------
32
+ st.markdown("""
33
+ <style>
34
+ .sidebar .sidebar-content {
35
+ background-color: #2c3e50; /* ุฎู„ููŠุฉ ุฏูƒู†ุงุก */
36
+ color: white;
37
+ padding: 15px;
38
+ border-radius: 10px;
39
+ }
40
+ .sidebar .sidebar-content h1, .sidebar .sidebar-content h2 {
41
+ font-size: 20px;
42
+ font-weight: bold;
43
+ color: #ecf0f1; /* ู„ูˆู† ุงู„ู†ุต */
44
+ }
45
+ .sidebar .sidebar-content .stButton button {
46
+ background-color: #3498db; /* ุฒุฑ ู„ูˆู† ุฃุฒุฑู‚ */
47
+ color: white;
48
+ font-weight: bold;
49
+ border-radius: 5px;
50
+ width: 100%;
51
+ padding: 10px;
52
+ }
53
+ .sidebar .sidebar-content .stButton button:hover {
54
+ background-color: #2980b9;
55
+ }
56
+ </style>
57
+ """, unsafe_allow_html=True)
58
+
59
+ # -------------------- ุชุญู…ูŠู„ ุงู„ุจูŠุงู†ุงุช --------------------
60
+ try:
61
+ movies = pickle.load(open('movie_list.pkl', 'rb'))
62
+ similarity = pickle.load(open('similarity.pkl', 'rb'))
63
+ except FileNotFoundError:
64
+ st.error("โŒ Required data files (movie_list.pkl and similarity.pkl) not found.")
65
+ st.stop()
66
+
67
+ # -------------------- ุฏูˆุงู„ ุงู„ู…ุณุงุนุฏุฉ --------------------
68
+ def fetch_poster(movie_id):
69
+ try:
70
+ url = f"https://api.themoviedb.org/3/movie/{movie_id}?api_key=8265bd1679663a7ea12ac168da84d2e8&language=en-US"
71
+ response = requests.get(url)
72
+ data = response.json()
73
+ poster_path = data.get('poster_path')
74
+ return f"https://image.tmdb.org/t/p/w500/{poster_path}" if poster_path else "https://via.placeholder.com/500x750?text=No+Image"
75
+ except:
76
+ return "https://via.placeholder.com/500x750?text=Error"
77
+
78
+ def fetch_movie_details(movie_id):
79
+ try:
80
+ url = f"https://api.themoviedb.org/3/movie/{movie_id}?api_key=8265bd1679663a7ea12ac168da84d2e8&language=en-US"
81
+ response = requests.get(url)
82
+ data = response.json()
83
+ overview = data.get('overview', 'No overview available.')
84
+ rating = data.get('vote_average', 'No rating')
85
+ release_date = data.get('release_date', 'No release date')
86
+ genres = ', '.join([genre['name'] for genre in data.get('genres', [])])
87
+ return overview, rating, release_date, genres
88
+ except:
89
+ return "No details available.", "No rating", "No release date", "No genres"
90
+
91
+ def recommend(movie):
92
+ if movie not in movies['title'].values:
93
+ return [], [], []
94
+ index = movies[movies['title'] == movie].index[0]
95
+ distances = sorted(list(enumerate(similarity[index])), reverse=True, key=lambda x: x[1])
96
+ recommended_names = []
97
+ recommended_posters = []
98
+ recommended_ids = []
99
+ for i in distances[1:6]:
100
+ movie_id = movies.iloc[i[0]].movie_id
101
+ recommended_names.append(movies.iloc[i[0]].title)
102
+ recommended_posters.append(fetch_poster(movie_id))
103
+ recommended_ids.append(movie_id)
104
+ return recommended_names, recommended_posters, recommended_ids
105
+
106
+ def fetch_popular_movies():
107
+ url = "https://api.themoviedb.org/3/movie/popular?api_key=8265bd1679663a7ea12ac168da84d2e8&language=en-US&page=1"
108
+ try:
109
+ response = requests.get(url)
110
+ data = response.json()
111
+ popular_movies = []
112
+ for movie in data['results'][:60]:
113
+ title = movie['title']
114
+ poster_path = movie.get('poster_path')
115
+ poster_url = f"https://image.tmdb.org/t/p/w500/{poster_path}" if poster_path else "https://via.placeholder.com/500x750?text=No+Image"
116
+ movie_id = movie['id']
117
+ popular_movies.append((title, poster_url, movie_id))
118
+ return popular_movies
119
+ except:
120
+ return []
121
+
122
+ # -------------------- ุงู„ุชู†ู‚ู„ ููŠ ุงู„ุดุฑูŠุท ุงู„ุฌุงู†ุจูŠ --------------------
123
+ st.sidebar.markdown("""
124
+ <div style="text-align:center; color:white; font-size:30px; font-weight:bold;">
125
+ ๐ŸŽž๏ธ Movie Recommender
126
+ </div>
127
+ <hr style="border-color: #ecf0f1;">
128
+ """, unsafe_allow_html=True)
129
+
130
+ st.session_state.selected_section = st.sidebar.radio(
131
+ "Navigate",
132
+ ["Popular Movies", "Recommend Movies", "Movie Details"]
133
+ )
134
+
135
+ # -------------------- ุงู„ุตูุญุฉ ุงู„ุฑุฆูŠุณูŠุฉ --------------------
136
+ st.markdown(f"### Hello, {st.session_state.get('name', 'Guest')} ๐Ÿ‘‹", unsafe_allow_html=True)
137
+
138
+ if st.session_state.selected_section == "Popular Movies":
139
+ with st.expander("๐Ÿ”ฅ Popular Movies", expanded=True):
140
+ popular = fetch_popular_movies()
141
+ if popular:
142
+ cols = st.columns(5)
143
+ for i, (title, poster_url, movie_id) in enumerate(popular):
144
+ with cols[i % 5]:
145
+ st.image(poster_url, use_container_width=True)
146
+ st.markdown(f"<div class='movie-title'>{title}</div>", unsafe_allow_html=True)
147
+ if st.button("๐Ÿ“„ Details", key=f"popular_details_{i}"):
148
+ overview, rating, release_date, genres = fetch_movie_details(movie_id)
149
+ st.markdown(f"**๐Ÿ“… Release Date:** {release_date}")
150
+ st.markdown(f"**โญ Rating:** {rating}")
151
+ st.markdown(f"**๐ŸŽญ Genres:** {genres}")
152
+ st.markdown(f"**๐Ÿ“ Overview:** {overview}")
153
+ else:
154
+ st.warning("Could not fetch popular movies.")
155
+
156
+ elif st.session_state.selected_section == "Recommend Movies":
157
+ movie_list = movies['title'].values
158
+ selected_movie = st.selectbox("๐ŸŽฅ Select a Movie", movie_list)
159
+ rating = st.slider("โญ Your Rating", 1, 10, 1)
160
+ st.write(f"โœ… Your rating: {rating} stars")
161
+
162
+ if "show_recommendations" not in st.session_state:
163
+ st.session_state.show_recommendations = False
164
+
165
+ if st.button("๐ŸŽฏ Show Recommendations"):
166
+ st.session_state.show_recommendations = not st.session_state.show_recommendations
167
+
168
+ if st.session_state.show_recommendations:
169
+ with st.spinner("โณ Fetching recommendations..."):
170
+ names, posters, ids = recommend(selected_movie)
171
+ if names:
172
+ st.markdown(f"### โœ… Recommended Movies Similar to {selected_movie}:")
173
+ cols = st.columns(5)
174
+ for i in range(len(names)):
175
+ with cols[i % 5]:
176
+ st.image(posters[i], use_container_width=True)
177
+ st.markdown(f"<div class='movie-title'>{names[i]}</div>", unsafe_allow_html=True)
178
+ if st.button("๐Ÿ“„ Details", key=f"recommend_details_{i}"):
179
+ overview, rating, release_date, genres = fetch_movie_details(ids[i])
180
+ st.markdown(f"**๐Ÿ“… Release Date:** {release_date}")
181
+ st.markdown(f"**โญ Rating:** {rating}")
182
+ st.markdown(f"**๐ŸŽญ Genres:** {genres}")
183
+ st.markdown(f"**๐Ÿ“ Overview:** {overview}")
184
+ else:
185
+ st.warning("No recommendations found.")
186
+
187
+ elif st.session_state.selected_section == "Movie Details":
188
+ if "show_details" not in st.session_state:
189
+ st.session_state.show_details = {}
190
+
191
+ movie_list = movies['title'].values
192
+ selected_movie = st.selectbox("๐ŸŽฅ Select a Movie to View Details", movie_list)
193
+ index = movies[movies['title'] == selected_movie].index[0]
194
+ movie_id = movies.iloc[index].movie_id
195
+ overview, rating, release_date, genres = fetch_movie_details(movie_id)
196
+ st.image(fetch_poster(movie_id), use_container_width=True)
197
+ st.markdown(f"**๐Ÿ“… Release Date:** {release_date}")
198
+ st.markdown(f"**โญ Rating:** {rating}")
199
+ st.markdown(f"**๐ŸŽญ Genres:** {genres}")
200
+ st.markdown(f"**๐Ÿ“ Overview:** {overview}")
201
+ # -------------------- Footer --------------------
202
+ st.markdown("<hr>", unsafe_allow_html=True)
203
+ st.markdown("<div class='footer'>ยฉ 2025 โ€ข by Youssef samy โ€ข Powered by TMDB API</div>", unsafe_allow_html=True)
204
+
205
+
206
+
207
+