Files
pgz-sport/scrapers/harvesters/akademski_pgz.py
T
damir ae9c4e2bfd Sportski objekti: API + Leaflet map page + address enrichment
DB: pgz_sport.sportski_objekti (103 objekti, 103 s geo, 60 s adresom, 31 tip)

API:
- /api/v2/sportski-objekti (filter: tip, grad, sport, q)
- /api/v2/sportski-objekti/meta (tipovi, gradovi, sportovi, ukupno)

Frontend:
- /static/objekti.html — Leaflet (OpenStreetMap) interactive map
- 3 dropdown filter (tip, grad, sport) + search
- Side panel s listom + map markers s ikonama (🏟️🏊🎿🎳⛸️🎯🥌🏃)
- Popup: naziv, tip, kapacitet, adresa, upravitelj, izgradeno, sportovi, web link, Google Maps link
- /objekti, /sport/objekti, /sport/api/v2/sportski-objekti routes

Sidebar app.html: +Sportski objekti link
Background: scripts/objekti_enrich_address.py (Nominatim reverse-geocode 60 objekata bez adrese)
2026-05-05 18:35:04 +02:00

65 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""UNIRI akademski repozitorij + znanstveni radovi."""
import sys, json, time
sys.path.insert(0, "/opt/pgz-sport/scrapers/harvesters")
from _common import (fetch, extract_text, extract_title, chunk_text,
upsert_facts, find_internal_links, DSN)
from urllib.parse import urlparse
import psycopg2
ACADEMIC = {
"uniri_repozitorij": ["https://repozitorij.uniri.hr/"],
"portal_znanstveni": ["https://portal.uniri.hr/"],
"hrčak_uniri": ["https://hrcak.srce.hr/"],
"pfri_radovi": ["https://repository.pfri.uniri.hr/"],
"medri_radovi": ["https://medri.uniri.hr/znanstveni-radovi/"],
"tfr_radovi": ["https://www.riteh.uniri.hr/"],
"ffri_radovi": ["https://www.ffri.uniri.hr/znanstveni-radovi/"],
}
def crawl(name, urls, max_pages=15):
conn = psycopg2.connect(DSN); conn.autocommit = True
visited = set(); queue = list(urls); facts = 0
while queue and len(visited) < max_pages:
url = queue.pop(0)
if url in visited: continue
visited.add(url)
html, status = fetch(url, timeout=20)
if not html or status != 200: continue
title = extract_title(html); text = extract_text(html)
if not text or len(text) < 300: continue
ff = []
if title and len(title) > 15:
ff.append({"fact": f"[Academic] {name} - {title}", "url": url, "title": title})
for c in chunk_text(text, 900):
if len(c) > 150:
ff.append({"fact": c, "url": url, "title": title})
facts += upsert_facts(conn, ff, source_name=name,
category="akademski_pgz", confidence=0.90)
base = urlparse(url).hostname
for link in find_internal_links(html, url):
if link not in visited and (urlparse(link).hostname or "") == base and len(queue) < 40:
queue.append(link)
time.sleep(0.7)
conn.close()
return {"name": name, "visited": len(visited), "facts": facts}
def main():
results = []
for name, urls in ACADEMIC.items():
try:
r = crawl(name, urls, max_pages=12)
print(f" {name:25} {r['visited']:>3}p {r['facts']:>5}f")
results.append(r)
except Exception as e:
print(f" {name:25} FAIL: {str(e)[:60]}")
total = sum(r.get("facts", 0) for r in results)
print(f"=== TOTAL: {total} ===")
print(json.dumps({"academic_count": len(results), "total_facts": total}))
if __name__ == "__main__":
main()