AnnNaser commited on
Commit
55e5424
·
verified ·
1 Parent(s): d38a8fd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +19 -63
app.py CHANGED
@@ -2,17 +2,14 @@ import streamlit as st
2
  import requests
3
  import pandas as pd
4
  import numpy as np
5
- from sklearn.feature_extraction.text import TfidfVectorizer
6
- from sklearn.metrics.pairwise import cosine_similarity
7
  from sklearn.preprocessing import MultiLabelBinarizer
8
- from gensim import corpora
9
- from gensim.models import LdaModel
10
  import nltk
11
- from nltk.corpus import stopwords
12
  import re
13
 
14
  # Download NLTK stopwords
15
  nltk.download("stopwords")
 
16
  stop_words = set(stopwords.words("english"))
17
 
18
  # Constants
@@ -49,10 +46,8 @@ def fetch_books(query, limit=100):
49
  book = {
50
  "title": doc.get("title", ""),
51
  "author": doc.get("author_name", [""])[0],
52
- "author_image": None, # Open Library doesn't provide author images directly
53
  "genre": doc.get("subject", []),
54
  "year": doc.get("first_publish_year", None),
55
- "description": doc.get("first_sentence", [""])[0] if doc.get("first_sentence") else "",
56
  "cover_image": cover_image
57
  }
58
  books.append(book)
@@ -61,65 +56,24 @@ def fetch_books(query, limit=100):
61
  st.error("Failed to fetch data from Open Library.")
62
  return []
63
 
64
- def preprocess_text(text):
65
- """Preprocess text by removing special characters, stopwords, and lowercasing."""
66
- text = re.sub(r"\W", " ", text.lower()) # Remove special characters and lowercase
67
- tokens = text.split()
68
- tokens = [word for word in tokens if word not in stop_words] # Remove stopwords
69
- return " ".join(tokens)
70
-
71
- def extract_topics(descriptions, num_topics=5):
72
- """Extract topics from book descriptions using LDA."""
73
- processed_texts = [preprocess_text(desc) for desc in descriptions if desc.strip()]
74
- if not processed_texts:
75
- return [0] * len(descriptions) # Return default topic if no valid descriptions
76
-
77
- tokenized_texts = [text.split() for text in processed_texts]
78
- if not any(tokenized_texts):
79
- return [0] * len(descriptions) # Return default topic if no valid tokens
80
-
81
- dictionary = corpora.Dictionary(tokenized_texts)
82
- if not dictionary:
83
- return [0] * len(descriptions) # Return default topic if dictionary is empty
84
-
85
- corpus = [dictionary.doc2bow(text) for text in tokenized_texts]
86
- if not any(corpus):
87
- return [0] * len(descriptions) # Return default topic if corpus is empty
88
-
89
- lda_model = LdaModel(corpus, num_topics=num_topics, id2word=dictionary, passes=15)
90
- topics = []
91
- for text in tokenized_texts:
92
- if not text:
93
- topics.append(0)
94
- continue
95
- bow = dictionary.doc2bow(text)
96
- if not bow:
97
- topics.append(0)
98
- continue
99
- topic_distribution = lda_model.get_document_topics(bow)
100
- topics.append(max(topic_distribution, key=lambda x: x[1])[0])
101
- return topics
102
 
103
  def recommend_books(input_books, all_books, top_n=20):
104
- """Recommend books based on similarity of descriptions, genres, and topics."""
105
- input_descriptions = [book["description"] for book in input_books]
106
- all_descriptions = [book["description"] for book in all_books]
107
  input_genres = [book["genre"] for book in input_books]
108
  all_genres = [book["genre"] for book in all_books]
109
-
110
- input_topics = extract_topics(input_descriptions)
111
- all_topics = extract_topics(all_descriptions)
112
 
113
  mlb = MultiLabelBinarizer()
114
  input_genres_encoded = mlb.fit_transform(input_genres)
115
  all_genres_encoded = mlb.transform(all_genres)
116
 
117
- vectorizer = TfidfVectorizer()
118
- input_tfidf = vectorizer.fit_transform(input_descriptions)
119
- all_tfidf = vectorizer.transform(all_descriptions)
120
-
121
- input_features = np.hstack((input_tfidf.toarray(), input_genres_encoded, np.array(input_topics).reshape(-1, 1)))
122
- all_features = np.hstack((all_tfidf.toarray(), all_genres_encoded, np.array(all_topics).reshape(-1, 1)))
123
 
124
  similarity_scores = cosine_similarity(input_features, all_features)
125
  avg_similarity = similarity_scores.mean(axis=0)
@@ -157,10 +111,10 @@ def main():
157
  filtered_books = [book for book in books if book["year"] and start_year <= book["year"] <= end_year]
158
  st.write(f"Found {len(filtered_books)} books between {start_year} and {end_year}.")
159
 
160
- # Filter books with valid descriptions
161
- valid_books = [book for book in filtered_books if book["description"].strip()]
162
  if not valid_books:
163
- st.warning("No books with valid descriptions found. Try a different query or adjust filters.")
164
  st.stop()
165
 
166
  # Display filtered books
@@ -171,7 +125,8 @@ def main():
171
  st.write(f"**Author:** {book['author']}")
172
  if book["cover_image"]:
173
  st.image(book["cover_image"], caption=book["title"], width=150)
174
- st.write(f"**Description:** {book['description']}")
 
175
  st.write("---")
176
 
177
  # Generate recommendations
@@ -183,8 +138,9 @@ def main():
183
  st.write(f"**Author:** {book['author']}")
184
  if book["cover_image"]:
185
  st.image(book["cover_image"], caption=book["title"], width=150)
186
- st.write(f"**Description:** {book['description']}")
 
187
  st.write("---")
188
 
189
  if __name__ == "__main__":
190
- main()
 
2
  import requests
3
  import pandas as pd
4
  import numpy as np
 
 
5
  from sklearn.preprocessing import MultiLabelBinarizer
6
+ from sklearn.metrics.pairwise import cosine_similarity
 
7
  import nltk
 
8
  import re
9
 
10
  # Download NLTK stopwords
11
  nltk.download("stopwords")
12
+ from nltk.corpus import stopwords
13
  stop_words = set(stopwords.words("english"))
14
 
15
  # Constants
 
46
  book = {
47
  "title": doc.get("title", ""),
48
  "author": doc.get("author_name", [""])[0],
 
49
  "genre": doc.get("subject", []),
50
  "year": doc.get("first_publish_year", None),
 
51
  "cover_image": cover_image
52
  }
53
  books.append(book)
 
56
  st.error("Failed to fetch data from Open Library.")
57
  return []
58
 
59
+ def preprocess_genres_and_topics(genres, topics):
60
+ """Preprocess genre and topic lists to create a combined feature."""
61
+ combined = genres + topics
62
+ return combined
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
  def recommend_books(input_books, all_books, top_n=20):
65
+ """Recommend books based on selected topics, genres, and year."""
 
 
66
  input_genres = [book["genre"] for book in input_books]
67
  all_genres = [book["genre"] for book in all_books]
68
+ input_topics = [book["topics"] for book in input_books]
69
+ all_topics = [book["topics"] for book in all_books]
 
70
 
71
  mlb = MultiLabelBinarizer()
72
  input_genres_encoded = mlb.fit_transform(input_genres)
73
  all_genres_encoded = mlb.transform(all_genres)
74
 
75
+ input_features = np.hstack((input_genres_encoded, np.array(input_topics).reshape(-1, 1)))
76
+ all_features = np.hstack((all_genres_encoded, np.array(all_topics).reshape(-1, 1)))
 
 
 
 
77
 
78
  similarity_scores = cosine_similarity(input_features, all_features)
79
  avg_similarity = similarity_scores.mean(axis=0)
 
111
  filtered_books = [book for book in books if book["year"] and start_year <= book["year"] <= end_year]
112
  st.write(f"Found {len(filtered_books)} books between {start_year} and {end_year}.")
113
 
114
+ # Filter books with valid genres and topics
115
+ valid_books = [book for book in filtered_books if book["genre"] and book["topics"]]
116
  if not valid_books:
117
+ st.warning("No books with valid genres and topics found. Try a different query or adjust filters.")
118
  st.stop()
119
 
120
  # Display filtered books
 
125
  st.write(f"**Author:** {book['author']}")
126
  if book["cover_image"]:
127
  st.image(book["cover_image"], caption=book["title"], width=150)
128
+ st.write(f"**Genres:** {', '.join(book['genre'])}")
129
+ st.write(f"**Published Year:** {book['year']}")
130
  st.write("---")
131
 
132
  # Generate recommendations
 
138
  st.write(f"**Author:** {book['author']}")
139
  if book["cover_image"]:
140
  st.image(book["cover_image"], caption=book["title"], width=150)
141
+ st.write(f"**Genres:** {', '.join(book['genre'])}")
142
+ st.write(f"**Published Year:** {book['year']}")
143
  st.write("---")
144
 
145
  if __name__ == "__main__":
146
+ main()