{"id":234,"date":"2025-11-20T09:10:37","date_gmt":"2025-11-20T09:10:37","guid":{"rendered":"https:\/\/codetypingpro.com\/?p=234"},"modified":"2025-11-20T09:10:37","modified_gmt":"2025-11-20T09:10:37","slug":"31-real-world-python-projects-ai-resume-screener","status":"publish","type":"post","link":"https:\/\/codetypingpro.com\/?p=234","title":{"rendered":"31 &#8211; Real-World Python Projects &#8211; AI Resume Screener"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\"><\/h1>\n\n\n\n<p><strong>Focus Areas:<\/strong> NLP, Machine Learning, Automation<br><strong>Difficulty:<\/strong> Intermediate\u2013Advanced<br><strong>Real-World Use:<\/strong> HR teams receive hundreds of resumes. An AI Resume Screener automatically parses resumes, extracts skills, ranks candidates, and generates a shortlist.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83c\udf1f <strong>What You Will Build<\/strong><\/h1>\n\n\n\n<p>A Python program that:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Reads multiple resumes (PDF\/DOCX\/TXT)<\/strong><\/li>\n\n\n\n<li><strong>Extracts candidate information<\/strong><\/li>\n\n\n\n<li><strong>Extracts skills using NLP<\/strong><\/li>\n\n\n\n<li><strong>Matches resume skills with job description skills<\/strong><\/li>\n\n\n\n<li><strong>Calculates a match score (0\u2013100%)<\/strong><\/li>\n\n\n\n<li><strong>Sorts and displays best candidates<\/strong><\/li>\n\n\n\n<li><strong>Exports results to CSV<\/strong><\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83e\udde0 <strong>Tech Stack<\/strong><\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>python-docx<\/code> (for DOCX reading)<\/li>\n\n\n\n<li><code>PyPDF2<\/code> (for PDF reading)<\/li>\n\n\n\n<li><code>spaCy<\/code> (NLP for skill extraction)<\/li>\n\n\n\n<li><code>pandas<\/code><\/li>\n\n\n\n<li><code>re<\/code> (regex for cleaning)<\/li>\n\n\n\n<li><code>os<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83d\udcc1 Folder Structure<\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>AI_Resume_Screener\/\n\u2502\u2500\u2500 resumes\/\n\u2502     \u251c\u2500\u2500 resume1.pdf\n\u2502     \u251c\u2500\u2500 resume2.docx\n\u2502\u2500\u2500 job_description.txt\n\u2502\u2500\u2500 screener.py\n\u2502\u2500\u2500 skills_library.txt\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83d\udcd8 <strong>skills_library.txt (example)<\/strong><\/h1>\n\n\n\n<p>These skills will be matched:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python\nmachine learning\nexcel\npower bi\ncommunication\nsql\ncustomer service\njava\nreact\nsalesforce\ndata analysis\n<\/code><\/pre>\n\n\n\n<p>You can add more.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83d\udcc4 <strong>job_description.txt (example)<\/strong><\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>We are hiring a Senior Customer Service Representative.\nStrong communication, client handling, CRM knowledge, and problem-solving required.\nExperience with Excel and email support preferred.\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83e\udde0 <strong>Core Python Program: <code>screener.py<\/code><\/strong><\/h1>\n\n\n\n<pre class=\"wp-block-code\"><code>import os\nimport re\nimport PyPDF2\nimport docx\nimport spacy\nimport pandas as pd\n\n# Load NLP model\nnlp = spacy.load(\"en_core_web_sm\")\n\n# Load skills library\nwith open(\"skills_library.txt\", \"r\") as f:\n    SKILL_LIST = &#91;skill.strip().lower() for skill in f.readlines()]\n\n# Clean text\ndef clean_text(text):\n    text = text.lower()\n    text = re.sub(r'&#91;^a-zA-Z0-9\\s]', ' ', text)\n    text = re.sub(r'\\s+', ' ', text)\n    return text\n\n# Extract text from PDF\ndef read_pdf(path):\n    text = \"\"\n    with open(path, \"rb\") as pdf:\n        reader = PyPDF2.PdfReader(pdf)\n        for page in reader.pages:\n            text += page.extract_text() + \" \"\n    return text\n\n# Extract text from DOCX\ndef read_docx(path):\n    doc = docx.Document(path)\n    return \" \".join(&#91;para.text for para in doc.paragraphs])\n\n# Read any resume\ndef extract_text(path):\n    if path.endswith(\".pdf\"):\n        return read_pdf(path)\n    elif path.endswith(\".docx\"):\n        return read_docx(path)\n    elif path.endswith(\".txt\"):\n        return open(path, \"r\").read()\n    return \"\"\n\n# Extract skills from resume\ndef extract_skills(text):\n    words = set(clean_text(text).split())\n    found = &#91;skill for skill in SKILL_LIST if skill in words]\n    return found\n\n# Calculate match score\ndef calculate_match(resume_skills, jd_skills):\n    score = (len(set(resume_skills) &amp; set(jd_skills)) \/ len(jd_skills)) * 100\n    return round(score, 2)\n\n# Load job description skills using NLP\ndef get_jd_skills():\n    with open(\"job_description.txt\", \"r\") as f:\n        jd_text = clean_text(f.read())\n    jd_words = jd_text.split()\n    return &#91;skill for skill in SKILL_LIST if skill in jd_words]\n\n# Main screening function\ndef screen_resumes():\n    jd_skills = get_jd_skills()\n    results = &#91;]\n\n    for file in os.listdir(\"resumes\"):\n        path = os.path.join(\"resumes\", file)\n        text = extract_text(path)\n        skills = extract_skills(text)\n        score = calculate_match(skills, jd_skills)\n\n        results.append({\n            \"Resume Name\": file,\n            \"Skills Found\": \", \".join(skills),\n            \"Match Score\": score\n        })\n\n    df = pd.DataFrame(results)\n    df = df.sort_values(by=\"Match Score\", ascending=False)\n    df.to_csv(\"screening_results.csv\", index=False)\n\n    print(df)\n    print(\"\\nResults saved to screening_results.csv\")\n\nscreen_resumes()\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83c\udfaf <strong>Output Example<\/strong><\/h1>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Resume<\/th><th>Skills Found<\/th><th>Match Score<\/th><\/tr><\/thead><tbody><tr><td>resume3.pdf<\/td><td>communication, excel, crm<\/td><td>85<\/td><\/tr><tr><td>resume1.docx<\/td><td>customer service, excel<\/td><td>70<\/td><\/tr><tr><td>resume2.pdf<\/td><td>python<\/td><td>10<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83c\udfc6 Real-World Improvements<\/h1>\n\n\n\n<p>Add these once basic version works:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 Resume Ranking Model<\/h3>\n\n\n\n<p>Use TF-IDF + cosine similarity.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 Named Entity Recognition<\/h3>\n\n\n\n<p>Extract:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Name<\/li>\n\n\n\n<li>Email<\/li>\n\n\n\n<li>Phone<\/li>\n\n\n\n<li>Experience years<\/li>\n\n\n\n<li>Education<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 Streamlit Web App<\/h3>\n\n\n\n<p>Upload resume \u2192 Get score instantly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 HR Dashboard<\/h3>\n\n\n\n<p>Graphs for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>skill distribution<\/li>\n\n\n\n<li>top candidates<\/li>\n\n\n\n<li>missing skill analysis<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u2714 Multi-Job Screening<\/h3>\n\n\n\n<p>Screen resumes for 50 different roles.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Focus Areas: NLP, Machine Learning, AutomationDifficulty: Intermediate\u2013AdvancedReal-World Use: HR teams receive hundreds of resumes. An AI Resume Screener automatically parses resumes, extracts skills, ranks candidates, and generates a shortlist. \ud83c\udf1f What You Will Build A Python program that: \ud83e\udde0 Tech Stack \ud83d\udcc1 Folder Structure \ud83d\udcd8 skills_library.txt (example) These skills will be matched: You can add [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-234","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/posts\/234","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=234"}],"version-history":[{"count":1,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/posts\/234\/revisions"}],"predecessor-version":[{"id":235,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=\/wp\/v2\/posts\/234\/revisions\/235"}],"wp:attachment":[{"href":"https:\/\/codetypingpro.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codetypingpro.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}