Tested on : https://dsel.education.gov.in/careers/index.html -> vol 2 pdf (page 23-120)
This project converts a scanned career guidance PDF into structured JSON data that can be used by a React UI or any other application.
The current pipeline is:
Scanned PDF -> Page Images -> PaddleOCR -> Column-aware Parser -> careers_data.json
- Reads a scanned PDF career book.
- Converts every page into an image.
- Runs OCR using PaddleOCR.
- Uses OCR box coordinates to reduce multi-column text mixing.
- Extracts structured career data into JSON.
- Generates fields such as title, description, personality traits, education path, salary, scholarships, work environment, growth path, institutes, and example profile.
| File | Purpose |
|---|---|
ocr_pdf_to_json_extractor.py |
Main OCR and parsing script |
Enginnering.pdf |
Input PDF used for extraction |
careers_data.json |
Generated structured output |
CareerGuidanceUI.jsx |
React UI component for viewing/searching career data |
The latest run generated:
Total careers: 39
Descriptions: 39
Personality traits: 28
Education pathways: 38
Degrees: 39
Entrance exams: 39
Salary ranges: 37
Scholarships: 39
Work places: 36
Work descriptions: 38
Growth paths: 39
Government institutes: 39
Private institutes: 39
Some values still depend on OCR quality and page layout. The script keeps a raw_text field for every career so missing or imperfect structured fields can still be recovered.
This project was tested on Windows with:
- Python 3.12
- PaddleOCR 3.5
- PaddlePaddle GPU 3.2.0
- NVIDIA RTX 3050 4 GB
- CUDA 12.6 runtime from Paddle wheel
- Poppler for PDF-to-image conversion
uvfor creating the working Python environment
The original env folder used Python 3.14, but PaddlePaddle did not provide compatible wheels for Python 3.14. The working setup uses ocr-gpu-env with Python 3.12.
Open PowerShell in the project folder:
cd C:\Users\stiwa\Downloads\RoadmapRun the extractor:
$env:PADDLE_PDX_DISABLE_MODEL_SOURCE_CHECK='True'
@('Enginnering.pdf', '') | .\ocr-gpu-env\Scripts\python.exe ocr_pdf_to_json_extractor.pyThe second empty input uses the default PaddleOCR language, en.
After the script finishes, it writes:
careers_data.json
On the RTX 3050 4 GB setup, the full 98-page PDF run takes around 4-6 minutes.
The script intentionally runs OCR sequentially instead of using multiple OCR threads. This avoids GPU memory crashes on 4 GB VRAM cards.
Check that JSON was generated:
Get-Item careers_data.jsonCheck field coverage:
$data = Get-Content careers_data.json -Raw | ConvertFrom-Json
$careers = @($data.careers)
"Total: $($careers.Count)"
"Descriptions: $(@($careers | Where-Object { $_.description }).Count)"
"Traits: $(@($careers | Where-Object { $_.personality_traits.Count -gt 0 }).Count)"
"Education: $(@($careers | Where-Object { $_.education.pathways.Count -gt 0 }).Count)"
"Salary: $(@($careers | Where-Object { $_.salary_range.min -ne $null }).Count)"
"Institutes: $(@($careers | Where-Object { $_.institutes.government.Count -gt 0 }).Count)"CareerGuidanceUI.jsx expects career data in the same shape as careers_data.json.
In a React project, copy:
CareerGuidanceUI.jsxcareers_data.json
Then import and render the component according to your app structure.
- Keep the PDF in portrait orientation for best extraction.
- Multi-column pages are handled by coordinate-aware OCR sorting, but complex page layouts can still create noisy fields.
raw_textis intentionally preserved for every career so the data can be re-parsed later without rerunning OCR.