Skip to content

Latest commit

Β 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎯 Job Hunter

Python Version Docker Playwright SQLite Telegram Bot API License: MIT

An automated, self-hosted job board monitoring system built with Python, Playwright, and SQLite. Job Hunter continuously tracks corporate career pages across global tech enterprises, filters new listings against your personal skill keywords and location preferences, and delivers instant alerts straight to your Telegram device.


🌟 Key Features

  • πŸ”Œ 9+ Built-in Scraper Engines: Native API clients and DOM parsers for major ATS platforms:
    • Greenhouse (JSON API)
    • Workday (REST API / Search endpoints)
    • Lever (Posting API)
    • SmartRecruiters (Public Job API)
    • Eightfold AI (API pagination)
    • Workable (Board API)
    • Phenom People (Careers Search API)
    • XML Sitemap Crawler (Automated job link discovery)
    • Generic Headless Scraper (Playwright Chromium for dynamic JavaScript single-page apps)
  • 🎯 Advanced Multi-Layer Filtering:
    • Keyword Include/Exclude: Match relevant roles (e.g. embedded systems, FPGA, firmware) while filtering out noise (e.g. frontend, sales).
    • Geographic Filtering: Restrict job postings to selected countries (e.g. Western/Southern Europe) or allow remote/global roles.
  • 🧠 Smart Deduplication & History:
    • SQLite database persists unique job fingerprints (url + title + company) so you never get notified twice for the same opening.
  • πŸ“² Telegram Notifications & Interactive Bot:
    • Rich Markdown notifications sent in batches.
    • Interactive bot polling: add new companies on the fly using /add <Company> <URL> directly from Telegram!
  • 🐳 Docker-First & Low Footprint:
    • Production-ready Docker Compose container with memory capping (1GB max), non-root user permissions, volume persistence, and automatic healthchecks.
  • πŸ”’ 100% Private & Open Source:
    • Zero telemetry or 3rd-party tracking. All scraped data and credentials stay on your server.

πŸ—οΈ Architecture & Workflow

             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
             β”‚       APScheduler (Runs every N hours)       β”‚
             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
                                    β–Ό
             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
             β”‚      Scraper Engine Dispatcher (src/)        β”‚
             β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚               β”‚               β”‚
                    β–Ό               β–Ό               β–Ό
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚ ATS APIs (JSON)  β”‚   β”‚ XML Sitemaps β”‚   β”‚ Playwright Head- β”‚
      β”‚ Greenhouse/Lever β”‚   β”‚   Crawler    β”‚   β”‚ less Chromium    β”‚
      β”‚ Workday/Eightfold    β”‚              β”‚   β”‚ (JS Dynamic Apps)β”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚               β”‚               β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
                                    β–Ό
             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
             β”‚       SQLite Database (data/jobs.db)         β”‚
             β”‚       (Deduplication & Fingerprinting)       β”‚
             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚ New jobs only
                                    β–Ό
             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
             β”‚     Filter Engine (src/filters.py)           β”‚
             β”‚   (Keyword Include/Exclude & Geo Check)      β”‚
             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚ Matched jobs
                                    β–Ό
             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
             β”‚      Telegram Bot API & Interactive Poll     β”‚
             β”‚    - Real-time Notifications                 β”‚
             β”‚    - `/add <Company> <URL>` command          β”‚
             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ› οΈ Supported Scraper Engines

Engine Type Sample URL Format Description
greenhouse REST API https://boards.greenhouse.io/company Official Greenhouse Job Board API.
lever REST API https://jobs.lever.co/company Official Lever Postings API.
workday REST API https://company.wd3.myworkdayjobs.com/... Workday external job board API.
smartrecruiters REST API https://api.smartrecruiters.com/v1/companies/... SmartRecruiters public API.
eightfold REST API https://company.eightfold.ai/careers Eightfold AI candidate portal API.
workable REST API https://apply.workable.com/company/ Workable postings API.
phenom REST API https://careers.company.com/jobs Phenom People careers API.
sitemap XML Crawler https://www.company.com/sitemap.xml Parses XML sitemaps for job detail URLs.
generic Headless Browser https://company.com/careers Playwright Chromium engine for SPA/React/Angular career portals.

πŸš€ Quick Start (Docker)

Prerequisites

1. Clone the Repository

git clone https://github.com/your-username/job-hunter.git
cd job-hunter

2. Configure Environment Variables

Copy the template environment file:

cp .env.example .env

Edit .env to supply your Telegram credentials:

TELEGRAM_BOT_TOKEN=123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ
TELEGRAM_CHAT_ID=987654321
SCAN_INTERVAL_HOURS=6
LOG_LEVEL=INFO

How to create a Telegram Bot:

  1. Message @BotFather on Telegram and send /newbot.
  2. Follow the prompt to get your Bot Token.
  3. Start a chat with your bot, then get your Chat ID by visiting: https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates (or use @userinfobot).

3. Configure Target Companies

Copy the example companies template and edit config/companies.yml to specify the companies and ATS scrapers you wish to monitor:

cp config/companies.example.yml config/companies.yml

Example configuration (config/companies.yml):

companies:
  - name: Example Tech
    country: Italy
    careers_url: https://example.eightfold.ai/careers
    scraper: eightfold
    company_id: exampletech

  - name: NXP Semiconductors
    country: Netherlands
    careers_url: https://nxp.wd3.myworkdayjobs.com/careers
    scraper: workday
    company_id: nxp
    workday_tenant: nxp
    workday_instance: wd3

  - name: Exein
    careers_url: https://job-boards.eu.greenhouse.io/exeinspa
    scraper: greenhouse
    company_id: exeinspa

4. Configure Search Filters

Copy the example filters template and edit config/filters.yml to specify desired keywords and allowed locations:

cp config/filters.example.yml config/filters.yml

Example configuration (config/filters.yml):

include_keywords:
  - hardware engineer
  - embedded systems
  - firmware developer
  - fpga design
  - pcb layout

exclude_keywords:
  - frontend developer
  - web developer
  - sales manager

allowed_countries:
  - Italy
  - Germany
  - Netherlands
  - France
  - Switzerland

5. Build and Launch Container

# Build the Docker image
docker compose build

# Start in detached (background) mode
docker compose up -d

Check the logs in real time:

docker compose logs -f

πŸ€– Interactive Telegram Bot Commands

Once running, Job Hunter listens for commands in your Telegram chat:

  • /help β€” Displays available commands and bot status.
  • /add <Company Name> <Careers URL> β€” Dynamically registers a new company to config/companies.yml. The bot auto-detects the ATS platform (Workday, Greenhouse, Lever, Eightfold, Workable, Phenom, SmartRecruiters) and includes it in the next scan cycle!

Example:

/add Acme Corp https://boards.greenhouse.io/acmecorp

βš™οΈ Configuration Reference

Directory Overview

job-hunter/
β”œβ”€β”€ Dockerfile              # Python 3.12-slim + Playwright Chromium image
β”œβ”€β”€ docker-compose.yml      # Service setup with volume persistence & resource limits
β”œβ”€β”€ requirements.txt        # Dependencies (Playwright, httpx, APScheduler, PyYAML)
β”œβ”€β”€ .env.example            # Environment variables template
β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ companies.example.yml # Template for target companies config
β”‚   β”œβ”€β”€ filters.example.yml   # Template for keyword & location filter rules
β”‚   β”œβ”€β”€ companies.yml         # User target companies (ignored by Git)
β”‚   └── filters.yml           # User search filters (ignored by Git)
β”œβ”€β”€ data/
β”‚   └── jobs.db             # Persistent SQLite database (auto-created)
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.py             # Entry point
β”‚   β”œβ”€β”€ config.py           # Configuration loader & validation
β”‚   β”œβ”€β”€ database.py         # SQLite persistence & query operations
β”‚   β”œβ”€β”€ models.py           # Data structures (Job model)
β”‚   β”œβ”€β”€ filters.py          # Keyword & geographic filtering logic
β”‚   β”œβ”€β”€ telegram.py         # Telegram notifications & bot polling engine
β”‚   β”œβ”€β”€ scheduler.py        # APScheduler orchestration loop
β”‚   └── scrapers/           # Modular ATS scraper implementations
β”‚       β”œβ”€β”€ base.py
β”‚       β”œβ”€β”€ generic.py
β”‚       β”œβ”€β”€ greenhouse.py
β”‚       β”œβ”€β”€ lever.py
β”‚       β”œβ”€β”€ workday.py
β”‚       β”œβ”€β”€ smartrecruiters.py
β”‚       β”œβ”€β”€ eightfold.py
β”‚       β”œβ”€β”€ workable.py
β”‚       β”œβ”€β”€ phenom.py
β”‚       β”œβ”€β”€ sitemap.py
β”‚       └── registry.py
└── tests/                  # Unit and integration test suite

πŸ’» Local Development & Testing

If you prefer to run Job Hunter natively without Docker:

1. Python Environment Setup

# Prerequisites: Python 3.12+
python -m venv venv

# On Linux/macOS:
source venv/bin/activate
# On Windows (PowerShell):
.\venv\Scripts\Activate.ps1

# Install requirements
pip install -r requirements.txt

# Install Playwright browser binaries
playwright install chromium

2. Run the Application

python -m src.main

3. Run Test Suite

Job Hunter comes with a comprehensive test suite covering scrapers, filtering logic, and database operations.

# Run tests
python -m pytest tests/ -v

# Run tests with coverage report
python -m pytest tests/ -v --cov=src --cov-report=term-missing

☁️ Deployment Guide (VPS / Server)

You can host Job Hunter 24/7 on any cheap Linux VPS (Hetzner, DigitalOcean, AWS EC2, Linode, Scaleway).

Ubuntu/Debian Setup

# 1. Update system & install Docker
sudo apt update && sudo apt install -y docker.io docker-compose-plugin git

# 2. Clone repository to /opt
sudo git clone https://github.com/your-username/job-hunter.git /opt/job-hunter
cd /opt/job-hunter

# 3. Configure env & config files
cp .env.example .env
nano .env

# 4. Start Docker container
docker compose build
docker compose up -d

# 5. Enable autostart on boot
sudo systemctl enable docker

πŸ—„οΈ Database Management & Backup

All jobs are tracked in data/jobs.db. The SQLite database is mounted outside the container for seamless data persistence.

Inspect Database Records

# Query recent jobs via sqlite3
sqlite3 data/jobs.db "SELECT company, title, location, first_seen_at FROM jobs ORDER BY first_seen_at DESC LIMIT 10;"

# Count discovered jobs per company
sqlite3 data/jobs.db "SELECT company, COUNT(*) FROM jobs GROUP BY company ORDER BY COUNT(*) DESC;"

Create Backup

# Backup SQLite database
cp data/jobs.db "data/jobs_backup_$(date +%Y%m%d).db"

🀝 Adding a Custom Scraper Engine

Job Hunter's scraper architecture is modular and extensible. To add support for a new ATS or career site platform:

  1. Create a new file in src/scrapers/my_platform.py:
from src.models import Job
from src.scrapers.base import BaseScraper

class MyPlatformScraper(BaseScraper):
    def scrape(self) -> list[Job]:
        # Implement fetching & parsing logic
        jobs = []
        # ... fetch jobs ...
        return jobs
  1. Register your class in src/scrapers/registry.py:
from src.scrapers.my_platform import MyPlatformScraper

# Add to _get_scrapers() dictionary:
"my_platform": MyPlatformScraper,
  1. Specify scraper: my_platform in config/companies.yml.

πŸ›‘οΈ Security & Privacy

  • No Third-Party Analytics: Job Hunter sends data only to the official Telegram Bot API endpoint (https://api.telegram.org).
  • Secrets & Configuration Protection: .env, custom configuration files (config/companies.yml, config/filters.yml), and SQLite database files (data/*.db) are explicitly ignored by Git (.gitignore).
  • Least Privilege: The Docker container executes under a non-root system user (appuser).

πŸ“„ License

Distributed under the MIT License. See LICENSE for more information.

About

A Telegram bot to help you find the perfect job

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages