<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ multiprocessing - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ multiprocessing - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 25 Jun 2026 04:44:08 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/multiprocessing/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Résumé Screening System Using Python and Multiprocessing ]]>
                </title>
                <description>
                    <![CDATA[ Hiring the right candidate starts with one time-consuming task: screening résumés. If you’ve ever posted a job opening, you know the pain of hundreds of applications in your inbox, leaving you to spend hours reviewing each résumé manually. In this ar... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/python-resume-screening-system/</link>
                <guid isPermaLink="false">698614754058fffacf721cc8</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ streamlit ]]>
                    </category>
                
                    <category>
                        <![CDATA[ multiprocessing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ automation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ pdf ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Abdul Talha ]]>
                </dc:creator>
                <pubDate>Fri, 06 Feb 2026 16:19:01 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770331777028/1ac80e66-cf22-4160-8812-ea917384cd3f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hiring the right candidate starts with one time-consuming task: screening résumés. If you’ve ever posted a job opening, you know the pain of hundreds of applications in your inbox, leaving you to spend hours reviewing each résumé manually.</p>
<p>In this article, you’ll build a résumé screening system using pure Python, focusing on core programming concepts and the power of multiprocessing. You’ll create a custom system that automates the evaluation process by transforming unstructured résumé documents into a ranked leaderboard.</p>
<p>By the end of this guide, you will:</p>
<ul>
<li><p>Parse documents by extracting text from PDF and DOCX résumés using Python</p>
</li>
<li><p>Extract information by identifying skills and keywords from résumé content</p>
</li>
<li><p>Design a scoring algorithm using weighted logic to rank candidates objectively</p>
</li>
<li><p>Build a web interface using Streamlit</p>
</li>
<li><p>Deploy the application on Streamlit Cloud for public access</p>
</li>
</ul>
<p>By following this tutorial, you’ll build a tool capable of processing hundreds of résumés in seconds.</p>
<p>Here’s the source code: <a target="_blank" href="https://github.com/abdultalha0862/Resume_Parser_Project">GitHub Repository</a></p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-project-overview">Project Overview</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-the-system-works">How the System Works</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-system-architecture">System Architecture</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-project-structure">Project Structure</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-1-set-up-the-project">Step 1: Set Up the Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-build-the-resume-parser">Step 2: Build the Résumé Parser</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-build-the-keyword-extractor">Step 3: Build the Keyword Extractor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-implement-the-scoring-engine">Step 4: Implement the Scoring Engine</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-build-the-web-interface">Step 5: Build the Web Interface</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-test-the-system">Step 6: Test the System</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-7-deploy-the-application">Step 7: Deploy the Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along with this tutorial, you should have:</p>
<ul>
<li><p>Basic knowledge of Python (functions, loops, dictionaries)</p>
</li>
<li><p>Python 3.8 or higher installed</p>
</li>
<li><p>Familiarity with installing packages using <code>pip</code></p>
</li>
<li><p>A code editor such as VS Code, PyCharm, or any editor you prefer</p>
</li>
</ul>
<h2 id="heading-project-overview">Project Overview</h2>
<p>In this guide, you’ll develop a system that takes a folder of résumés and a Job Description (JD) as input. The system processes each résumé, extracts relevant information, and calculates a score based on how well the candidate matches the job requirements.</p>
<h2 id="heading-how-the-system-works">How the System Works</h2>
<p>The project consists of four core components:</p>
<ul>
<li><p><strong>Résumé Parser</strong>: Reads PDF and DOCX files and extracts text</p>
</li>
<li><p><strong>JD Parser</strong>: Analyses the job description to identify required skills</p>
</li>
<li><p><strong>Keyword Extractor</strong>: Matches résumé content against a skills taxonomy</p>
</li>
<li><p><strong>Scoring Engine</strong>: Ranks candidates using a weighted algorithm</p>
</li>
</ul>
<h3 id="heading-scoring-formula">Scoring Formula</h3>
<p>Here’s the scoring formula we’ll use:</p>
<pre><code class="lang-plaintext">Total Score =
(Required Skills × 50%) +
(Preferred Skills × 25%) +
(Experience × 15%) +
(Keywords × 10%)
</code></pre>
<p>This approach ensures that essential skills carry more weight than secondary keywords.</p>
<h3 id="heading-how-this-approach-helps-reduce-bias">How This Approach Helps Reduce Bias</h3>
<p>This system evaluates résumés using predefined criteria instead of subjective judgment. Each résumé is scored based on the same set of required skills, preferred skills, experience indicators, and keywords.</p>
<p>Because all candidates are evaluated using the same weighted formula, personal factors such as writing style, formatting, or unconscious preferences don’t influence the ranking. The scoring logic focuses only on how closely a résumé matches the job requirements.</p>
<p>By normalising the evaluation process, the system promotes more consistent and objective screening, which helps reduce bias during the initial résumé review stage.</p>
<h2 id="heading-system-architecture">System Architecture</h2>
<pre><code class="lang-plaintext">Input                    Processing                     Output
─────                    ──────────                     ──────

Résumés ──► Résumé Parser ──► Keyword Extractor ──┐
(PDF/DOCX)                                        │
                                                  ├──► Scoring Engine ──► Ranked Results
Job Description ──► JD Parser ────────────────────┘
(TXT/PDF)
</code></pre>
<p>The system follows a simple input–process–output flow.</p>
<p>Résumés and the job description are provided as inputs. The Résumé Parser extracts text from each résumé, while the JD Parser identifies required and preferred skills from the job description.</p>
<p>The extracted résumé text is then passed to the Keyword Extractor, which matches skills and keywords using a predefined taxonomy.</p>
<p>Finally, the Scoring Engine applies a weighted formula to calculate a score for each candidate and outputs a ranked list of résumés.</p>
<h2 id="heading-project-structure">Project Structure</h2>
<pre><code class="lang-plaintext">resume_screening_system/
├── app.py                    # Streamlit web interface
├── main.py                   # Command-line interface
├── parsers/
│   ├── resume_parser.py      # PDF/DOCX text extraction
│   └── jd_parser.py          # Job description parsing
├── extractors/
│   └── keyword_extractor.py  # Skills and experience extraction
├── matcher/
│   └── scorer.py             # Scoring algorithm
├── data/
│   ├── config.json           # Scoring weights
│   └── skills_taxonomy.json  # Skills database
└── requirements.txt          # Dependencies
</code></pre>
<p>The project is organised into clear, modular directories. Parsing logic, keyword extraction, and scoring are separated into their own folders, while configuration files and data are kept isolated. This structure keeps the codebase easy to navigate, maintain, and extend.</p>
<h2 id="heading-step-1-set-up-the-project">Step 1: Set Up the Project</h2>
<p>Create the folder structure and set up a virtual environment:</p>
<pre><code class="lang-bash">mkdir resume_screening_system
<span class="hljs-built_in">cd</span> resume_screening_system
mkdir parsers extractors matcher data input output
python -m venv venv
</code></pre>
<p>Then go ahead and activate the virtual environment:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Windows</span>
<span class="hljs-built_in">source</span> venv/Scripts/activate

<span class="hljs-comment"># macOS / Linux</span>
<span class="hljs-built_in">source</span> venv/bin/activate
</code></pre>
<p>Install the required dependencies like this:</p>
<pre><code class="lang-bash">pip install PyPDF2 python-docx streamlit pandas
</code></pre>
<h2 id="heading-step-2-build-the-resume-parser">Step 2: Build the Résumé Parser</h2>
<p>The résumé parser handles different file formats by using a separate extraction method for each type.</p>
<p>For PDF files, the parser opens the document page by page and extracts text from each page using a PDF reader. The extracted text is combined into a single string for further processing.</p>
<p>For DOCX files, the parser reads each paragraph in the document and joins the paragraph text into one block. This ensures consistent text output regardless of the résumé format.</p>
<p>By combining all résumés into plain text, the parser allows components such as keyword extraction and scoring to work efficiently.</p>
<p><strong>File:</strong> <code>parsers/resume_parser.py</code></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_extract_pdf</span>(<span class="hljs-params">self, file_path: Path</span>) -&gt; str:</span>
    text = <span class="hljs-string">""</span>
    <span class="hljs-keyword">with</span> open(file_path, <span class="hljs-string">"rb"</span>) <span class="hljs-keyword">as</span> file:
        pdf_reader = PyPDF2.PdfReader(file)
        <span class="hljs-keyword">for</span> page <span class="hljs-keyword">in</span> pdf_reader.pages:
            page_text = page.extract_text()
            <span class="hljs-keyword">if</span> page_text:
                text += page_text + <span class="hljs-string">"\\n"</span>
    <span class="hljs-keyword">return</span> text.strip()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">_extract_docx</span>(<span class="hljs-params">self, file_path: Path</span>) -&gt; str:</span>
    <span class="hljs-keyword">from</span> docx <span class="hljs-keyword">import</span> Document
    doc = Document(file_path)
    <span class="hljs-keyword">return</span> <span class="hljs-string">"\\n"</span>.join(
        para.text <span class="hljs-keyword">for</span> para <span class="hljs-keyword">in</span> doc.paragraphs
    ).strip()
</code></pre>
<h2 id="heading-step-3-build-the-keyword-extractor">Step 3: Build the Keyword Extractor</h2>
<p>This project uses a résumé dataset from <a target="_blank" href="https://www.kaggle.com/datasets/snehaanbhawal/resume-dataset">Kaggle</a> to ensure the logic works with real-world professional data. The keyword extractor identifies skills by scanning the résumé text.</p>
<p>The résumé text is first converted to lowercase so that matching is case-insensitive. A predefined skills taxonomy stores each skill along with its possible variations. The extractor checks the résumé text against these variations to find matches.</p>
<p>Word boundaries are used during matching to avoid partial matches, such as matching “Java” inside “JavaScript”. Matched skills are stored in a set to prevent duplicates.</p>
<p>This approach ensures consistent and controlled skill detection across all résumés.</p>
<p><strong>File:</strong> <code>extractors/keyword_extractor.py</code></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">extract_skills</span>(<span class="hljs-params">self, text: str</span>) -&gt; Set[str]:</span>
    text_lower = text.lower()
    found_skills = set()

    <span class="hljs-keyword">for</span> category, skills_dict <span class="hljs-keyword">in</span> self.skills_taxonomy.items():
        <span class="hljs-keyword">for</span> skill_name, variations <span class="hljs-keyword">in</span> skills_dict.items():
            <span class="hljs-keyword">for</span> variation <span class="hljs-keyword">in</span> variations:
                <span class="hljs-comment"># Prevent "Java" matching "JavaScript"</span>
                pattern = <span class="hljs-string">r"\\b"</span> + re.escape(variation) + <span class="hljs-string">r"\\b"</span>
                <span class="hljs-keyword">if</span> re.search(pattern, text_lower):
                    found_skills.add(skill_name)
                    <span class="hljs-keyword">break</span>

    <span class="hljs-keyword">return</span> found_skills
</code></pre>
<h2 id="heading-step-4-implement-the-scoring-engine">Step 4: Implement the Scoring Engine</h2>
<p>To produce objective rankings, the system uses a weighted scoring formula.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Component</td><td>Weight</td><td>Rationale</td></tr>
</thead>
<tbody>
<tr>
<td>Required Skills</td><td>50%</td><td>Essential technical needs</td></tr>
<tr>
<td>Preferred Skills</td><td>25%</td><td>Competitive differentiators</td></tr>
<tr>
<td>Experience</td><td>15%</td><td>Professional depth</td></tr>
<tr>
<td>Keywords</td><td>10%</td><td>Domain familiarity</td></tr>
</tbody>
</table>
</div><pre><code class="lang-plaintext">Total Score =
(S_req × 0.50) +
(S_pref × 0.25) +
(E_exp × 0.15) +
(K_key × 0.10)
</code></pre>
<p>The scoring engine calculates a final score for each résumé using weighted values.</p>
<p>It counts how many required skills, preferred skills, experience indicators, and keywords appear in a résumé. Each count is multiplied by its assigned weight, with required skills contributing the most.</p>
<p>The weighted values are summed to produce a single score. Résumés are then sorted by this score to generate a ranked list of candidates.</p>
<h2 id="heading-step-5-build-the-web-interface">Step 5: Build the Web Interface</h2>
<p>Streamlit provides a simple web interface for interacting with the résumé screening system.</p>
<p>The text area allows users to input a job description, while the file uploader lets them upload multiple résumé files. When the button is clicked, Streamlit triggers the backend logic to parse résumés, extract data, and calculate scores.</p>
<p>The results are then displayed in the browser, allowing users to run the screening process without using the command line.</p>
<p><strong>File:</strong> <code>app.py</code></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> streamlit <span class="hljs-keyword">as</span> st

jd_text = st.text_area(
    <span class="hljs-string">"Paste the job description here:"</span>,
    height=<span class="hljs-number">300</span>
)

uploaded_files = st.file_uploader(
    <span class="hljs-string">"Upload resume files:"</span>,
    type=[<span class="hljs-string">"pdf"</span>, <span class="hljs-string">"docx"</span>, <span class="hljs-string">"txt"</span>],
    accept_multiple_files=<span class="hljs-literal">True</span>
)

<span class="hljs-keyword">if</span> st.button(<span class="hljs-string">"Screen Resumes"</span>, type=<span class="hljs-string">"primary"</span>):
    st.success(<span class="hljs-string">"Processing resumes..."</span>)
</code></pre>
<p>Run the application:</p>
<pre><code class="lang-bash">streamlit run app.py
</code></pre>
<p>The app will be available at <a target="_blank" href="http://localhost:8501/"><code>http://localhost:8500</code></a>.</p>
<h2 id="heading-step-6-test-the-system">Step 6: Test the System</h2>
<h3 id="heading-sample-job-description-input">Sample Job Description Input</h3>
<p>Below is an example of a job description you can use to test the system:</p>
<pre><code class="lang-plaintext">We are looking for a Senior Python Developer with strong experience in backend development.

Required Skills:
- Python
- Django
- REST APIs
- SQL

Preferred Skills:
- PostgreSQL
- Docker
- AWS

Experience:
- 3+ years of professional Python development
- Experience building web applications
</code></pre>
<p>This input helps the system identify required skills, preferred skills, and experience keywords, which are then used by the scoring engine to rank résumés.</p>
<pre><code class="lang-bash">python main.py
</code></pre>
<h3 id="heading-sample-output">Sample Output</h3>
<pre><code class="lang-plaintext">============================================================
SCREENING RESULTS
============================================================
Rank #1: Alice Johnson | Score: 85.42/100 | Matched: python, django, postgresql
Rank #2: Carol Davis   | Score: 72.50/100 | Matched: python, django
</code></pre>
<h2 id="heading-step-7-deploy-the-application">Step 7: Deploy the Application</h2>
<p>To make the system publicly accessible:</p>
<ol>
<li><p>Push the code to GitHub</p>
</li>
<li><p>Go to <a target="_blank" href="http://share.streamlit.io/"><code>share.streamlit.io</code></a></p>
</li>
<li><p>Select your <a target="_blank" href="http://app.py/"><code>app.py</code></a> file</p>
</li>
<li><p>Deploy the application</p>
</li>
</ol>
<p>Your app will be live at:</p>
<pre><code class="lang-plaintext">&lt;https://your-app-name.streamlit.app&gt;
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you’ve built a complete résumé screening system from scratch using Python. By combining text processing, structured scoring, and automation, this project demonstrates how manual résumé screening can be transformed into an efficient and objective workflow.</p>
<p>This system helps reduce bias, save time, and evaluate candidates more consistently. Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
