Spaces:
Paused
Paused
| import streamlit as st | |
| import wikipedia | |
| import re | |
| from functools import lru_cache | |
| import time | |
| # Configure page | |
| st.set_page_config( | |
| page_title="Car Categories Explorer", | |
| layout="centered", | |
| page_icon="π" | |
| ) | |
| # Custom CSS for better styling | |
| st.markdown(""" | |
| <style> | |
| .main-header { | |
| text-align: center; | |
| color: #2E86AB; | |
| margin-bottom: 2rem; | |
| } | |
| .car-card { | |
| border: 1px solid #ddd; | |
| border-radius: 10px; | |
| padding: 1rem; | |
| margin: 1rem 0; | |
| background-color: #f9f9f9; | |
| } | |
| .error-message { | |
| color: #d32f2f; | |
| font-weight: bold; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| st.markdown('<h1 class="main-header">π Car Categories Explorer</h1>', unsafe_allow_html=True) | |
| # --- Initialize session state --- | |
| if 'search_history' not in st.session_state: | |
| st.session_state.search_history = [] | |
| if 'favorites' not in st.session_state: | |
| st.session_state.favorites = [] | |
| # --- Sidebar Configuration --- | |
| st.sidebar.header("π Car Categories") | |
| # Category selection with descriptions | |
| categories = { | |
| "Vintage Cars": { | |
| "description": "Classic automobiles from bygone eras", | |
| "examples": ["Ford Model T", "Jaguar E-Type", "Rolls-Royce Silver Ghost", "Chevrolet Bel Air"] | |
| }, | |
| "Trending Cars": { | |
| "description": "Popular modern vehicles", | |
| "examples": ["Tesla Model S", "Hyundai Exter", "Mahindra Thar", "Toyota Camry"] | |
| }, | |
| "SUVs": { | |
| "description": "Sport Utility Vehicles", | |
| "examples": ["Tata Harrier", "Jeep Compass", "Hyundai Creta", "Ford EcoSport"] | |
| }, | |
| "Electric Cars": { | |
| "description": "Eco-friendly electric vehicles", | |
| "examples": ["Tesla Model 3", "Nissan Leaf", "Tata Nexon EV", "BMW i3"] | |
| } | |
| } | |
| category = st.sidebar.selectbox("Choose a Category", list(categories.keys())) | |
| # Display category info | |
| st.sidebar.markdown(f"**{categories[category]['description']}**") | |
| st.sidebar.markdown("#### π‘ Example Cars:") | |
| for example in categories[category]['examples']: | |
| st.sidebar.markdown(f"- {example}") | |
| # Search history in sidebar | |
| if st.session_state.search_history: | |
| st.sidebar.markdown("#### π Recent Searches:") | |
| for item in st.session_state.search_history[-5:]: # Show last 5 searches | |
| if st.sidebar.button(f"π {item}", key=f"history_{item}"): | |
| st.session_state.current_search = item | |
| # --- Caching Functions --- | |
| def cached_wikipedia_search(query): | |
| """Cache Wikipedia search results to avoid repeated API calls""" | |
| try: | |
| if len(query.strip()) < 3: | |
| return [] | |
| return wikipedia.search(query, results=10) | |
| except Exception as e: | |
| st.error(f"Search error: {str(e)}") | |
| return [] | |
| def cached_wikipedia_page(car_name): | |
| """Cache Wikipedia page content""" | |
| try: | |
| # Set language to English for better car results | |
| wikipedia.set_lang("en") | |
| page = wikipedia.page(car_name) | |
| summary = wikipedia.summary(car_name, sentences=8) | |
| # Clean summary | |
| clean_summary = re.sub(r'\[\d+\]', '', summary) | |
| clean_summary = re.sub(r'\s+', ' ', clean_summary).strip() | |
| # Get first valid image | |
| image_url = None | |
| if page.images: | |
| for img in page.images[:3]: # Try first 3 images | |
| if any(ext in img.lower() for ext in ['.jpg', '.jpeg', '.png', '.gif']): | |
| image_url = img | |
| break | |
| return clean_summary, image_url, page.url, page.title | |
| except wikipedia.exceptions.DisambiguationError as e: | |
| # Handle disambiguation by trying the first option | |
| try: | |
| return cached_wikipedia_page(e.options[0]) | |
| except: | |
| return None, None, None, None | |
| except wikipedia.exceptions.PageError: | |
| return None, None, None, None | |
| except Exception as e: | |
| st.error(f"Error fetching page: {str(e)}") | |
| return None, None, None, None | |
| def smart_search_cars(query, category): | |
| """Enhanced search with category-specific terms""" | |
| if not query.strip(): | |
| return [] | |
| # Add category context to search | |
| category_terms = { | |
| "Vintage Cars": ["vintage", "classic", "antique"], | |
| "Trending Cars": ["2023", "2024", "new", "latest"], | |
| "SUVs": ["SUV", "crossover"], | |
| "Electric Cars": ["electric", "EV", "hybrid"] | |
| } | |
| # Try exact search first | |
| results = cached_wikipedia_search(query) | |
| # If few results, try with category context | |
| if len(results) < 3: | |
| enhanced_query = f"{query} {category_terms.get(category, [''])[0]}" | |
| enhanced_results = cached_wikipedia_search(enhanced_query) | |
| results.extend([r for r in enhanced_results if r not in results]) | |
| return results[:10] # Limit to 10 results | |
| # --- Main Search Interface --- | |
| st.markdown(f"### π Search Cars in {category}") | |
| # Search input with debouncing | |
| search_container = st.container() | |
| with search_container: | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| query = st.text_input( | |
| "Type a Car Name", | |
| placeholder="e.g., Tesla Model S, Ford Mustang", | |
| key="search_input" | |
| ) | |
| with col2: | |
| st.markdown("<br>", unsafe_allow_html=True) # Add spacing | |
| clear_btn = st.button("ποΈ Clear", help="Clear search") | |
| if clear_btn: | |
| st.rerun() | |
| # Live suggestions with improved logic | |
| suggestions = [] | |
| if query and len(query.strip()) >= 3: | |
| with st.spinner("Searching..."): | |
| suggestions = smart_search_cars(query, category) | |
| # Display suggestions | |
| if suggestions: | |
| selected_car = st.selectbox("π Select from suggestions:", [""] + suggestions) | |
| else: | |
| selected_car = None | |
| # Search button | |
| submit_btn = st.button("π Get Car Information", type="primary") | |
| # --- Display Results --- | |
| if submit_btn and selected_car: | |
| # Add to search history | |
| if selected_car not in st.session_state.search_history: | |
| st.session_state.search_history.append(selected_car) | |
| st.markdown("---") | |
| # Progress bar for better UX | |
| progress_bar = st.progress(0) | |
| status_text = st.empty() | |
| status_text.text("Fetching car information...") | |
| progress_bar.progress(25) | |
| # Fetch car information | |
| summary, image_url, page_url, page_title = cached_wikipedia_page(selected_car) | |
| progress_bar.progress(75) | |
| if summary: | |
| # Display main car info | |
| st.markdown(f'<div class="car-card">', unsafe_allow_html=True) | |
| # Title with favorite button | |
| col1, col2 = st.columns([4, 1]) | |
| with col1: | |
| st.subheader(f"π {page_title or selected_car}") | |
| with col2: | |
| if st.button("β Favorite", key=f"fav_{selected_car}"): | |
| if selected_car not in st.session_state.favorites: | |
| st.session_state.favorites.append(selected_car) | |
| st.success("Added to favorites!") | |
| # Display image and summary | |
| if image_url: | |
| try: | |
| st.image(image_url, caption=page_title or selected_car, use_column_width=True) | |
| except: | |
| st.info("π· Image could not be loaded") | |
| st.write(summary) | |
| # Links and actions | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| if page_url: | |
| st.markdown(f"[π Wikipedia Page]({page_url})") | |
| with col2: | |
| if st.button("π Search Similar", key=f"similar_{selected_car}"): | |
| # Extract brand name for similar search | |
| brand = selected_car.split()[0] | |
| similar_results = cached_wikipedia_search(f"{brand} cars") | |
| if similar_results: | |
| st.info(f"Similar cars: {', '.join(similar_results[:3])}") | |
| with col3: | |
| if st.button("π€ Share", key=f"share_{selected_car}"): | |
| st.code(f"Check out this car: {selected_car}\n{page_url}") | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| progress_bar.progress(100) | |
| status_text.text("β Information loaded successfully!") | |
| # Clear progress indicators after 2 seconds | |
| time.sleep(1) | |
| progress_bar.empty() | |
| status_text.empty() | |
| else: | |
| progress_bar.progress(100) | |
| status_text.empty() | |
| progress_bar.empty() | |
| st.markdown('<div class="error-message">β No information found for this car.</div>', unsafe_allow_html=True) | |
| st.info("π‘ Try searching with a different spelling or check the suggestions above.") | |
| # --- Favorites Section --- | |
| if st.session_state.favorites: | |
| st.markdown("---") | |
| st.subheader("β Your Favorite Cars") | |
| for i, fav in enumerate(st.session_state.favorites): | |
| col1, col2 = st.columns([4, 1]) | |
| with col1: | |
| st.write(f"π {fav}") | |
| with col2: | |
| if st.button("ποΈ", key=f"remove_{i}", help="Remove from favorites"): | |
| st.session_state.favorites.remove(fav) | |
| st.rerun() | |
| # --- Footer --- | |
| st.markdown("---") | |
| st.markdown(""" | |
| <div style='text-align: center; color: #666;'> | |
| <p>π Car Categories Explorer | Powered by Wikipedia API</p> | |
| <p><small>Data provided by Wikipedia. Images and content are subject to their respective licenses.</small></p> | |
| </div> | |
| """, unsafe_allow_html=True) |