Python automation for keeping an alumni tracker current without manually searching every profile.
The tool reads a Google Sheets alumni database, finds likely LinkedIn profile matches through configurable search APIs, scores candidate quality, and updates job-status fields only when confidence is high enough. Ambiguous matches are routed for human review instead of being written blindly.
Alumni databases get stale quickly, especially when job titles, companies, and locations change across hundreds of rows. This project turns a manual research workflow into a controlled data pipeline with review gates, dry-run support, and conservative update behavior.
- Finds LinkedIn candidates for alumni rows with missing, stale, or broken data.
- Scores candidates using name, school, department, and known company signals.
- Writes low-confidence matches to review columns instead of overwriting clean data.
- Scrapes high-confidence profiles for current company, role, location, and status.
- Preserves existing values when scraped fields are blank.
- Records row-level status, notes, and last-checked dates for repeatable follow-up.
- Python
- Google Sheets API via
gspread - Playwright browser automation
linkedin-scraper- SerpAPI, Google Custom Search, or Bing Web Search
python-dotenvfor local configuration
The script expects the main alumni table to use this layout:
| Column | Field |
|---|---|
H |
LinkedIn URL |
L |
Current status |
M |
Company / institution |
N |
Position / role |
O |
City / country |
S |
Data source |
T |
Updated date |
U:Z |
Automation status, confidence, notes, and review fields |
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python -m playwright install chromium
Copy-Item .env.example .envThen update .env with:
- Your Google Sheet ID.
- A Google Cloud service-account JSON path.
- At least one configured search provider key.
- A LinkedIn session file generated locally.
Create the LinkedIn browser session:
python .\create_linkedin_session.pyFind profile candidates without scraping:
python .\sync_alumni_linkedin.py --discover-only --limit 20Preview planned writes:
python .\sync_alumni_linkedin.py --dry-run --limit 20Process rows that are stale, missing, or broken:
python .\sync_alumni_linkedin.py --limit 20Re-check all valid alumni rows:
python .\sync_alumni_linkedin.py --force- Clean rows are skipped by default.
- Terminal states are not retried every run unless
--forceis used. - Low-confidence results are marked
NEEDS_REVIEW. - Failed rows get
ERRORplus notes for later diagnosis. - Local credentials and session files are excluded through
.gitignore.
This project demonstrates practical automation, API integration, data-quality controls, and stakeholder-aware workflow design. It was built for a real operations-style data maintenance problem where accuracy matters more than blind throughput.