AIJobFinderAgent / main.py
jeellyfish's picture
Create main.py
0ff251f verified
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,