# File: download_oews.py # Path: apps/etl/src/airiskindex_etl/download_oews.py # Project: AI Risk Index — airiskindex.io # Author: Simon-Pierre Boucher # Contact: contact@spboucher.ai # Copyright © 2026 Simon-Pierre Boucher. All rights reserved. # # Description: Fetch BLS OEWS national wage data into data/raw/oews/. """Fetch BLS OEWS national wage data (May 2025) into data/raw/oews/. BLS blocks non-browser user agents — a descriptive UA with contact info works. Source: https://www.bls.gov/oes/tables.htm (docs/research/02-data-sources.md). """ from __future__ import annotations import sys import zipfile from pathlib import Path import requests OEWS_URL = "https://www.bls.gov/oes/special-requests/oesm25nat.zip" USER_AGENT = "Mozilla/5.0 (compatible; airiskindex-etl/0.1; +https://www.airiskindex.io)" REPO_ROOT = Path(__file__).resolve().parents[4] RAW_DIR = REPO_ROOT / "data" / "raw" / "oews" def download() -> Path: RAW_DIR.mkdir(parents=True, exist_ok=True) archive = RAW_DIR / "oesm25nat.zip" if not archive.exists(): print(f"downloading {OEWS_URL}") response = requests.get(OEWS_URL, headers={"User-Agent": USER_AGENT}, timeout=300) response.raise_for_status() archive.write_bytes(response.content) with zipfile.ZipFile(archive) as zf: zf.extractall(RAW_DIR) print(f"extracted to {RAW_DIR}") return archive if __name__ == "__main__": try: download() except requests.RequestException as error: print(f"download failed: {error}", file=sys.stderr) sys.exit(1)