"""TÜİK Yükseköğretim İstihdam Göstergeleri Excel'lerinden src/lib/bolum-istihdam.ts sabitini üretir. Kullanım (yılda bir, TÜİK bülteni Temmuz'da yayımlayınca): python3 scripts/tuik-istihdam-uret.py 2025 Girdi: data/kaynak/tuik-istihdam-{lisans,onlisans}-bolum-{istihdam-orani,is-bulma-suresi,kazanc-gruplari}-.xls (veriportali.tuik.gov.tr → "Yükseköğretim İstihdam Göstergeleri, " bülteni → Tablolar; tarayıcıyla tek tek indirilir — portal komut satırını engelliyor ve art arda istekte boş sayfa dönüyor). Bağımlılık: xlrd. Kurallar: - Veri ÜLKE GENELİ ve bölüm bazındadır; üniversite kırılımı TÜİK'te yok. - Anahtar: /bolum/[slug] sayfa slug'ı (bolumBazAdi + turkishSlugify). Yalnız yokatlas.db'de sayfası olan bölümler yazılır; eşleşmeyenler ekrana basılır. Takma ad tablosu yok: eşleşmeyenler henüz mezun vermemiş yeni bölümler ya da bizde olmayan özel yetenek / kapanmış bölümlerdir. - "." = TÜİK'in yayımlamadığı hücre → null. Mezun sayısı medyanın altındaki bölümler tablolarda hiç yok. - Kazanç TL değil, TÜİK'in beş kademeli grubudur (Çok düşük … Çok yüksek). """ import re import sqlite3 import sys import unicodedata from pathlib import Path import xlrd KOK = Path(__file__).resolve().parent.parent YIL = sys.argv[1] if len(sys.argv) > 1 else "2025" BULTEN_URL = "https://veriportali.tuik.gov.tr/tr/press/58027" DUZEYLER = (("lisans", 0), ("onlisans", 1)) KAZANC_GRUPLARI = ("Çok düşük", "Düşük", "Orta", "Yüksek", "Çok yüksek") def slugify(s: str) -> str: # src/lib/slug.ts turkishSlugify ile aynı kural. s = s.replace("I", "ı").replace("İ", "i").lower() for a, b in [("ı", "i"), ("ş", "s"), ("ğ", "g"), ("ü", "u"), ("ö", "o"), ("ç", "c"), ("â", "a"), ("î", "i"), ("û", "u")]: s = s.replace(a, b) s = unicodedata.normalize("NFKD", s) s = re.sub(r"[̀-ͯ]", "", s) s = re.sub(r"[^a-z0-9]+", "-", s) return s.strip("-") def bolum_slug(isim: str) -> str: # src/lib/slug.ts bolumSayfaSlug ile aynı kural. return slugify(re.sub(r"\s+", " ", re.sub(r"\s*\([^)]*\)", "", isim)).strip()) def tr_satir(v) -> str: """Hücreler 'Türkçe\\r\\nEnglish' biçiminde; Türkçe satırı al.""" return str(v).replace("\r", "").split("\n")[0].strip() def tablo(duzey: str, ad: str) -> tuple[dict[str, tuple[str, object]], object]: """slug → (TÜİK adı, son yıl değeri) ve 'Toplam' satırının değeri.""" yol = KOK / "data" / "kaynak" / f"tuik-istihdam-{duzey}-bolum-{ad}-{YIL}.xls" s = xlrd.open_workbook(yol).sheet_by_index(0) baslik = next(r for r in range(s.nrows) if str(s.cell_value(r, 0)).startswith("Bölüm")) kolon = next(c for c in range(s.ncols) if str(s.cell_value(baslik, c)).startswith(YIL)) satirlar: dict[str, tuple[str, object]] = {} toplam = None for r in range(baslik + 1, s.nrows): bolum = tr_satir(s.cell_value(r, 0)) if not bolum or bolum.startswith(("TÜİK", "TurkStat", ".")): continue v = s.cell_value(r, kolon) if bolum == "Toplam": toplam = v continue satirlar[slugify(bolum)] = (bolum, v) return satirlar, toplam def sayi(v) -> float | None: return round(float(v), 1) if isinstance(v, (int, float)) else None def kazanc(v) -> str | None: g = tr_satir(v) if g in KAZANC_GRUPLARI: return g if g not in (".", ""): sys.exit(f"Bilinmeyen kazanç grubu: {g!r}") return None def ts(v) -> str: if v is None: return "null" return f'"{v}"' if isinstance(v, str) else str(v) db = sqlite3.connect(f"file:{KOK / 'data' / 'yokatlas.db'}?mode=ro", uri=True) bloklar: list[str] = [] ortalamalar: list[str] = [] for duzey, onlisans in DUZEYLER: sayfalar = {bolum_slug(i) for (i,) in db.execute("SELECT DISTINCT isim FROM programs WHERE onlisans = ?", (onlisans,))} oran, oran_toplam = tablo(duzey, "istihdam-orani") sure, sure_toplam = tablo(duzey, "is-bulma-suresi") kaz, _ = tablo(duzey, "kazanc-gruplari") hepsi = sorted(set(oran) | set(sure) | set(kaz)) eslesen = [k for k in hepsi if k in sayfalar] eslesmeyen = [(oran.get(k) or sure.get(k) or kaz[k])[0] for k in hepsi if k not in sayfalar] print(f"{duzey}: TÜİK {len(hepsi)} bölüm, sayfası olan {len(eslesen)}") if eslesmeyen: print(" sayfası olmayan (yazılmadı):", ", ".join(eslesmeyen)) satirlar = [] for k in eslesen: o = sayi(oran[k][1]) if k in oran else None s = sayi(sure[k][1]) if k in sure else None g = kazanc(kaz[k][1]) if k in kaz else None if o is None and s is None and g is None: continue satirlar.append(f' "{k}": {{ istihdam: {ts(o)}, isBulmaAy: {ts(s)}, kazanc: {ts(g)} }},') bloklar.append(f" {duzey}: {{\n" + "\n".join(satirlar) + "\n },") ortalamalar.append(f" {duzey}: {{ istihdam: {ts(sayi(oran_toplam))}, isBulmaAy: {ts(sayi(sure_toplam))} }},") cikti = f"""// TÜİK Yükseköğretim İstihdam Göstergeleri {YIL}: bölüm başına mezun istihdamı. // // ÜRETİLMİŞ DOSYA — elle düzenleme. Kaynak Excel'ler data/kaynak/ altında; // yeniden üretmek için: python3 scripts/tuik-istihdam-uret.py {YIL} // // Veri ÜLKE GENELİ ve bölüm bazındadır: aynı bölümün her üniversitesi için // aynı sayı döner; üniversite kırılımı TÜİK'te yok. Kayıtlı istihdam = mezunun // SGK kaydıyla çalışıyor olması. Kazanç TL değil, beş kademeli gruptur. // Anahtar: /bolum/[slug] sayfa slug'ı. Burada olmayan bölüm ya henüz yeterli // mezun vermemiştir ya da TÜİK tablosunda yoktur — "kötü" demek değildir. export const BOLUM_ISTIHDAM_YIL = {YIL}; export const BOLUM_ISTIHDAM_KAYNAK = "TÜİK, Yükseköğretim İstihdam Göstergeleri, {YIL}"; export const BOLUM_ISTIHDAM_KAYNAK_URL = "{BULTEN_URL}"; export type KazancGrubu = {" | ".join(f'"{g}"' for g in KAZANC_GRUPLARI)}; export type IstihdamDuzeyi = "lisans" | "onlisans"; export type BolumIstihdam = {{ /** Kayıtlı istihdam oranı (%) */ istihdam: number | null; /** Mezuniyetten sonra ilk işi bulma süresi (ay, ortalama) */ isBulmaAy: number | null; /** Aylık ortalama kazanç grubu (bölümler arası göreli) */ kazanc: KazancGrubu | null; }}; /** Tüm mezunların ortalaması — kıyas çizgisi. */ export const ISTIHDAM_ORTALAMA: Record = {{ {chr(10).join(ortalamalar)} }}; export const BOLUM_ISTIHDAM: Record> = {{ {chr(10).join(bloklar)} }}; /** Bölüm sayfa slug'ının TÜİK satırı; yoksa null. */ export function bolumIstihdamBul(slug: string, duzey: IstihdamDuzeyi): BolumIstihdam | null {{ return BOLUM_ISTIHDAM[duzey][slug] ?? null; }} """ (KOK / "src" / "lib" / "bolum-istihdam.ts").write_text(cikti, encoding="utf-8") print("yazıldı: src/lib/bolum-istihdam.ts")