File size: 2,863 Bytes
2005bec
21d54a4
4aa5719
2005bec
1f5134c
21d54a4
 
 
 
 
 
2005bec
1f5134c
 
4aa5719
1f5134c
 
4aa5719
 
 
 
1f5134c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2005bec
 
4aa5719
2005bec
 
 
 
 
 
4aa5719
 
 
2005bec
 
1f5134c
2005bec
4aa5719
2005bec
4aa5719
2005bec
4aa5719
1f5134c
 
2005bec
1f5134c
 
2005bec
1f5134c
4aa5719
 
 
1f5134c
 
4aa5719
1f5134c
4aa5719
 
 
 
 
 
 
 
1f5134c
4aa5719
1f5134c
4aa5719
1f5134c
4aa5719
 
 
 
2005bec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import spacy
import re
from difflib import get_close_matches

# Safe model load
try:
    nlp = spacy.load("en_core_web_sm")
except:
    from spacy.cli import download
    download("en_core_web_sm")
    nlp = spacy.load("en_core_web_sm")

# Common skills list (used for fuzzy matching)
common_skills = [
    "python", "sql", "java", "c++", "machine learning", "deep learning", "nlp", "tensorflow",
    "keras", "pandas", "numpy", "matplotlib", "power bi", "excel", "html", "css", "django", "flask",
    "scikit-learn", "seaborn", "fastapi", "pytorch"
]

edu_keywords = ["bachelor", "bs", "msc", "ms", "phd", "b.sc", "b.s.", "university", "institute", "college"]


def extract_skills(text):
    doc = nlp(text)
    # Extract noun phrases
    noun_phrases = set(chunk.text.lower().strip() for chunk in doc.noun_chunks)

    # Add common skills if fuzzy matched
    matched_common = set()
    words = set(text.lower().split())
    for skill in common_skills:
        if get_close_matches(skill.lower(), words, n=1, cutoff=0.85):
            matched_common.add(skill.lower())

    # Combine and clean
    all_skills = noun_phrases.union(matched_common)
    filtered = [s for s in all_skills if 2 <= len(s.split()) <= 5 and not s.startswith(("i ", "my ", "our "))]
    return list(set(filtered))


def extract_entities(text):
    doc = nlp(text)

    entities = {
        "Name": None,
        "Email": None,
        "Phone": None,
        "Skills": [],
        "Education": [],
        "Experience": [],
        "Certifications": [],
        "Projects": []
    }

    # βœ… Extract Name
    for ent in doc.ents:
        if ent.label_ == "PERSON":
            entities["Name"] = ent.text
            break

    # βœ… Extract Email & Phone
    entities["Email"] = next(iter(re.findall(r"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+", text)), None)
    entities["Phone"] = next(iter(re.findall(r"\+?\d[\d\s\-]{8,15}", text)), None)

    # βœ… Extract Skills
    entities["Skills"] = extract_skills(text)

    # βœ… Section-based parsing
    current_section = None
    lines = text.split("\n")
    for line in lines:
        clean_line = line.strip()
        if not clean_line:
            continue
        line_lower = clean_line.lower()

        if "experience" in line_lower:
            current_section = "Experience"
        elif "project" in line_lower:
            current_section = "Projects"
        elif "certification" in line_lower:
            current_section = "Certifications"
        elif any(kw in line_lower for kw in edu_keywords):
            entities["Education"].append(clean_line)
        elif current_section:
            entities[current_section].append(clean_line)

    # βœ… Deduplicate list entries
    for key in entities:
        if isinstance(entities[key], list):
            entities[key] = list(set(entities[key]))

    return entities