Nye-TeeOff/backend/scrape_golfamore1.2.py
2026-02-26 09:20:51 +01:00

110 lines
4.7 KiB
Python

import asyncio
import asyncpg
import httpx
from bs4 import BeautifulSoup
import re
import json
DB_URL = "postgresql://teeoff_admin:teeoff_secret_password@db:5432/teeoff"
def clean(text):
if not text: return ""
# Fjerner alt som ikke er bokstaver for å matche navn på tvers av systemer
return re.sub(r'[^a-z0-9]', '', text.lower().replace("golfklubb", "").replace("gk", "").replace(" og ", "").replace("&", ""))
async def scrape_golfamore():
print("\n******************************************")
print("🚀 GOLFAMORE ULTIMATE SYNC v1.2")
print("******************************************\n")
conn = await asyncpg.connect(DB_URL)
facilities = await conn.fetch("SELECT id, name FROM facilities")
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
}
async with httpx.AsyncClient(timeout=30.0, headers=headers, follow_redirects=True) as client:
print("🕵️ Henter baneliste fra Golfamore (Norge)...")
url = "https://www.golfamore.com/no/golfbaner/?country=NO"
resp = await client.get(url)
# 1. Finn alle klubb-lenker i kildekoden (omgår lazyload)
# Vi leter etter mønsteret "/no/golfklubb/navn-pa-klubb/"
all_slugs = re.findall(r'/no/golfklubb/([^/\"\s]+)/', resp.text)
found_links = list(set([f"https://www.golfamore.com/no/golfklubb/{s}/" for s in all_slugs]))
print(f"📍 Fant {len(found_links)} potensielle norske klubber i kildekoden.")
if not found_links:
print("❌ Klarte ikke å finne noen baner. Sjekk om Golfamore har endret URL-struktur.")
await conn.close()
return
# Lag et map for rask matching {vasket_navn: url}
link_map = {clean(l.split('/')[-2].replace('-', ' ')): l for l in found_links}
matches_found = 0
for fac in facilities:
fac_id = fac['id']
fac_name = fac['name']
fac_clean = clean(fac_name)
match_url = link_map.get(fac_clean)
# Prøv delvis match (f.eks "Arendal" i "Arendal og Omegn")
if not match_url:
for key, url in link_map.items():
if len(fac_clean) > 4 and (fac_clean in key or key in fac_clean):
match_url = url
break
if match_url:
try:
print(f"✅ Match: {fac_name}")
f_resp = await client.get(match_url)
soup = BeautifulSoup(f_resp.text, 'html.parser')
# Finn teksten om når kortet gjelder
# Vi leter etter div-er som inneholder "Gjelder"
validity = "Gjelder én gang pr. sesong."
# Golfamore bruker ofte en liste (ul/li) eller en spesifikk div for regler
rules_container = soup.find('div', class_=re.compile(r'rules|conditions|terms', re.I))
if not rules_container:
# Fallback: Let etter tekstblokken manuelt
for div in soup.find_all('div'):
if div.text and "Gjelder" in div.text and len(div.text) < 200:
validity = div.text.strip()
break
else:
validity = rules_container.get_text(separator=' ').strip()
# Vask teksten for linjeskift
validity = re.sub(r'\s+', ' ', validity).replace('"', '').strip()
ga_data = {
"url": match_url,
"validity": validity
}
await conn.execute("""
UPDATE facilities
SET golfamore = true, golfamore_data = $1
WHERE id = $2
""", json.dumps(ga_data), fac_id)
matches_found += 1
await asyncio.sleep(0.2) # Vær snill
except Exception as e:
print(f"⚠️ Feil ved parsing av {fac_name}: {e}")
await conn.execute("UPDATE facilities SET golfamore = true WHERE id = $1", fac_id)
else:
# Hvis ikke funnet, sett til false
await conn.execute("UPDATE facilities SET golfamore = false, golfamore_data = '{}' WHERE id = $1", fac_id)
await conn.close()
print(f"\n🎉 Ferdig! {matches_found} baner er nå synkronisert med Golfamore.")
if __name__ == "__main__":
asyncio.run(scrape_golfamore())