SPB Git

spb/airiskindex Public

The most methodologically rigorous, fully transparent AI job-exposure index.

TypeScript 88% Python 6.1% SQL 2.7% CSS 1.2% JavaScript 0.9% Shell 0.8%
1.6 KB · 51 lines python
Raw Blame History
1#  File:    download_oews.py2#  Path:    apps/etl/src/airiskindex_etl/download_oews.py3#  Project: AI Risk Index — airiskindex.io4#  Author:  Simon-Pierre Boucher5#  Contact: contact@spboucher.ai6#  Copyright © 2026 Simon-Pierre Boucher. All rights reserved.7#8#  Description: Fetch BLS OEWS national wage data into data/raw/oews/.910"""Fetch BLS OEWS national wage data (May 2025) into data/raw/oews/.1112BLS blocks non-browser user agents — a descriptive UA with contact info works.13Source: https://www.bls.gov/oes/tables.htm (docs/research/02-data-sources.md).14"""1516from __future__ import annotations1718import sys19import zipfile20from pathlib import Path2122import requests2324OEWS_URL = "https://www.bls.gov/oes/special-requests/oesm25nat.zip"25USER_AGENT = "Mozilla/5.0 (compatible; airiskindex-etl/0.1; +https://www.airiskindex.io)"2627REPO_ROOT = Path(__file__).resolve().parents[4]28RAW_DIR = REPO_ROOT / "data" / "raw" / "oews"293031def download() -> Path:32    RAW_DIR.mkdir(parents=True, exist_ok=True)33    archive = RAW_DIR / "oesm25nat.zip"34    if not archive.exists():35        print(f"downloading {OEWS_URL}")36        response = requests.get(OEWS_URL, headers={"User-Agent": USER_AGENT}, timeout=300)37        response.raise_for_status()38        archive.write_bytes(response.content)39    with zipfile.ZipFile(archive) as zf:40        zf.extractall(RAW_DIR)41    print(f"extracted to {RAW_DIR}")42    return archive434445if __name__ == "__main__":46    try:47        download()48    except requests.RequestException as error:49        print(f"download failed: {error}", file=sys.stderr)50        sys.exit(1)51