Spaces:
Running
Running
| import requests | |
| import pandas as pd | |
| from io import BytesIO | |
| from bs4 import BeautifulSoup | |
| import streamlit as st | |
| # Streamlit app title | |
| st.title("Visa Application Status Checker") | |
| # URL of the website to scrape | |
| url = "https://www.ireland.ie/en/india/newdelhi/services/visas/processing-times-and-decisions/" | |
| # Headers to mimic a browser request | |
| headers = { | |
| "User-Agent": ( | |
| "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " | |
| "(KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" | |
| ) | |
| } | |
| # Step 1: Function to fetch and cache the .ods file | |
| def fetch_ods_file(): | |
| response = requests.get(url, headers=headers) | |
| if response.status_code == 200: | |
| soup = BeautifulSoup(response.content, 'html.parser') | |
| # Find all anchor tags | |
| links = soup.find_all('a') | |
| # Search for the link containing the specific text | |
| file_url = None | |
| for link in links: | |
| link_text = link.get_text(strip=True) | |
| if "Visa decisions made from 1 January 2024 to" in link_text: | |
| file_url = link.get('href') | |
| file_name = link_text | |
| break | |
| if file_url: | |
| # Make the link absolute if it is relative | |
| if not file_url.startswith('http'): | |
| file_url = requests.compat.urljoin(url, file_url) | |
| file_response = requests.get(file_url, headers=headers) | |
| if file_response.status_code == 200: | |
| return BytesIO(file_response.content), file_name | |
| else: | |
| st.error(f"Failed to download the file. Status code: {file_response.status_code}") | |
| else: | |
| st.error("The specified link was not found.") | |
| else: | |
| st.error(f"Failed to retrieve the webpage. Status code: {response.status_code}") | |
| return None, None | |
| # Step 2: Fetch the cached .ods file | |
| ods_file, cached_file_name = fetch_ods_file() | |
| if ods_file: | |
| try: | |
| # Step 3: Read the .ods file into a DataFrame | |
| df = pd.read_excel(ods_file, engine='odf') | |
| # Clean up the DataFrame by dropping unnecessary columns | |
| df.drop(columns=["Unnamed: 0", "Unnamed: 1"], inplace=True, errors='ignore') | |
| # Drop empty rows and reset index | |
| df.dropna(how='all', inplace=True) | |
| df.reset_index(drop=True, inplace=True) | |
| # Identify the header row and reformat DataFrame | |
| for idx, row in df.iterrows(): | |
| if row['Unnamed: 2'] == 'Application Number' and row['Unnamed: 3'] == 'Decision': | |
| df.columns = ['Application Number', 'Decision'] | |
| df = df.iloc[idx + 1:] # Skip the header row | |
| break | |
| # Reset index after cleaning | |
| df.reset_index(drop=True, inplace=True) | |
| # Convert "Application Number" to string for consistency | |
| df['Application Number'] = df['Application Number'].astype(str) | |
| # Step 4: Get user input for application number using Streamlit | |
| user_input = st.text_input("Enter your Application Number (including IRL if applicable):") | |
| if user_input: | |
| # Input validation logic | |
| if "irl" in user_input.lower(): | |
| try: | |
| application_number = int("".join(filter(str.isdigit, user_input.lower().split("irl")[-1]))) | |
| if len(str(application_number)) < 8: | |
| st.warning("Please enter a valid application number with at least 8 digits after IRL.") | |
| st.stop() | |
| except ValueError: | |
| st.error("Invalid input after IRL. Please enter only digits.") | |
| st.stop() | |
| else: | |
| if not user_input.isdigit() or len(user_input) < 8: | |
| st.warning("Please enter at least 8 digits for your VISA application number.") | |
| st.stop() | |
| application_number = int(user_input) | |
| # Check if the application number exists in the DataFrame | |
| result = df[df['Application Number'] == str(application_number)] | |
| if not result.empty: | |
| decision = result.iloc[0]['Decision'] | |
| st.success(f"Application Number: **{application_number}**\n\nDecision: **{decision}**") | |
| else: | |
| st.warning(f"No record found for Application Number: {application_number}.") | |
| # Find the nearest application numbers | |
| df['Application Number'] = df['Application Number'].astype(int) | |
| df['Difference'] = abs(df['Application Number'] - application_number) | |
| nearest_records = df.nsmallest(2, 'Difference') | |
| if not nearest_records.empty: | |
| st.subheader("Nearest Application Numbers") | |
| st.table(nearest_records[['Application Number', 'Decision', 'Difference']]) | |
| else: | |
| st.info("No nearest application numbers found.") | |
| except Exception as e: | |
| st.error(f"Error reading the .ods file: {e}") | |
| else: | |
| st.error("No file data available.") | |