Spaces:
Runtime error
Runtime error
Download src/streamlit_app.py from jayanth-2005/New: direct link, hf CLI and curl.
- Browser
- Download file 3.62 kB
-
https://huggingface.co/spaces/jayanth-2005/New/resolve/main/src/streamlit_app.py
- Command line
-
hf download hf://spaces/jayanth-2005/New/src/streamlit_app.py
-
curl -L -o streamlit_app.py https://huggingface.co/spaces/jayanth-2005/New/resolve/main/src/streamlit_app.py
3.62 kB
| import streamlit as st | |
| import pandas as pd | |
| import re | |
| import time | |
| from selenium import webdriver | |
| from selenium.webdriver.chrome.options import Options | |
| from bs4 import BeautifulSoup | |
| st.set_page_config(page_title="Faculty Scraper", layout="wide") | |
| st.title("π Universal Faculty Scraper (Clean + Smart)") | |
| EMAIL_REGEX = r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}" | |
| # -------- DRIVER -------- | |
| def get_driver(): | |
| options = Options() | |
| options.binary_location = "/usr/bin/chromium" | |
| options.add_argument("--headless") | |
| options.add_argument("--no-sandbox") | |
| options.add_argument("--disable-dev-shm-usage") | |
| driver = webdriver.Chrome(options=options) | |
| return driver | |
| # -------- NAME CLEANING -------- | |
| def name_from_email(email): | |
| name_part = email.split("@")[0] | |
| # Replace separators | |
| name_part = re.sub(r"[._]", " ", name_part) | |
| # Split camel case | |
| name_part = re.sub(r'([a-z])([A-Z])', r'\1 \2', name_part) | |
| # Remove numbers | |
| name_part = re.sub(r'\d+', '', name_part) | |
| words = name_part.split() | |
| return " ".join([w.capitalize() for w in words if len(w) > 1]) | |
| # -------- PHONE CLEANING -------- | |
| def clean_phone(text): | |
| phones = re.findall(r"\+?\d[\d\s\-]{8,15}", text) | |
| for p in phones: | |
| p_clean = p.replace(" ", "") | |
| # Reject year-like values | |
| if re.search(r"\d{4}-\d{2}", p_clean): | |
| continue | |
| digits = re.sub(r"\D", "", p_clean) | |
| # Accept only realistic phone lengths | |
| if 10 <= len(digits) <= 13: | |
| return p_clean | |
| return "Not Available" | |
| # -------- MAIN SCRAPER -------- | |
| def scrape_faculty(url): | |
| driver = get_driver() | |
| driver.get(url) | |
| time.sleep(5) | |
| soup = BeautifulSoup(driver.page_source, "html.parser") | |
| driver.quit() | |
| data = [] | |
| blocks = soup.find_all(["tr", "div", "li", "section"]) | |
| for block in blocks: | |
| text = block.get_text(" ", strip=True) | |
| if len(text) < 20: | |
| continue | |
| # -------- EMAIL -------- | |
| email_match = re.search(EMAIL_REGEX, text) | |
| if not email_match: | |
| mail = block.find("a", href=re.compile("mailto:", re.I)) | |
| if mail: | |
| email = mail.get("href").replace("mailto:", "").strip() | |
| else: | |
| continue | |
| else: | |
| email = email_match.group() | |
| # -------- NAME -------- | |
| name = None | |
| # Try headings | |
| h = block.find(["h1", "h2", "h3", "h4", "strong", "b"]) | |
| if h: | |
| name = h.get_text(strip=True) | |
| # Fallback | |
| if not name or len(name) < 3: | |
| name = name_from_email(email) | |
| # -------- PHONE -------- | |
| phone = clean_phone(text) | |
| data.append([name, email, phone]) | |
| df = pd.DataFrame(data, columns=["Name", "Email", "Phone"]) | |
| # -------- REMOVE DUPLICATES -------- | |
| df = df.drop_duplicates(subset=["Email"]) | |
| return df | |
| # -------- UI -------- | |
| url = st.text_input("π Enter Faculty Page URL") | |
| if st.button("π Scrape Data"): | |
| if not url: | |
| st.warning("Please enter a URL") | |
| else: | |
| with st.spinner("Scraping intelligently..."): | |
| df = scrape_faculty(url) | |
| if not df.empty: | |
| st.success("β Data Extracted Successfully") | |
| st.dataframe(df, use_container_width=True) | |
| csv = df.to_csv(index=False).encode("utf-8") | |
| st.download_button( | |
| "π₯ Download CSV", | |
| csv, | |
| "faculty_data.csv", | |
| "text/csv" | |
| ) | |
| else: | |
| st.error("β No data found") |