NewsMitra / News_app.py
NeonSamurai's picture
Update News_app.py
c6426cb verified
import streamlit as st
import numpy as np
import re
import emoji
import nltk
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
# Download necessary resources
nltk.download('punkt_tab')
nltk.download('stopwords')
nltk.download('wordnet')
import tensorflow
import keras
from keras.utils import pad_sequences
import pickle
import base64
# Streamlit UI
st.set_page_config(page_title="News Category Classifier", page_icon="📰", layout="centered")
def set_background(local_image_path):
with open(local_image_path, "rb") as image_file:
encoded_string = base64.b64encode(image_file.read()).decode()
bg_image_style = f"""
<style>
.stApp {{
background-image: url(data:image/{"png"};base64,{encoded_string});
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
}}
</style>
"""
st.markdown(bg_image_style, unsafe_allow_html=True)
# Call this function with the path to your image
set_background(r"Images/bkg4.jpg") # Replace with the actual image path
# Initialize stopwords and lemmatizer
stop_words = set(stopwords.words('english')).union({"pm"})
lemmatizer = WordNetLemmatizer()
def pre_process(x):
x = x.lower()
x = re.sub("<.*?>", "", x)
x = re.sub("http[s]?://.+?\\S+", "", x)
x = re.sub("[@#].+?\\S", "", x)
x = re.sub(r"\\_+", " ", x)
x = re.sub("^[A-Za-z.].*\\s-\\s", "", x)
x = emoji.demojize(x)
x = re.sub(":.*?:", "", x)
x = re.sub("[^a-zA-Z0-9\\s_]", "", x)
words = word_tokenize(x)
words = [word for word in words if word not in stop_words]
x = " ".join([lemmatizer.lemmatize(word) for word in words])
return x
@st.cache_resource
def load_model():
model_path = r"new_classifier_m6_acc84.keras"
vectorizer_path = r"vec_text_m6.keras"
label_encoder_path = r"label_encoder_m6.pkl"
model = keras.models.load_model(model_path)
vectorizer = keras.models.load_model(vectorizer_path)
with open(label_encoder_path, 'rb') as file:
label_encoder = pickle.load(file)
return model, vectorizer, label_encoder
model, vectorizer, label_encoder = load_model()
def predict_category(text):
processed_text = [pre_process(text)]
text_vectorized = pad_sequences(vectorizer(processed_text).numpy().tolist(), padding='pre', maxlen=82)
prediction = model.predict(text_vectorized)
category_idx = np.argmax(prediction, axis=1)[0]
return label_encoder.inverse_transform([category_idx])[0]
# UI
st.markdown(
"""
<style>
body {
background-color: #f8f9fa;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.title {
color: #ffffff;
font-size: 2.4em;
text-align: center;
font-weight: 700;
margin-bottom: 15px;
text-transform: uppercase;
text-shadow: 2px 2px 8px rgba(0, 0, 0, 1.0);
padding: 10px;
}
.subtitle {
color: #ffff;
font-size: 1.3em;
text-align: center;
font-weight: 600;
margin-bottom: 15px;
text-shadow: 1px 1px 6px rgba(0, 0, 0, 1.0);
padding: 5px;
}
.classify-button {
background-color: #3498db;
color: white;
font-size: 1.2em;
padding: 12px 24px;
border: none;
border-radius: 8px;
cursor: pointer;
display: block;
margin: 20px auto;
transition: 0.3s;
}
.classify-button:hover {
background-color: #2980b9;
}
.result-box {
background: linear-gradient(135deg, #6284FF 30%, #FF0000 70%); /* Blue to Red */
padding: 20px;
border-radius: 10px;
text-align: center;
margin-top: 30px;
position: relative;
overflow: hidden;
border: 2px solid transparent;
background-clip: padding-box, border-box;
border-image: linear-gradient(135deg, #6284FF 30%, #FF0000 70%);
border-image-slice: 0;
transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
}
/* Hover Effect */
.result-box:hover {
transform: scale(1.05);
box-shadow: 0px 10px 30px rgba(98, 132, 255, 0.8),
0px 10px 30px rgba(255, 0, 0, 0.8);
}
/* Light Reflection for Glossy Look */
.result-box::before {
content: "";
position: absolute;
top: -100%;
left: -100%;
width: 250%;
height: 250%;
background: radial-gradient(circle, rgba(255, 255, 255, 0.4) 10%, rgba(255, 255, 255, 0) 70%);
opacity: 0.6;
transform: rotate(-25deg);
animation: shine 3s infinite linear;
}
/* Shimmer Animation */
@keyframes shine {
0% { top: -150%; left: -150%; }
100% { top: 150%; left: 150%; }
}
.result-text {
font-size: 1.8em;
color: #ffffff; /* Darker color for better visibility */
font-weight: 900;
text-shadow: 3px 3px 10px rgba(0, 0, 0, 0.5);
animation: fadeIn 0.8s ease-in-out;
}
.warning-box {
background: linear-gradient(135deg, rgba(255, 77, 77, 0.8), rgba(255, 165, 0, 0.7)); /* Smooth red-orange gradient */
padding: 18px;
border-radius: 10px;
text-align: center;
color: white;
font-weight: bold;
font-size: 1.2em;
text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6);
margin-top: 25px;
border: 2px solid rgba(255, 77, 77, 0.9);
box-shadow: 0px 8px 15px rgba(255, 0, 0, 0.4);
transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
}
</style>
""",
unsafe_allow_html=True
)
st.markdown("<div class='title'>📰 News Classifier</div>", unsafe_allow_html=True)
st.markdown("<div class='subtitle'>"
"Enter a news headline or article snippet to analyze its category."
"</div>", unsafe_allow_html=True)
user_input = st.text_area("Enter text here:", height=150, key="text_input",
label_visibility="collapsed", placeholder="Type your news text here...",
help="Enter news article or headline")
if st.button("Analyze 🏷️", key="classify_button", on_click=None, help="Click to analyze the entered text"):
if user_input.strip():
category = predict_category(user_input)
st.markdown(f"<div class='result-box'><span class='result-text'>🗂️ Predicted Category: <strong>{category}</strong></span></div>", unsafe_allow_html=True)
else:
st.markdown("<div class='warning-box'>⚠️ Please enter some text to analyze.</div>", unsafe_allow_html=True)