Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

7 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“¦ Job Scraper Pipeline

A modular, scalable ETL system for job scraping across Middle East job boards. Designed for Data Engineering & Python practice using real-world scraping and pipeline architecture.


GitHub Actions



πŸ”” Current Status

  • Status: Active development β€” latest work on Pydantic models, packaging, and Makefile.
  • Branch: chore/pydantic-packaging-makefile
  • Implemented: Project skeleton, modular extract/transform/load layers, example scrapers, and basic test scaffolding.
  • In Progress: Pydantic-based data models, packaging improvements (pyproject/packaging), Makefile updates, and CI integration.
  • Notes: This repository is actively developed; some features and tests may be incomplete. Run pytest -q locally and review requirements.txt before using in production.

πŸš€ Overview

This project is a production-ready job scraping pipeline organized into a clean ETL architecture:

Extract β†’ Transform β†’ Load β†’ Automate

You can scrape multiple job boards (Wuzzuf, GulfTalent, Bayt, etc.), clean and normalize the data, extract metadata (tags, salary, seniority), dedupe jobs, load into SQLite/CSV, and schedule daily runs.

The entire pipeline is fully modular, configurable, and extendable β€” every site scraper lives in its own file.


πŸ“‚ Project Structure

job-scraper/
β”œβ”€β”€ README.md
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ Makefile
β”œβ”€β”€ cli.py
β”‚
β”œβ”€β”€ extract/
β”‚   β”œβ”€β”€ base_scraper.py
β”‚   β”œβ”€β”€ wuzzuf.py
β”‚   β”œβ”€β”€ gulftalent.py
β”‚   β”œβ”€β”€ naukrigulf.py
β”‚   β”œβ”€β”€ tanqeeb.py
β”‚   β”œβ”€β”€ drjobs.py
β”‚   β”œβ”€β”€ bayt.py
β”‚   β”œβ”€β”€ laimoon.py
β”‚   β”œβ”€β”€ akhtaboot.py
β”‚   β”œβ”€β”€ example_site.py
β”‚   └── utils/
β”‚       β”œβ”€β”€ fetch.py
β”‚       β”œβ”€β”€ rate_limit.py
β”‚       β”œβ”€β”€ parse.py
β”‚       └── logger.py
β”‚
β”œβ”€β”€ transform/
β”‚   β”œβ”€β”€ normalize.py
β”‚   β”œβ”€β”€ clean_text.py
β”‚   β”œβ”€β”€ extract_metadata.py
β”‚   β”œβ”€β”€ dedupe.py
β”‚   └── text_normalization/
β”‚       β”œβ”€β”€ arabic.py
β”‚       β”œβ”€β”€ english.py
β”‚       β”œβ”€β”€ html.py
β”‚       └── unicode.py
β”‚
β”œβ”€β”€ load/
β”‚   β”œβ”€β”€ to_csv.py
β”‚   β”œβ”€β”€ to_sqlite.py
β”‚   β”œβ”€β”€ to_parquet.py
β”‚   β”œβ”€β”€ merge.py
β”‚   └── schema.py
β”‚
β”œβ”€β”€ pipeline/
β”‚   β”œβ”€β”€ runner.py
β”‚   β”œβ”€β”€ scheduler.py
β”‚   └── validation.py
β”‚
β”œβ”€β”€ core/
β”‚   β”œβ”€β”€ models.py
β”‚   β”œβ”€β”€ helpers.py
β”‚   └── exceptions.py
β”‚
β”œβ”€β”€ configs/
β”‚   β”œβ”€β”€ sites.yml
β”‚   └── rules/
β”‚       β”œβ”€β”€ salary.yml
β”‚       β”œβ”€β”€ seniority.yml
β”‚       └── tags.yml
β”‚
β”œβ”€β”€ data/
β”‚   β”œβ”€β”€ raw/
β”‚   β”œβ”€β”€ intermediate/
β”‚   β”œβ”€β”€ processed/
β”‚   └── logs/
β”‚
β”œβ”€β”€ metadata/
β”‚   β”œβ”€β”€ run_history.json
β”‚   β”œβ”€β”€ cache/
β”‚   └── mapping/
β”‚
└── scripts/
    └── run_pipeline.sh

πŸ›  Installation

1️⃣ Clone the repo

git clone https://github.com/husseini2000/job-scraper.git
cd job-scraper

2️⃣ Create a virtual environment

python -m venv env
source env/bin/activate        # Mac/Linux
env\Scripts\activate           # Windows

3️⃣ Install dependencies

pip install -r requirements.txt

Or if you're using Poetry:

poetry install

▢️ Quick Start

Run entire ETL pipeline

python cli.py run-all

Run per-stage

python cli.py extract
python cli.py transform
python cli.py load

Scrape one site

python cli.py extract --site wuzzuf

πŸ§ͺ Testing

pytest -q

🎯 Features

βœ… Modular scrapers

Each job site has its own Python scraper.

βœ… Config-driven

Enable/disable sites or adjust rate limits in:

configs/sites.yml

βœ… Strong Transform Layer

  • HTML & emoji cleaning
  • Arabic + English normalization
  • Salary extraction
  • Seniority detection
  • Skill tag extraction (Python, SQL, AWS, Airflow, etc.)
  • Duplicate job removal

βœ… Multiple Load Targets

  • CSV
  • SQLite
  • Parquet

βœ… Pipeline Automation

Use pipeline/runner.py or run via cron using:

scripts/run_pipeline.sh

🧭 Roadmap

This project is divided into phases to help build a strong, production-worthy pipeline.


🧱 **PHASE 0 β€” Foundation & Environment **

Goal: Prepare the project structure and development environment.

Tasks

βœ… Project Structure: Organized, professional layout

βœ… Virtual Environments: Isolated dependencies

βœ… Dependency Management: requirements.txt

βœ… Automation: Makefile for common tasks

βœ… Version Control: .gitignore and git basics

βœ… Testing: pytest with coverage

βœ… Data Models: Pydantic for validation

βœ… Code Quality: black, flake8, mypy setup


🐣 PHASE 1 β€” Core Engine & Utilities (2–3 days)

Goal: Create the shared engine for all scrapers.

Tasks

  • Implement utils (fetcher, rate limiter, logger)
  • Implement core models and helpers
  • Create configs/sites.yml

Output: Full scraper engine foundation.


🌐 PHASE 2 β€” First Scraper (Wuzzuf) + BaseScraper (3–4 days)

Build BaseScraper and implement Wuzzuf as the first complete scraper.

Output: Working Wuzzuf scraper.


🧹 PHASE 3 β€” Transform Layer (4–5 days)

Clean, normalize, extract metadata, dedupe.

Output: Standardized job objects.


πŸ›’ PHASE 4 β€” Load Layer (2–3 days)

CSV, SQLite, Parquet, merging, schema.

Output: jobs_raw.csv, jobs_clean.csv, jobs.db


🌍 PHASE 5 β€” Additional Scrapers (5–12 days)

GulfTalent, Tanqeeb, DrJobs, Bayt, NaukriGulf, Laimoon, Akhtaboot.


πŸ” PHASE 6 β€” CLI + Pipeline Runner (2–3 days)

One-command ETL workflow.


πŸ“Š PHASE 7 β€” Validation, Logging, Monitoring (1–2 days)

Add run history, validation, and clear error reporting.


πŸš€ PHASE 8 β€” Automation & Deployment (1 day)

Cron job automation + final polish.


❀️ Contributing

Pull requests are welcome β€” thank you for contributing! To make contributions easy to review and merge, please follow this short checklist:

  • Fork & Branch: Fork the repo and create a feature branch named feat/<short-desc> or fix/<short-desc>.
  • Sync: Rebase or merge the latest main (or master) before opening a PR.
  • Tests: Add or update tests for any new behavior and run pytest -q locally.
  • Type & Style: Ensure code passes linters and type checks (e.g., black, flake8, mypy if configured).
  • Docs: Update README.md or relevant docs when adding features or changing usage.
  • PR Description: Include a clear description, motivation, and any migration steps; reference any related issues.

If you're adding a scraper for a new job site, follow extract/example_site.py as a template and include a small sample output or fixture to help reviewers.


πŸ“œ License

MIT License.


About

Modular ETL pipeline for Middle East job boards

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages