Spaces:
No application file
No application file
| import PyPDF2 | |
| import requests | |
| from geopy.geocoders import Nominatim | |
| import spacy | |
| from flask import Flask, request, render_template_string, flash | |
| from werkzeug.utils import secure_filename | |
| from selenium import webdriver | |
| from selenium.webdriver.chrome.service import Service | |
| from webdriver_manager.chrome import ChromeDriverManager | |
| from selenium.webdriver.common.by import By | |
| from selenium.webdriver.support.ui import WebDriverWait | |
| from selenium.webdriver.support import expected_conditions as EC | |
| import time | |
| import os | |
| import re | |
| # Load spaCy model | |
| nlp = spacy.load("en_core_web_sm") | |
| # Expanded skills list | |
| SKILLS_LIST = [ | |
| "python", "java", "sql", "javascript", "machine learning", "data analysis", "project management", | |
| "react", "aws", "docker", "git", "excel", "node.js", "typescript", "linux", "devops", "cloud", | |
| "html", "css", "agile", "scrum", "tensorflow", "pandas", "numpy", "communication", "leadership" | |
| ] | |
| # Step 1: Parse Resume with spaCy | |
| def extract_text_from_pdf(pdf_path): | |
| try: | |
| with open(pdf_path, 'rb') as file: | |
| reader = PyPDF2.PdfReader(file) | |
| text = '' | |
| for page in reader.pages: | |
| text += page.extract_text() or '' | |
| return text | |
| except Exception as e: | |
| raise ValueError(f"Failed to extract text from PDF: {e}") | |
| def extract_skills(text): | |
| doc = nlp(text.lower()) | |
| # Extract skills from predefined list and NER entities (e.g., ORG, PRODUCT) | |
| skills = set([token.text for token in doc if token.text in SKILLS_LIST]) | |
| for ent in doc.ents: | |
| if ent.label_ in ["ORG", "PRODUCT"] and ent.text.lower() in SKILLS_LIST: | |
| skills.add(ent.text.lower()) | |
| return list(skills) | |
| # Step 2: Get Location Coordinates | |
| def get_coordinates(location): | |
| try: | |
| geolocator = Nominatim(user_agent="job_search_agent") | |
| loc = geolocator.geocode(location, timeout=10) | |
| if loc: | |
| return loc.latitude, loc.longitude | |
| raise ValueError("Invalid location") | |
| except Exception as e: | |
| raise ValueError(f"Geocoding error: {e}") | |
| # Step 3: Search Jobs via API (Adzuna) | |
| def search_jobs(skills, latitude, longitude, radius=25, min_salary=None, job_type="full_time"): | |
| api_key = "YOUR_RAPIDAPI_KEY" # Replace with your RapidAPI key | |
| url = "https://adzuna.p.rapidapi.com/v1/jobs/search" | |
| querystring = { | |
| "what": " ".join(skills), | |
| "where": f"{latitude},{longitude}", | |
| "distance": radius, | |
| "max_days_old": 30, | |
| "results_per_page": 10, | |
| "contract_type": job_type | |
| } | |
| if min_salary: | |
| querystring["salary_min"] = min_salary | |
| headers = { | |
| "X-RapidAPI-Key": api_key, | |
| "X-RapidAPI-Host": "adzuna.p.rapidapi.com" | |
| } | |
| try: | |
| response = requests.get(url, headers=headers, params=querystring, timeout=10) | |
| response.raise_for_status() | |
| return response.json().get('results', []) | |
| except requests.exceptions.RequestException as e: | |
| print(f"API error: {e}") | |
| return [] | |
| # Step 4: Generate Cover Letter | |
| def generate_cover_letter(job_title, company, skills): | |
| return f""" | |
| Dear Hiring Manager, | |
| I am excited to apply for the {job_title} position at {company}. With my experience in {', '.join(skills)}, | |
| I am confident in my ability to contribute to your team. My background in these areas aligns well with | |
| the requirements of this role, and I am eager to bring my expertise to your organization. | |
| Thank you for considering my application. I look forward to discussing how I can add value to {company}. | |
| Sincerely, | |
| [Your Name] | |
| """ | |
| # Step 5: Automate Application (Tailored for Indeed) | |
| def apply_to_job(apply_url, resume_path, cover_letter): | |
| driver = webdriver.Chrome(service=Service(ChromeDriverManager().install())) | |
| driver.get(apply_url) | |
| try: | |
| WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "body"))) | |
| # Indeed-specific selectors (adjust as needed) | |
| try: | |
| # Upload resume | |
| resume_input = WebDriverWait(driver, |