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%
2.4 KB · 74 lines python
Raw Blame History
1#  File:    download_onet.py2#  Path:    apps/etl/src/airiskindex_etl/download_onet.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 the O*NET database text dump into data/raw/onet/.910"""Fetch the O*NET database text dump into data/raw/onet/ (immutable).1112O*NET 30.x — CC BY 4.0, attribution required. 30.x renamed13"Technology Skills" -> "Software Skills" and split Skills into14Essential/Transferable (see docs/research/02-data-sources.md §O*NET).15Check https://www.onetcenter.org/database.html for the current release16(31.0 expected late Aug 2026) before bumping ONET_VERSION.17"""1819from __future__ import annotations2021import hashlib22import json23import sys24import zipfile25from pathlib import Path2627import requests2829ONET_VERSION = "30_3"30ONET_URL = f"https://www.onetcenter.org/dl_files/database/db_{ONET_VERSION}_text.zip"3132# Some sources (notably BLS OEWS) block non-browser user agents; use a plain33# descriptive UA with contact info everywhere for consistency and courtesy.34USER_AGENT = "airiskindex-etl/0.1 (https://www.airiskindex.io; data pipeline)"3536REPO_ROOT = Path(__file__).resolve().parents[4]37RAW_DIR = REPO_ROOT / "data" / "raw" / "onet"383940def download() -> Path:41    RAW_DIR.mkdir(parents=True, exist_ok=True)42    archive = RAW_DIR / f"db_{ONET_VERSION}_text.zip"43    if archive.exists():44        print(f"already present: {archive}")45        return archive4647    print(f"downloading {ONET_URL}")48    response = requests.get(ONET_URL, headers={"User-Agent": USER_AGENT}, timeout=300, stream=True)49    response.raise_for_status()50    with archive.open("wb") as fh:51        for chunk in response.iter_content(chunk_size=1 << 20):52            fh.write(chunk)5354    with zipfile.ZipFile(archive) as zf:55        zf.extractall(RAW_DIR)5657    manifest = {58        "source": ONET_URL,59        "version": ONET_VERSION,60        "sha256": hashlib.sha256(archive.read_bytes()).hexdigest(),61        "files": sorted(p.name for p in RAW_DIR.iterdir()),62    }63    (RAW_DIR / "manifest.json").write_text(json.dumps(manifest, indent=2))64    print(f"downloaded and extracted to {RAW_DIR}")65    return archive666768if __name__ == "__main__":69    try:70        download()71    except requests.RequestException as error:72        print(f"download failed: {error}", file=sys.stderr)73        sys.exit(1)74