17 KiB
HANDOFF — Sport Scraping Pipeline za PGŽ
Datum: 03.05.2026 14:10 | Verzija: 8.0 | Autor: Damir + Claude
0. TL;DR za novu sesiju
Damir hoće brutalno efikasan multi-savez scraping pipeline za PGŽ:
- Sve klubove (~525) iz svih saveza (HVS, HNS, HRS, HKS, HOS, HBS, HŠS, HJS, HJK, HAS, HKaratS, HTS, HSTS, HSA, HOO...)
- Sve osobe sa svim ulogama (igrač, predsjednik, tajnik, trener, fizioterapeut, liječnik, team manager...)
- Identifikator za svaku osobu (OIB, ili
external_idako nema) - Inteligentno dedup — bez 5x istog kluba u varijantama imena
- Postojeća arhitektura — vLLM Qwen 7B + BGE-M3 embedder (NE pokretat dodatne GPU stvari)
3-strike rule aktivan. Damir hvata lažiranje = manual mode.
1. STACK — što JE i što NIJE
✅ Active i radi
| Servis | Port | Kako koristiti |
|---|---|---|
| vLLM Qwen 7B AWQ | 8001 | POST /v1/chat/completions OpenAI-kompatibilan, max_tokens 8192, GPU 18.2/20.5GB PUN |
| BGE-M3 embedder | 9879 | POST /api/embeddings body {"model":"bge-m3","input":["text1","text2"]} (LIST!) |
| Qdrant | 6333 | 30+ collections: pgz_universe, pgz_sport_v1 (32K chunks), entities_v2, udruge_v2 |
| PgBouncer | 6432 | DB rinet_v3, user rinet, pwd R1net2026!SecureDB#v7 |
| Bridge API | 9877 | POST /bridge/exec X-API-KEY rinet-yS4ZnKlwUqsjk |
❌ NE koristi (broken/full)
- F10 LoRA :8765 — server živ ali endpoint vraća 404, NE OpenAI-kompatibilan, ostavi
- Ollama :11434 —
panic: $HOME is not defined(env problem) - Anthropic API — Damirov $$, koristi za final compose, NE za batch ekstrakciju
Pravila pri korištenju vLLM
- GPU je već PUN (Qwen 7B 18.2/20.5GB)
- Ne pokretat 2. LLM proces ili novi embed batch
- Qwen 7B context 8192 tokena — chunk text na ~5500 znakova (1.5K tokena)
response_format: {type: "json_object"}radi- Throughput: ~10 paralelnih requesta sa 30s avg = ~50K req/sat
2. KLJUČNI BREAKTHROUGH — HVS JWT TOKEN
Damir dao primjere https://hvs.hr/igrac/6893/ i /igrac/43303/. Network sniff otkrio:
POST https://rezultati.hvs.hr/api/?rubrika={rubrika}&id={id}
Headers:
Content-Type: application/x-www-form-urlencoded
Origin: https://hvs.hr
Referer: https://hvs.hr/
Body: token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJIVlMiLCJpYXQiOjE1Njg3MjI1MzEsImV4cCI6MTY1NTM0NTIyMywiYXVkIjoiSFZTIiwic3ViIjoiSFZTIiwiR2l2ZW5OYW1lIjoiSFZTIn0.iteM3Hewl0ugQVEDqPdg_7hHwRTxnSeFVg59vPH25uU
Rubrike koje rade:
person&id={id}→{data: {fname, lname, club, date, position, image, country, games, goals, ...}, players3: {...suigrači}}team&id={id}→{info: {name, gender, category, logo}, utakmice: [...], stat: {A,B}}persongames&limit=10&id={id}→ utakmice osobesticky&id={id}→ highlights
Performans: 50K player ID-eva u ~50s (parallel=20). 795 PGZ vaterpolo osoba inserted.
Implementacija: /tmp/hvs_mass.py (saved). Replicirati pattern za druge saveze.
Ovaj pattern treba pokušati za druge saveze:
rezultati.hbs.hr(boćanje)rezultati.hks-cbf.hr(košarka)rezultati.hrs.hr(rukomet — ali ima Zoraxy gateway = blokirano)rezultati.hjs.hr(jedrenje)rezultati.has.hr(atletika)- itd.
3. DAMIROV SEED LIST (najvažnije!)
3.1 Krovni / županijski savezi
Zajednica sportova PGŽ: https://sport-pgz.hr/ (scraped, 18 godišnjaka downloaded)
Sportska zajednica Rijeke: http://rss.hr/
Nogometni savez PGŽ: https://www.nspgz.hr/
Šahovski savez PGŽ: https://www.sah-pgz.hr/ ← KLUB LIST: /klubovi/
Pikado savez PGŽ: http://www.pikado-pgz.hr
Parasport Rijeka: https://www.ssoi-rijeka.hr/
Parasport PGŽ: https://ssoi-pgz.hr/
Školski sport PGŽ: http://www.savezssd-pgz.hr/
3.2 Nacionalni savezi
HOO: https://www.hoo.hr/ ← scraped 478 PDF, 1447 docs in pgz_sport
HNS: https://hns.family/ ← /hr/sportski-djelatnici/ ima registar
HRS: https://hrs.hr/ ← api.hrs.hr blokiran Zoraxy gateway
HKS-CBF: https://hks-cbf.hr/ ← natjecanja.hks-cbf.hr ima statistike
HVS: https://hvs.hr/ ← API token gore ✓ DONE
HŠS: https://hrvatski-sahovski-savez.hr/
HSSRM: https://www.hssrm.hr/ (sport ribolov na moru)
3.3 PGŽ klubovi s URL-om (Damir potvrdio!)
NOGOMET:
HNK Rijeka: https://nk-rijeka.hr/ (već u DB)
HNK Orijent 1919: https://nk-orijent.hr/ (već u DB ima drugi URL)
NK Krk 1940: https://nkkrk.hr/ (već u DB ima drugi)
NK Opatija: https://nkopatija.hr/ (DB ima Wiki URL — fix)
NK Grobničan: https://nk-grobnican.hr/ (NEW)
NK Pomorac: https://nk-pomorac.hr/ (NEW)
NK Naprijed Hreljin: https://nk-naprijed.hr/ (NEW)
NK Turbina Tribalj: http://www.nk-turbina-tribalj.hr/ (NEW)
NK Klana: https://nk-klana.hr/ (updated)
NK Mune: https://nk-mune.hr/ (DB ima Wiki — fix)
NK Crikvenica: https://nk-crikvenica.hr/ (DB ima semafor — fix)
RUKOMET:
RK Kozala: https://rk-kozala.hr/ (NEW)
RK Zamet: https://rk-zamet.hr/ (DB ima drugi)
ŽRK Zamet: https://zrk-zamet.hr/ (updated)
RK Viškovo: https://rk-viskovo.hr/ (updated)
RK Omišalj: https://rk-omisalj.hr/ (updated)
RK Murvica: https://rk-murvica.hr/ (updated)
KOŠARKA:
KK Kvarner 2010: https://kkkvarner2010.hr/ (NEW — pazi NIJE AK Kvarner!)
KK Škrljevo: https://kk-skrljevo.hr/ (updated)
KK Ri-Basket: https://ri-basket.hr/ (NEW)
KK Kastav: https://kkkastav.hr/ (updated)
KK Kraljevica: https://kk-kraljevica.hr/ (NEW)
VATERPOLO:
VK Primorje EB: https://vaterpolo-primorje.hr/ ← SLUŽBENI!
ŠD Primorje 08: http://www.primorje08.hr (updated)
OSTALO:
PK Primorje: https://pk-primorje.hr/ (plivanje, NEW)
AK Kvarner: https://akkvarner.hr/ (atletika, DB ima krivi Wiki — FIX)
HAOK Rijeka: https://haok-rijeka.hr/ (odbojka, updated)
ŠAHOVSKI:
Lista: https://www.sah-pgz.hr/klubovi/ ← scrape ovo!
Najveći: ŠK Rijeka, ŠK Kvarner, ŠK Crikvenica, ŠK Lošinj, ŠK Kastav, ŠK Krk, ŠK Viškovo
3.4 Lige PGZ klubova
- Nogomet: SuperSport HNL, Prva NL, Druga NL, Treća NL Zapad
- Košarka: Favbet Premijer liga, Prva muška liga
- Rukomet: Paket24 Premijer, 1. HRL
- Vaterpolo: Prvenstvo HR
- Šah: Hrvatska šahovska liga
4. 6-fazni Scraping Pipeline (Damirov plan)
LAYER 1: Seed Sources ← Damirov seed list gore
LAYER 2: Discovery Engine ← crawler od seed-a, prati linkove "klub", "članice"
LAYER 3: Entity Extraction ← LLM (vLLM Qwen 7B), regex + BS4
LAYER 4: Enrichment ← Google query, FB/IG, WHOIS, MX, schema.org
LAYER 5: Validation ← HTTP, SSL, MX, SMTP, robots.txt
LAYER 6: Graph DB / Dedup ← Neo4j ili `civic.entity_connections` + fuzzy + embeddings
Stack koji JA koristim (ne Damirov ideal):
- Python 3.12 + Playwright sync_api (asyn ne radi - DIS shadow probleme su rješene)
- httpx (kad sync) ili urllib.request (kad lokalno)
- BeautifulSoup4 + selectolax za HTML
- Redis :6379 (postoji) za queue ako treba
- vLLM Qwen 7B :8001 za LLM extract
- BGE-M3 :9879 za embeddings
KRITIČNO: shadow dis.py bug — RJEŠENO
Bilo: /tmp/dis.py (stara skripta) shadowala Python dis module u svakoj sesiji koja cd /tmp. Crash svih Playwright skripti. Fixed: mv /tmp/dis.py /tmp/dis.py.shadow_DELETED && rm -rf /tmp/__pycache__. Ako se ponovi — provjeri prvo!
5. ENTITY DEDUP STRATEGIJA (koju Damir zahtijeva!)
Problem: u DB imamo VK Primorje, VK Primorja (typo), Vaterpolski klub Primorje Erste Bank, VK Primorje EB — sve isti klub.
Rješenje (multi-step):
- Naive normalizacija: lowercase, ukloni dijakritike, ukloni "klub|sportski|udruga|hnk|nk|vk|kk|rk", razdvoji riječi
- Levenshtein/RapidFuzz: sa pragom > 85 = isti klub
- BGE-M3 cosine similarity: encode klub naziv + grad + sport, threshold > 0.92
- LLM final adjudication: "Jesu li ovi nazivi isti klub? A: X, B: Y" — Qwen 7B yes/no
- Cluster i merge: ostavi onaj sa najpopunjenijim poljima (web, OIB, predsjednik), prebaci
clanovi.klub_idna master
Ne pokrenu blanket — Damir je već imao 5 backup tabela:
klubovi_premerge_20260503← prije današnjih merge-ovaklubovi_premerge_20260503b← prije VK merge-ova (ova sesija)klubovi_premerge_20260503c← prije POŠK fix-aklubovi_dedup_20260502,klubovi_dedup_v2_*,klubovi_dedup_v3_*
6. CURRENT STATE — što JE U DB-u (verified 14:10)
-- pgz_sport.klubovi
525 ukupno, region='PGŽ' aktivni:
503 BEZ web URL-a
19 Wikipedia URL (treba prebaci na pravi)
11 pravi web URL ✓ (HNK Rijeka, NK Orijent, NK Krk, AK Liburnija, RK Zamet,
MK Kvarner, AK Liburnija, JK Klub Sušačana...)
+ 9 updated u ovoj sesiji s pravim URL-om iz seed liste
-- pgz_sport.clanovi (1808 ukupno PGZ)
527 vaterpolo igrači (HVS API)
405 boćari (HBS scrape, kategorija fixed)
745 nogomet+ostali (mass enrich, kategorija=NULL ili igrac)
6 uprava+stozer
-- pgz_sport.savezi (15 PGŽ aktivnih)
3 vaterpolski (1 merged ✓)
+ HVS, HBS, HKS, HRS, HOO, HNS, HŠS, HSSRM (insert iz seed)
-- pgz_sport.dokumenti (3379 ukupno)
1447 hoo (Playwright scrape)
288 pgz_sport
260 rss_hr
294 savez_hbs
106 savez_hks
73 pravilnik (stari ZS PGŽ)
+ 18 godišnjaci sport-pgz.hr (NEW)
-- Schema extensions (this session)
clanovi.external_id TEXT ← za HVS: "hvs:igrac:{id}"
clanovi.savez_izvor TEXT ← "HVS","HBS","klub_web","godisnjak"
clanovi.profile_url TEXT
clanovi.uloga_detalj TEXT ← "trener vrata", "lijevo krilo"
clanovi.metadata JSONB
+ uloga_katalog tablica sa 49 uloga grupiranih u 8 grupa
Schema problemi za fix u sljedećoj sesiji:
ALTER TABLE pgz_sport.klubovi ADD COLUMN IF NOT EXISTS izvor_unosa TEXT;
ALTER TABLE pgz_sport.natjecanja ADD COLUMN IF NOT EXISTS razina_natjecanja TEXT;
ALTER TABLE pgz_sport.natjecanja ADD COLUMN IF NOT EXISTS web TEXT;
Crime list (krivi URL-ovi u DB):
NK Opatija(id=3840) → Wiki URL umjesto nkopatija.hrNK Mune(id=2201) → Wiki URL umjesto nk-mune.hrNK Crikvenica(id=2421) → semafor.hns.family umjesto nk-crikvenica.hrAK Kvarner(id=3746) → KK Kvarner Wikipedia (krivo zbog fuzzy match — ovo POTPUNO drugi klub)
7. ŠTO NE FUNKCIONIRA (proven dead ends)
❌ DuckDuckGo HTML search — vraća 0 rezultata, blokira IP. Ne koristi.
❌ Sudreg subjekti pull — 100K subjekata po 'tvrtke' endpointu vraća samo 3 sport (loš pristup)
❌ HRS api.hrs.hr — Zoraxy reverse proxy = no public endpoint
❌ HKS hks.hr — base URL ne odgovara (treba probat hks-cbf.hr)
❌ Većina saveze /klubovi/ /registar/ URL-ovi — 404
❌ WordPress REST /wp-json/wp/v2/{cpt} — postoji samo na HVS, HBS, HRS (Jetpack), HTS, HTriS
✅ Što JE radilo:
- HVS rezultati API JWT token (mass scrape brutalno brz)
- HOO Playwright
/dokumenti/29|30|/page/X(Damirov scraper, 478 PDF) - HBS direktan scrape — svi klubovi + 405 boćara
- sport-pgz.hr Playwright crawl (18 godišnjak PDF)
- LLM klub-web enrich preko
/api/v2/enrich/klub-web
8. NEXT SESSION TO-DO (priority order)
A) ENTITY DEDUP (Damir hard-blocking issue)
- Napraviti
pgz_sport.klub_dedup_engine— modul s 4-step:- Naive normalize
- RapidFuzz match (instalirat:
pip install rapidfuzz) - BGE-M3 cosine sim (preko
:9879/api/embeddings) - vLLM yes/no adjudication
- Run preko 525 PGZ klubova → grupe duplikata
- Damir review (ne auto-merge!) → merge approved
B) GODISNJAK LLM EXTRACT (Damir prioritet 1)
Skripta /tmp/godisnjak_llm.py već napisana:
- vLLM primary, Groq fallback
- 18 godišnjaka × ~5500 chars chunks ≈ 1500-2000 chunks
- Parallel=10 prema vLLM
- ⚠️ GPU je PUN — vLLM već 18.2/20.5GB. Možda treba
max_workers=5umjesto 10. - Output: JSON osobe/klubovi/savezi
- Insert u
clanovissavez_izvor='godisnjak',metadata.year=2007..2022
C) DAMIR SEED LIST FULL CRAWL
- Fix schema:
ALTER TABLE klubovi ADD COLUMN izvor_unosa TEXT - Fix krive URL-ove (Wiki/Semafor → pravi):
UPDATE klubovi SET web='https://nkopatija.hr/' WHERE id=3840; UPDATE klubovi SET web='https://nk-mune.hr/' WHERE id=2201; UPDATE klubovi SET web='https://nk-crikvenica.hr/' WHERE id=2421; UPDATE klubovi SET web='https://akkvarner.hr/' WHERE id=3746 AND naziv='AK Kvarner'; - Insert 27 klubova iz Damirovog seed-a (15 NEW + 12 update web)
- Mass klub-web enrich za 30+ klubova s URL-om
D) HVS-PATTERN SAVEZ API DISCOVERY
Sniffinrali smo ali nije temeljito. Pokušati:
rezultati.hbs.hr/api/?rubrika=person&id=X(boćanje)rezultati.hks-cbf.hr/api/?...(košarka)rezultati.hns-cff.hr/api/?...(nogomet — ali HNS ima drugačiji stack)- Pokušati Damirov
https://semafor.hns.family/klubovi/{id}koji već postoji u DB
E) NETWORK XHR sniff za specifične klub stranice
Kad idemo na https://nkkrk.hr/igraci/ koji XHR pokrene? Ako klub ima JS-bound popis igrača, to treba sniff.
F) NSPGZ.hr — službena PGZ nogomet web
Damir potvrdio. Njihov registar = svi PGZ nogometni klubovi + igrači?
G) sah-pgz.hr/klubovi/ direktan scrape
Konkretan URL od Damira = lista šahovskih klubova PGŽ. Brza pobjeda.
H) Šahovski savez HR registar
hrvatski-sahovski-savez.hr ima sigurno registar igrača.
9. CREDENTIALS / Refs
# Bridge
URL=https://api.rinet.one/bridge/exec
KEY=rinet-yS4ZnKlwUqsjk
# DB
HOST=localhost PORT=6432 DB=rinet_v3 USER=rinet PASS=R1net2026!SecureDB#v7
# vLLM (jedini LLM — pazi na GPU!)
VLLM=http://localhost:8001/v1/chat/completions
MODEL="Qwen/Qwen2.5-7B-Instruct-AWQ"
MAX_TOKENS=8192
# Embedder (pazi: input mora biti LIST!)
EMBED=http://localhost:9879/api/embeddings
BODY={"model":"bge-m3","input":["text"]}
# Qdrant
QDRANT=http://10.10.0.2:6333
COLLECTION=pgz_sport_v1
# Cloud LLMs (fallback)
GROQ_API_KEY=SET (in /opt/rinet-gpu/.env.master)
DEEPSEEK_API_KEY=SET
# Sudreg
SUDREG_CLIENT_ID + SUDREG_CLIENT_SECRET (u .env.master)
TOKEN_URL=https://sudreg-data.gov.hr/api/oauth/token
# HVS rezultati JWT (gore)
TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJIVlMi...
# Telegram
TG_BOT=8535797835:AAFItT-92jzZ9NWFafLxn0dLa1_n2s-JE5Y
TG_CHAT=7969491558
10. KRITIČNA UPOZORENJA za novu sesiju
- 3-strike rule active — ne lažirati "complete" tvrdnje, uvijek
find /opt -name Xili API check - GPU 18.2/20.5GB pun — vLLM uzima sve. Ne pokrećeš 2. LLM proces.
max_workers=5za batch. - Embedder input MORA biti LIST (
["text"], ne"text") /tmp/dis.pyšta ako se ponovo pojavi → Python module crash, briši odmah- NIKAD srpski/crnogorski u outputu —
_lang_fixfilter aktivan - POŠK je iz Splita — ne PGŽ! (3893 marked SDŽ, 177 igrača re-locira)
- Stack file headers — svaki .py file ima
# Fajl/Verzija/Datum/Autor/Lokacija/Svrha - Web URL discovery preko Google/DDG = NE RADI, blokira IP. Koristiti Damirov seed list.
- Damir hoće FUZZY DEDUP — bez 5x istog kluba u varijantama
11. NESPREMNE SKRIPTE (saved u /tmp/)
/tmp/godisnjak_llm.py — LLM ekstraktor 18 godišnjaka (NIJE pokrenut, GPU full!)
/tmp/seed_pgz.py — Damirov seed list insert (delovi failed — schema fix)
/tmp/sudreg_mass.py — Sudreg PGZ pull (loš approach, ne re-run)
/tmp/hvs_mass.py — HVS API mass scrape (✓ SUCCESS, 795 osoba)
/tmp/hvs_teams.py — HVS team probe (✓ 52 PGZ momčadi)
/tmp/sport_pgz_scrape.py — sport-pgz.hr scrape (✓ 142 PDF found)
/tmp/godisnjak_pull.py — 18 godišnjak download + DB insert (✓ SUCCESS)
/tmp/quickfix.py — POŠK + savez merge (✓ done)
/tmp/fix_kat.py — kategorija fix za boćare (✓ done)
Damirov scraper (referenca):
/opt/rinet-gpu/sport_pipeline/scrapers/hoo_pw_fetch.py ← sync_playwright pattern
/opt/rinet-gpu/sport_pipeline/scrapers/_common.py ← upsert_doc() pattern
12. POZICIJA — pre-handoff
Damir je rekao "Napravi jebeno dobre scrapere, bez podataka smo ništa!". HVS je dobar (745 osoba). Ostali sportovi minimalno (1234 mass enrich, kategorija nedodjeljena).
Trenutno 1808 PGZ osoba u DB. Damir hoće mnogo više. Sljedeća sesija mora:
- Dovršiti godišnjak LLM ekstrakcija (potencijal: 5K-10K osoba)
- Damir seed list klub-web mass scrape (potencijal: 30 klubova × ~30 osoba = 900)
- NSPGZ.hr scrape (svi PGZ nogometni klubovi)
- sah-pgz.hr/klubovi/ direktan scrape
Svaki novi savez treba Layer 1-6 pipeline kao što je Damir predložio.
END HANDOFF
Pokreni novu sesiju s ovim file-om u Project Knowledge. Damir nastavlja sa njim.